Fix various crashes from a destroy-timeout activity
This prevents below 3 cases that caused by using the
removed token to server side:
Block at | From method | Exception
-----------------------------------------------------
onCreate | reportSizeConfigurations | IllegalArgument
onStart | isTopOfTask | IllegalArgument
onResume | addView | BadToken
Bug: 109718716
Test: atest CtsActivityManagerDeviceTestCases:ActivityLifecycleTests
Test: Sample app in bug link.
Change-Id: I123a048c36f7ddbca0d5b1bf8060c3a4dd13a903
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 2daa577..34fb0c5 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -259,6 +259,7 @@
final H mH = new H();
final Executor mExecutor = new HandlerExecutor(mH);
final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>();
+ /** The activities to be truly destroyed (not include relaunch). */
final Map<IBinder, ClientTransactionItem> mActivitiesToBeDestroyed =
Collections.synchronizedMap(new ArrayMap<IBinder, ClientTransactionItem>());
// List of new activities (via ActivityRecord.nextIdle) that should
@@ -3077,6 +3078,10 @@
}
private void reportSizeConfigurations(ActivityClientRecord r) {
+ if (mActivitiesToBeDestroyed.containsKey(r.token)) {
+ // Size configurations of a destroyed activity is meaningless.
+ return;
+ }
Configuration[] configurations = r.activity.getResources().getSizeConfigurations();
if (configurations == null) {
return;
@@ -3825,6 +3830,13 @@
// We didn't actually resume the activity, so skipping any follow-up actions.
return;
}
+ if (mActivitiesToBeDestroyed.containsKey(token)) {
+ // Although the activity is resumed, it is going to be destroyed. So the following
+ // UI operations are unnecessary and also prevents exception because its token may
+ // be gone that window manager cannot recognize it. All necessary cleanup actions
+ // performed below will be done while handling destruction.
+ return;
+ }
final Activity a = r.activity;
diff --git a/services/core/java/com/android/server/am/ActivityTaskManagerService.java b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
index 10e0182..3211afb 100644
--- a/services/core/java/com/android/server/am/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
@@ -2395,10 +2395,7 @@
public boolean isTopOfTask(IBinder token) {
synchronized (mGlobalLock) {
ActivityRecord r = ActivityRecord.isInStackLocked(token);
- if (r == null) {
- throw new IllegalArgumentException();
- }
- return r.getTask().getTopActivity() == r;
+ return r != null && r.getTask().getTopActivity() == r;
}
}