Skip to content

Commit 265f1cc

Browse files
author
Jeff Brown
committed
Improve ANR diagnostics.
When an ANR occurs, log the associated reason. When an event takes too long to process (currently more than 2 seconds) log basic information about the event including how long it actually took. Dump the contents of the inbound, outbound and wait queues as part of dumpsys input. Bug: 6574842 Change-Id: I9ab754c320f609cb86fe266c469a61e7032dfed6
1 parent 68cefd2 commit 265f1cc

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)