summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Makoto Onuki <omakoto@google.com> 2023-01-11 14:11:35 -0800
committer Makoto Onuki <omakoto@google.com> 2023-01-17 12:00:10 -0800
commitcb7ba3cfd5cd16f9b64db6dad363da9db5be13c4 (patch)
tree8b0cd5bde4187b8ff83f222c3d41adb02fb520b5
parentb72d65fd3014d61356bcdc67cf40714cd81b50b6 (diff)
Do not repeat ANR dialogs, except for "input" ANRs
The ANR dialog's behavior changed in I4ca34bb8cc60bcde3ff571566553f44246d78ddc such that even if the user presses "wait" on the ANR dialog, the dialog will re-appear unless the app starts responding again. However, the "stop the repeat" was only implemented for input ANRs, so for other kinds of ANRs (e.g. the broadcast ANR), the dialog would keep showing up even after the app starts behaving normally. This change will change the behavior so that only input ANRs will repeatedly show up. Fix: 263182141 Test: Manual test: Make shore "short service" ANR dialog will not repeat Test: Manual test: Make shore input ANR dialog will actually repeat Test: atest FrameworksServicesTests:AnrHelperTest Test: atest FrameworksServicesTests:ProcessRecordTests Change-Id: Id9b34cef605a65ff29b5569e72945790695d7abf
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java9
-rw-r--r--services/core/java/com/android/server/am/AnrHelper.java14
-rw-r--r--services/core/java/com/android/server/am/AppNotRespondingDialog.java15
-rw-r--r--services/core/java/com/android/server/am/ProcessErrorStateRecord.java6
-rw-r--r--services/tests/servicestests/src/com/android/server/am/AnrHelperTest.java12
-rw-r--r--services/tests/servicestests/src/com/android/server/am/ProcessRecordTests.java3
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*/);
}
}