Skip to content

Commit ea6b818

Browse files
Jeff BrownAndroid (Google) Code Review
authored andcommitted
Merge "Improve ANR diagnostics." into jb-dev
2 parents ae20ae1 + 265f1cc commit ea6b818

File tree

3 files changed

+134
-46
lines changed

3 files changed

+134
-46
lines changed

core/java/android/view/Choreographer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@ void doFrame(long frameTimeNanos, int frame) {
493493
if (jitterNanos >= mFrameIntervalNanos) {
494494
final long skippedFrames = jitterNanos / mFrameIntervalNanos;
495495
if (skippedFrames >= SKIPPED_FRAME_WARNING_LIMIT) {
496-
Log.w(TAG, "Skipped " + skippedFrames + " frames! "
496+
Log.i(TAG, "Skipped " + skippedFrames + " frames! "
497497
+ "The application may be doing too much work on its main thread.");
498498
}
499499
final long lastFrameOffset = jitterNanos % mFrameIntervalNanos;

services/input/InputDispatcher.cpp

Lines changed: 124 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@
5656

5757
#define INDENT " "
5858
#define INDENT2 " "
59+
#define INDENT3 " "
60+
#define INDENT4 " "
5961

6062
namespace android {
6163

@@ -78,6 +80,9 @@ const nsecs_t STALE_EVENT_TIMEOUT = 10000 * 1000000LL; // 10sec
7880
// queue of waiting unfinished events, then ANRs will similarly be delayed by one second.
7981
const nsecs_t STREAM_AHEAD_EVENT_TIMEOUT = 500 * 1000000LL; // 0.5sec
8082

83+
// Log a warning when an event takes longer than this to process, even if an ANR does not occur.
84+
const nsecs_t SLOW_EVENT_PROCESSING_WARNING_TIMEOUT = 2000 * 1000000LL; // 2sec
85+
8186

8287
static inline nsecs_t now() {
8388
return systemTime(SYSTEM_TIME_MONOTONIC);
@@ -897,11 +902,11 @@ int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,
897902
const EventEntry* entry,
898903
const sp<InputApplicationHandle>& applicationHandle,
899904
const sp<InputWindowHandle>& windowHandle,
900-
nsecs_t* nextWakeupTime) {
905+
nsecs_t* nextWakeupTime, const char* reason) {
901906
if (applicationHandle == NULL && windowHandle == NULL) {
902907
if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY) {
903908
#if DEBUG_FOCUS
904-
ALOGD("Waiting for system to become ready for input.");
909+
ALOGD("Waiting for system to become ready for input. Reason: %s", reason);
905910
#endif
906911
mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY;
907912
mInputTargetWaitStartTime = currentTime;
@@ -912,8 +917,9 @@ int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,
912917
} else {
913918
if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
914919
#if DEBUG_FOCUS
915-
ALOGD("Waiting for application to become ready for input: %s",
916-
getApplicationWindowLabelLocked(applicationHandle, windowHandle).string());
920+
ALOGD("Waiting for application to become ready for input: %s. Reason: %s",
921+
getApplicationWindowLabelLocked(applicationHandle, windowHandle).string(),
922+
reason);
917923
#endif
918924
nsecs_t timeout;
919925
if (windowHandle != NULL) {
@@ -946,7 +952,7 @@ int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,
946952

947953
if (currentTime >= mInputTargetWaitTimeoutTime) {
948954
onANRLocked(currentTime, applicationHandle, windowHandle,
949-
entry->eventTime, mInputTargetWaitStartTime);
955+
entry->eventTime, mInputTargetWaitStartTime, reason);
950956

951957
// Force poll loop to wake up immediately on next iteration once we get the
952958
// ANR response back from the policy.
@@ -1017,13 +1023,11 @@ int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
10171023
// then drop the event.
10181024
if (mFocusedWindowHandle == NULL) {
10191025
if (mFocusedApplicationHandle != NULL) {
1020-
#if DEBUG_FOCUS
1021-
ALOGD("Waiting because there is no focused window but there is a "
1022-
"focused application that may eventually add a window: %s.",
1023-
getApplicationWindowLabelLocked(mFocusedApplicationHandle, NULL).string());
1024-
#endif
10251026
injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
1026-
mFocusedApplicationHandle, NULL, nextWakeupTime);
1027+
mFocusedApplicationHandle, NULL, nextWakeupTime,
1028+
"Waiting because no window has focus but there is a "
1029+
"focused application that may eventually add a window "
1030+
"when it finishes starting up.");
10271031
goto Unresponsive;
10281032
}
10291033

@@ -1040,21 +1044,18 @@ int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
10401044

10411045
// If the currently focused window is paused then keep waiting.
10421046
if (mFocusedWindowHandle->getInfo()->paused) {
1043-
#if DEBUG_FOCUS
1044-
ALOGD("Waiting because focused window is paused.");
1045-
#endif
10461047
injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
1047-
mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime);
1048+
mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime,
1049+
"Waiting because the focused window is paused.");
10481050
goto Unresponsive;
10491051
}
10501052

10511053
// If the currently focused window is still working on previous events then keep waiting.
10521054
if (!isWindowReadyForMoreInputLocked(currentTime, mFocusedWindowHandle, entry)) {
1053-
#if DEBUG_FOCUS
1054-
ALOGD("Waiting because focused window still processing previous input.");
1055-
#endif
10561055
injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
1057-
mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime);
1056+
mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime,
1057+
"Waiting because the focused window has not finished "
1058+
"processing the input events that were previously delivered to it.");
10581059
goto Unresponsive;
10591060
}
10601061

@@ -1210,11 +1211,9 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
12101211
// it is invisible) then wait for it. Any other focused window may in
12111212
// fact be in ANR state.
12121213
if (topErrorWindowHandle != NULL && newTouchedWindowHandle != topErrorWindowHandle) {
1213-
#if DEBUG_FOCUS
1214-
ALOGD("Waiting because system error window is pending.");
1215-
#endif
12161214
injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
1217-
NULL, NULL, nextWakeupTime);
1215+
NULL, NULL, nextWakeupTime,
1216+
"Waiting because a system error window is about to be displayed.");
12181217
injectionPermission = INJECTION_PERMISSION_UNKNOWN;
12191218
goto Unresponsive;
12201219
}
@@ -1241,14 +1240,11 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
12411240
// but not yet put up a window and the user is starting to get impatient.
12421241
if (maskedAction == AMOTION_EVENT_ACTION_DOWN
12431242
&& mFocusedApplicationHandle != NULL) {
1244-
#if DEBUG_FOCUS
1245-
ALOGD("Waiting because there is no touched window but there is a "
1246-
"focused application that may eventually add a new window: %s.",
1247-
getApplicationWindowLabelLocked(
1248-
mFocusedApplicationHandle, NULL).string());
1249-
#endif
12501243
injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
1251-
mFocusedApplicationHandle, NULL, nextWakeupTime);
1244+
mFocusedApplicationHandle, NULL, nextWakeupTime,
1245+
"Waiting because there is no touchable window that can "
1246+
"handle the event but there is focused application that may "
1247+
"eventually add a new window when it finishes starting up.");
12521248
goto Unresponsive;
12531249
}
12541250

