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;
         }
     }