From db46d6b0744d286efc6ad6df600e15285868c2ab Mon Sep 17 00:00:00 2001 From: riddle_hsu Date: Wed, 1 Apr 2015 18:58:07 +0800 Subject: [PATCH] [ActivityManager] Reduce report wrong anr activity Symptom: Report ANR on wrong activity. Reproduce steps: (All launchMode, taskAffinity are default and without additional intent flag) Case 1: 1.Launch activity A from launcher. 2.Activity A starts B activity. 3.Press home key. 4.Launch activity A from launcher (B is top). 5.Press back key twice to finish B and A, A sleep 10s in onResume. 6.ANR will report on launcher. Case 2: 1.Launch activity A from launcher. 2.Press home key. 3.Kill process of A. 4.Launch activity A from launcher. 5.A sleep 10s in onResume, press back key immediately. 6.ANR will report on launcher. Possible root cause: Focused activity will not be updated every time when activity resumed. (the condition to call setFocusedActivityLocked) Case 1: Launcher was stopped and not waitingVisible due to launcher is not the previous one, then getWaitingHistoryRecordLocked has no chance to correct the real ANR activity. Case 2: Due to process of next activity is died, bring existed task will not set mResumedActivity (it will be set when its process is started), so when assigning waitingVisible from processStoppingActivitiesLocked, the return value of allResumedActivitiesVisible will be true even there is no mResumedActivity. That results set waitingVisible to false to previous activity (e.g. launcher), then also cannot correct ANR target as case 1. Change-Id: I0b24f46a8fab266382ebc6e2ed84ebeca9358768 --- .../com/android/server/am/ActivityRecord.java | 21 ++++++++----------- .../server/am/ActivityStackSupervisor.java | 10 ++++++--- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index b1b2a5cbda3c9..1497c1d408002 100755 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -982,24 +982,21 @@ final class ActivityRecord { } private ActivityRecord getWaitingHistoryRecordLocked() { - // First find the real culprit... if we are waiting - // for another app to start, then we have paused dispatching - // for this activity. - ActivityRecord r = this; - if (r.waitingVisible) { + // First find the real culprit... if this activity is waiting for + // another activity to start or has stopped, then the key dispatching + // timeout should not be caused by this. + if (waitingVisible || stopped) { final ActivityStack stack = mStackSupervisor.getFocusedStack(); - // Hmmm, who might we be waiting for? - r = stack.mResumedActivity; + // Try to use the one which is closest to top. + ActivityRecord r = stack.mResumedActivity; if (r == null) { r = stack.mPausingActivity; } - // Both of those null? Fall back to 'this' again - if (r == null) { - r = this; + if (r != null) { + return r; } } - - return r; + return this; } public boolean keyDispatchingTimedOut(String reason) { diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 27c5404e9fa4d..8ab2368a3949e 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -607,17 +607,21 @@ public final class ActivityStackSupervisor implements DisplayListener { } boolean allResumedActivitiesVisible() { + boolean foundResumed = false; for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { ArrayList stacks = mActivityDisplays.valueAt(displayNdx).mStacks; for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { final ActivityStack stack = stacks.get(stackNdx); final ActivityRecord r = stack.mResumedActivity; - if (r != null && (!r.nowVisible || r.waitingVisible)) { - return false; + if (r != null) { + if (!r.nowVisible || r.waitingVisible) { + return false; + } + foundResumed = true; } } } - return true; + return foundResumed; } /**