@@ -1412,21 +1408,18 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
14121408
if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
14131409
// If the touched window is paused then keep waiting.
14141410
if (touchedWindow.windowHandle->getInfo()->paused) {
1415-
#if DEBUG_FOCUS
1416-
ALOGD("Waiting because touched window is paused.");
1417-
#endif
14181411
injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
1419-
NULL, touchedWindow.windowHandle, nextWakeupTime);
1412+
NULL, touchedWindow.windowHandle, nextWakeupTime,
1413+
"Waiting because the touched window is paused.");
14201414
goto Unresponsive;
14211415
}
14221416

14231417
// If the touched window is still working on previous events then keep waiting.
14241418
if (!isWindowReadyForMoreInputLocked(currentTime, touchedWindow.windowHandle, entry)) {
1425-
#if DEBUG_FOCUS
1426-
ALOGD("Waiting because touched window still processing previous input.");
1427-
#endif
14281419
injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
1429-
NULL, touchedWindow.windowHandle, nextWakeupTime);
1420+
NULL, touchedWindow.windowHandle, nextWakeupTime,
1421+
"Waiting because the touched window has not finished "
1422+
"processing the input events that were previously delivered to it.");
14301423
goto Unresponsive;
14311424
}
14321425
}
@@ -1897,6 +1890,7 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
18971890
while (connection->status == Connection::STATUS_NORMAL
18981891
&& !connection->outboundQueue.isEmpty()) {
18991892
DispatchEntry* dispatchEntry = connection->outboundQueue.head;
1893+
dispatchEntry->deliveryTime = currentTime;
19001894

19011895
// Publish the event.
19021896
status_t status;
@@ -3099,7 +3093,65 @@ void InputDispatcher::dumpDispatchStateLocked(String8& dump) {
30993093
dump.append(INDENT "MonitoringChannels: <none>\n");
31003094
}
31013095

3102-
dump.appendFormat(INDENT "InboundQueue: length=%u\n", mInboundQueue.count());
3096+
nsecs_t currentTime = now();
3097+
3098+
if (!mInboundQueue.isEmpty()) {
3099+
dump.appendFormat(INDENT "InboundQueue: length=%u\n", mInboundQueue.count());
3100+
for (EventEntry* entry = mInboundQueue.head; entry; entry = entry->next) {
3101+
dump.append(INDENT2);
3102+
entry->appendDescription(dump);
3103+
dump.appendFormat(", age=%01.1fms\n",
3104+
(currentTime - entry->eventTime) * 0.000001f);
3105+
}
3106+
} else {
3107+
dump.append(INDENT "InboundQueue: <empty>\n");
3108+
}
3109+
3110+
if (!mConnectionsByFd.isEmpty()) {
3111+
dump.append(INDENT "Connections:\n");
3112+
for (size_t i = 0; i < mConnectionsByFd.size(); i++) {
3113+
const sp<Connection>& connection = mConnectionsByFd.valueAt(i);
3114+
dump.appendFormat(INDENT2 "%d: channelName='%s', windowName='%s', "
3115+
"status=%s, monitor=%s, inputPublisherBlocked=%s\n",
3116+
i, connection->getInputChannelName(), connection->getWindowName(),
3117+
connection->getStatusLabel(), toString(connection->monitor),
3118+
toString(connection->inputPublisherBlocked));
3119+
3120+
if (!connection->outboundQueue.isEmpty()) {
3121+
dump.appendFormat(INDENT3 "OutboundQueue: length=%u\n",
3122+
connection->outboundQueue.count());
3123+
for (DispatchEntry* entry = connection->outboundQueue.head; entry;
3124+
entry = entry->next) {
3125+
dump.append(INDENT4);
3126+
entry->eventEntry->appendDescription(dump);
3127+
dump.appendFormat(", targetFlags=0x%08x, resolvedAction=%d, age=%01.1fms\n",
3128+
entry->targetFlags, entry->resolvedAction,
3129+
(currentTime - entry->eventEntry->eventTime) * 0.000001f);
3130+
}
3131+
} else {
3132+
dump.append(INDENT3 "OutboundQueue: <empty>\n");
3133+
}
3134+
3135+
if (!connection->waitQueue.isEmpty()) {
3136+
dump.appendFormat(INDENT3 "WaitQueue: length=%u\n",
3137+
connection->waitQueue.count());
3138+
for (DispatchEntry* entry = connection->waitQueue.head; entry;
3139+
entry = entry->next) {
3140+
dump.append(INDENT4);
3141+
entry->eventEntry->appendDescription(dump);
3142+
dump.appendFormat(", targetFlags=0x%08x, resolvedAction=%d, "
3143+
"age=%01.1fms, wait=%01.1fms\n",
3144+
entry->targetFlags, entry->resolvedAction,
3145+
(currentTime - entry->eventEntry->eventTime) * 0.000001f,
3146+
(currentTime - entry->deliveryTime) * 0.000001f);
3147+
}
3148+
} else {
3149+
dump.append(INDENT3 "WaitQueue: <empty>\n");
3150+
}
3151+
}
3152+
} else {
3153+
dump.append(INDENT "Connections: <none>\n");
3154+
}
31033155

31043156
if (isAppSwitchPendingLocked()) {
31053157
dump.appendFormat(INDENT "AppSwitch: pending, due in %01.1fms\n",
@@ -3214,6 +3266,7 @@ void InputDispatcher::onDispatchCycleFinishedLocked(
32143266
CommandEntry* commandEntry = postCommandLocked(
32153267
& InputDispatcher::doDispatchCycleFinishedLockedInterruptible);
32163268
commandEntry->connection = connection;
3269+
commandEntry->eventTime = currentTime;
32173270
commandEntry->seq = seq;
32183271
commandEntry->handled = handled;
32193272
}
@@ -3231,12 +3284,12 @@ void InputDispatcher::onDispatchCycleBrokenLocked(
32313284
void InputDispatcher::onANRLocked(
32323285
nsecs_t currentTime, const sp<InputApplicationHandle>& applicationHandle,
32333286
const sp<InputWindowHandle>& windowHandle,
3234-
nsecs_t eventTime, nsecs_t waitStartTime) {
3287+
nsecs_t eventTime, nsecs_t waitStartTime, const char* reason) {
32353288
ALOGI("Application is not responding: %s. "
3236-
"%01.1fms since event, %01.1fms since wait started",
3289+
"It has been %01.1fms since event, %01.1fms since wait started. Reason: %s",
32373290
getApplicationWindowLabelLocked(applicationHandle, windowHandle).string(),
32383291
(currentTime - eventTime) / 1000000.0,
3239-
(currentTime - waitStartTime) / 1000000.0);
3292+
(currentTime - waitStartTime) / 1000000.0, reason);
32403293

32413294
CommandEntry* commandEntry = postCommandLocked(
32423295
& InputDispatcher::doNotifyANRLockedInterruptible);
@@ -3308,12 +3361,22 @@ void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
33083361
void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(
33093362
CommandEntry* commandEntry) {
33103363
sp<Connection> connection = commandEntry->connection;
3364+
nsecs_t finishTime = commandEntry->eventTime;
33113365
uint32_t seq = commandEntry->seq;
33123366
bool handled = commandEntry->handled;
33133367

33143368
// Handle post-event policy actions.
33153369
DispatchEntry* dispatchEntry = connection->findWaitQueueEntry(seq);
33163370
if (dispatchEntry) {
3371+
nsecs_t eventDuration = finishTime - dispatchEntry->deliveryTime;
3372+
if (eventDuration > SLOW_EVENT_PROCESSING_WARNING_TIMEOUT) {
3373+
String8 msg;
3374+
msg.appendFormat("Window '%s' spent %01.1fms processing the last input event: ",
3375+
connection->getWindowName(), eventDuration * 0.000001f);
3376+
dispatchEntry->eventEntry->appendDescription(msg);
3377+
ALOGI("%s", msg.string());
3378+
}
3379+
33173380
bool restartEvent;
33183381
if (dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) {
33193382
KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
@@ -3656,6 +3719,10 @@ InputDispatcher::ConfigurationChangedEntry::ConfigurationChangedEntry(nsecs_t ev
36563719
InputDispatcher::ConfigurationChangedEntry::~ConfigurationChangedEntry() {
36573720
}
36583721

3722+
void InputDispatcher::ConfigurationChangedEntry::appendDescription(String8& msg) const {
3723+
msg.append("ConfigurationChangedEvent()");
3724+
}
3725+
36593726

36603727
// --- InputDispatcher::DeviceResetEntry ---
36613728

@@ -3667,6 +3734,10 @@ InputDispatcher::DeviceResetEntry::DeviceResetEntry(nsecs_t eventTime, int32_t d
36673734
InputDispatcher::DeviceResetEntry::~DeviceResetEntry() {
36683735
}
36693736

3737+
void InputDispatcher::DeviceResetEntry::appendDescription(String8& msg) const {
3738+
msg.appendFormat("DeviceResetEvent(deviceId=%d)", deviceId);
3739+
}
3740+
36703741

36713742
// --- InputDispatcher::KeyEntry ---
36723743

@@ -3685,6 +3756,11 @@ InputDispatcher::KeyEntry::KeyEntry(nsecs_t eventTime,
36853756
InputDispatcher::KeyEntry::~KeyEntry() {
36863757
}
36873758

3759+
void InputDispatcher::KeyEntry::appendDescription(String8& msg) const {
3760+
msg.appendFormat("KeyEvent(action=%d, deviceId=%d, source=0x%08x)",
3761+
action, deviceId, source);
3762+
}
3763+
36883764
void InputDispatcher::KeyEntry::recycle() {
36893765
releaseInjectionState();
36903766

@@ -3718,6 +3794,11 @@ InputDispatcher::MotionEntry::MotionEntry(nsecs_t eventTime,
37183794
InputDispatcher::MotionEntry::~MotionEntry() {
37193795
}
37203796

3797+
void InputDispatcher::MotionEntry::appendDescription(String8& msg) const {
3798+
msg.appendFormat("MotionEvent(action=%d, deviceId=%d, source=0x%08x)",
3799+
action, deviceId, source);
3800+
}
3801+
37213802

37223803
// --- InputDispatcher::DispatchEntry ---
37233804

@@ -3728,7 +3809,7 @@ InputDispatcher::DispatchEntry::DispatchEntry(EventEntry* eventEntry,
37283809
seq(nextSeq()),
37293810
eventEntry(eventEntry), targetFlags(targetFlags),
37303811
xOffset(xOffset), yOffset(yOffset), scaleFactor(scaleFactor),
3731-
resolvedAction(0), resolvedFlags(0) {
3812+
deliveryTime(0), resolvedAction(0), resolvedFlags(0) {
37323813
eventEntry->refCount += 1;
37333814
}
37343815

0 commit comments

Comments
 (0)