diff options
6 files changed, 41 insertions, 18 deletions
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index fc6d30bf58c9..1e3f69fc173b 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -6684,6 +6684,10 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public void appNotResponding(final String reason) { + appNotResponding(reason, /*isContinuousAnr*/ false); + } + + public void appNotResponding(final String reason, boolean isContinuousAnr) { TimeoutRecord timeoutRecord = TimeoutRecord.forApp("App requested: " + reason); final int callingPid = Binder.getCallingPid(); @@ -6696,7 +6700,7 @@ public class ActivityManagerService extends IActivityManager.Stub } mAnrHelper.appNotResponding(app, null, app.info, null, null, false, - timeoutRecord); + timeoutRecord, isContinuousAnr); } } @@ -18325,7 +18329,8 @@ public class ActivityManagerService extends IActivityManager.Stub } } mAnrHelper.appNotResponding(proc, activityShortComponentName, aInfo, - parentShortComponentName, parentProcess, aboveSystem, timeoutRecord); + parentShortComponentName, parentProcess, aboveSystem, timeoutRecord, + /*isContinuousAnr*/ true); } return true; diff --git a/services/core/java/com/android/server/am/AnrHelper.java b/services/core/java/com/android/server/am/AnrHelper.java index 71c80ea4f045..463a2f84aa6b 100644 --- a/services/core/java/com/android/server/am/AnrHelper.java +++ b/services/core/java/com/android/server/am/AnrHelper.java @@ -96,13 +96,13 @@ class AnrHelper { void appNotResponding(ProcessRecord anrProcess, TimeoutRecord timeoutRecord) { appNotResponding(anrProcess, null /* activityShortComponentName */, null /* aInfo */, null /* parentShortComponentName */, null /* parentProcess */, - false /* aboveSystem */, timeoutRecord); + false /* aboveSystem */, timeoutRecord, /*isContinuousAnr*/ false); } void appNotResponding(ProcessRecord anrProcess, String activityShortComponentName, ApplicationInfo aInfo, String parentShortComponentName, WindowProcessController parentProcess, boolean aboveSystem, - TimeoutRecord timeoutRecord) { + TimeoutRecord timeoutRecord, boolean isContinuousAnr) { try { timeoutRecord.mLatencyTracker.appNotRespondingStarted(); final int incomingPid = anrProcess.mPid; @@ -132,7 +132,7 @@ class AnrHelper { timeoutRecord.mLatencyTracker.anrRecordPlacingOnQueueWithSize(mAnrRecords.size()); mAnrRecords.add(new AnrRecord(anrProcess, activityShortComponentName, aInfo, parentShortComponentName, parentProcess, aboveSystem, - mAuxiliaryTaskExecutor, timeoutRecord)); + mAuxiliaryTaskExecutor, timeoutRecord, isContinuousAnr)); } startAnrConsumerIfNeeded(); } finally { @@ -230,10 +230,12 @@ class AnrHelper { final boolean mAboveSystem; final ExecutorService mAuxiliaryTaskExecutor; final long mTimestamp = SystemClock.uptimeMillis(); + final boolean mIsContinuousAnr; AnrRecord(ProcessRecord anrProcess, String activityShortComponentName, ApplicationInfo aInfo, String parentShortComponentName, WindowProcessController parentProcess, boolean aboveSystem, - ExecutorService auxiliaryTaskExecutor, TimeoutRecord timeoutRecord) { + ExecutorService auxiliaryTaskExecutor, TimeoutRecord timeoutRecord, + boolean isContinuousAnr) { mApp = anrProcess; mPid = anrProcess.mPid; mActivityShortComponentName = activityShortComponentName; @@ -243,6 +245,7 @@ class AnrHelper { mParentProcess = parentProcess; mAboveSystem = aboveSystem; mAuxiliaryTaskExecutor = auxiliaryTaskExecutor; + mIsContinuousAnr = isContinuousAnr; } void appNotResponding(boolean onlyDumpSelf) { @@ -250,7 +253,8 @@ class AnrHelper { mTimeoutRecord.mLatencyTracker.anrProcessingStarted(); mApp.mErrorState.appNotResponding(mActivityShortComponentName, mAppInfo, mParentShortComponentName, mParentProcess, mAboveSystem, - mTimeoutRecord, mAuxiliaryTaskExecutor, onlyDumpSelf); + mTimeoutRecord, mAuxiliaryTaskExecutor, onlyDumpSelf, + mIsContinuousAnr); } finally { mTimeoutRecord.mLatencyTracker.anrProcessingEnded(); } diff --git a/services/core/java/com/android/server/am/AppNotRespondingDialog.java b/services/core/java/com/android/server/am/AppNotRespondingDialog.java index 5fe842752e81..d3e91da3d330 100644 --- a/services/core/java/com/android/server/am/AppNotRespondingDialog.java +++ b/services/core/java/com/android/server/am/AppNotRespondingDialog.java @@ -169,8 +169,10 @@ final class AppNotRespondingDialog extends BaseErrorDialog implements View.OnCli errState.getDialogController().clearAnrDialogs(); } mService.mServices.scheduleServiceTimeoutLocked(app); - // If the app remains unresponsive, show the dialog again after a delay. - mService.mInternal.rescheduleAnrDialog(mData); + if (mData.isContinuousAnr) { + // If the app remains unresponsive, show the dialog again after a delay. + mService.mInternal.rescheduleAnrDialog(mData); + } } break; } @@ -197,10 +199,17 @@ final class AppNotRespondingDialog extends BaseErrorDialog implements View.OnCli final ApplicationInfo aInfo; final boolean aboveSystem; - Data(ProcessRecord proc, ApplicationInfo aInfo, boolean aboveSystem) { + // If true, then even if the user presses "WAIT" on the ANR dialog, + // we'll show it again until the app start responding again. + // (we only use it for input dispatch ANRs) + final boolean isContinuousAnr; + + Data(ProcessRecord proc, ApplicationInfo aInfo, boolean aboveSystem, + boolean isContinuousAnr) { this.proc = proc; this.aInfo = aInfo; this.aboveSystem = aboveSystem; + this.isContinuousAnr = isContinuousAnr; } } } diff --git a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java index 68d906be65de..9bb63d306f3c 100644 --- a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java +++ b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java @@ -263,7 +263,8 @@ class ProcessErrorStateRecord { void appNotResponding(String activityShortComponentName, ApplicationInfo aInfo, String parentShortComponentName, WindowProcessController parentProcess, boolean aboveSystem, TimeoutRecord timeoutRecord, - ExecutorService auxiliaryTaskExecutor, boolean onlyDumpSelf) { + ExecutorService auxiliaryTaskExecutor, boolean onlyDumpSelf, + boolean isContinuousAnr) { String annotation = timeoutRecord.mReason; AnrLatencyTracker latencyTracker = timeoutRecord.mLatencyTracker; Future<?> updateCpuStatsNowFirstCall = null; @@ -630,7 +631,8 @@ class ProcessErrorStateRecord { // Bring up the infamous App Not Responding dialog Message msg = Message.obtain(); msg.what = ActivityManagerService.SHOW_NOT_RESPONDING_UI_MSG; - msg.obj = new AppNotRespondingDialog.Data(mApp, aInfo, aboveSystem); + msg.obj = new AppNotRespondingDialog.Data(mApp, aInfo, aboveSystem, + isContinuousAnr); mService.mUiHandler.sendMessageDelayed(msg, anrDialogDelayMs); } diff --git a/services/tests/servicestests/src/com/android/server/am/AnrHelperTest.java b/services/tests/servicestests/src/com/android/server/am/AnrHelperTest.java index e6ab73a6f924..162855a7caa7 100644 --- a/services/tests/servicestests/src/com/android/server/am/AnrHelperTest.java +++ b/services/tests/servicestests/src/com/android/server/am/AnrHelperTest.java @@ -119,12 +119,13 @@ public class AnrHelperTest { final TimeoutRecord timeoutRecord = TimeoutRecord.forInputDispatchWindowUnresponsive( annotation); mAnrHelper.appNotResponding(mAnrApp, activityShortComponentName, appInfo, - parentShortComponentName, parentProcess, aboveSystem, timeoutRecord); + parentShortComponentName, parentProcess, aboveSystem, timeoutRecord, + /*isContinuousAnr*/ false); verify(mAnrApp.mErrorState, timeout(TIMEOUT_MS)).appNotResponding( eq(activityShortComponentName), eq(appInfo), eq(parentShortComponentName), eq(parentProcess), eq(aboveSystem), eq(timeoutRecord), eq(mExecutorService), - eq(false) /* onlyDumpSelf */); + eq(false) /* onlyDumpSelf */, eq(false) /*isContinuousAnr*/); } @Test @@ -137,13 +138,14 @@ public class AnrHelperTest { processingLatch.await(); return null; }).when(mAnrApp.mErrorState).appNotResponding(anyString(), any(), any(), any(), - anyBoolean(), any(), any(), anyBoolean()); + anyBoolean(), any(), any(), anyBoolean(), anyBoolean()); final ApplicationInfo appInfo = new ApplicationInfo(); final TimeoutRecord timeoutRecord = TimeoutRecord.forInputDispatchWindowUnresponsive( "annotation"); final Runnable reportAnr = () -> mAnrHelper.appNotResponding(mAnrApp, "activityShortComponentName", appInfo, "parentShortComponentName", - null /* parentProcess */, false /* aboveSystem */, timeoutRecord); + null /* parentProcess */, false /* aboveSystem */, timeoutRecord, + false /*isContinuousAnr*/); reportAnr.run(); // This should be skipped because the pid is pending in queue. reportAnr.run(); @@ -160,6 +162,6 @@ public class AnrHelperTest { // There is only one ANR reported. verify(mAnrApp.mErrorState, timeout(TIMEOUT_MS).only()).appNotResponding( anyString(), any(), any(), any(), anyBoolean(), any(), eq(mExecutorService), - anyBoolean()); + anyBoolean(), anyBoolean()); } } diff --git a/services/tests/servicestests/src/com/android/server/am/ProcessRecordTests.java b/services/tests/servicestests/src/com/android/server/am/ProcessRecordTests.java index 9cada91f1db0..6350e225a429 100644 --- a/services/tests/servicestests/src/com/android/server/am/ProcessRecordTests.java +++ b/services/tests/servicestests/src/com/android/server/am/ProcessRecordTests.java @@ -202,6 +202,7 @@ public class ProcessRecordTests { TimeoutRecord timeoutRecord = TimeoutRecord.forInputDispatchNoFocusedWindow(annotation); processErrorState.appNotResponding(null /* activityShortComponentName */, null /* aInfo */, null /* parentShortComponentName */, null /* parentProcess */, - false /* aboveSystem */, timeoutRecord, mExecutorService, false /* onlyDumpSelf */); + false /* aboveSystem */, timeoutRecord, mExecutorService, false /* onlyDumpSelf */, + false /*isContinuousAnr*/); } } |