Merge "Do not repeat ANR dialogs, except for "input" ANRs"
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 8e1f969..e962fb0 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -6694,6 +6694,10 @@
@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();
@@ -6706,7 +6710,7 @@
}
mAnrHelper.appNotResponding(app, null, app.info, null, null, false,
- timeoutRecord);
+ timeoutRecord, isContinuousAnr);
}
}
@@ -18401,7 +18405,8 @@
}
}
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 71c80ea..463a2f8 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 @@
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 @@
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 @@
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 @@
mParentProcess = parentProcess;
mAboveSystem = aboveSystem;
mAuxiliaryTaskExecutor = auxiliaryTaskExecutor;
+ mIsContinuousAnr = isContinuousAnr;
}
void appNotResponding(boolean onlyDumpSelf) {
@@ -250,7 +253,8 @@
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 5fe8427..d3e91da 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 @@
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 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 68d906b..9bb63d3 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 @@
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 @@
// 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 e6ab73a..162855a 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 @@
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 @@
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 @@
// 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 9cada91..6350e22 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 @@
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*/);
}
}