OSDN Git Service

Bad token of activity when do the launch work at the app process side.
authorxiaomei.li <xiaomei.li@spreadtrum.com>
Sun, 9 Oct 2016 08:56:48 +0000 (16:56 +0800)
committerJoey Rizzoli <joey@lineageos.it>
Sun, 30 Apr 2017 08:37:08 +0000 (08:37 +0000)
If the activity destroy timeout, AMS will clear it from the task.

And if activity LAUNCH_ACTIVITY message is blocked in the app main thread,
it may do the handleLaunchActivity after AMS removed the activity record
token from the task.At this time, ActivityThread launch the activity and
call some AMS interfaces like reportSizeConfigurations(isTopOfTask etc.),
AMS may throw IllegalArgumentException for the bad token.

Good for the system stability, we should check if the launching activity
is in any stack to deceide whether need to do the follow-up launch work.

Test: monkey test 20h with no crash.

Change-Id: I508601a9e944d71c9f1955fb387b8a623f0aa8fd

core/java/android/app/ActivityThread.java

index 9d2ef91..2282ce8 100644 (file)
@@ -379,6 +379,21 @@ public final class ActivityThread {
             return activityInfo.persistableMode == ActivityInfo.PERSIST_ACROSS_REBOOTS;
         }
 
+        public boolean isInStack() {
+            try {
+                int stackId = ActivityManagerNative.getDefault().getActivityStackId(token);
+                int taskId = ActivityManagerNative.getDefault().getTaskForActivity(token, false);
+                // INVALID_STACK_ID = -1 and INVALID_TASK_ID = -1
+                if (stackId != -1 && taskId != -1) {
+                    return true;
+                }
+            } catch (RemoteException e) {
+                Log.w(TAG, "remote exception occur while check the task and stack of activity:"
+                        + this.toString(), e);
+            }
+            return false;
+        }
+
         public String toString() {
             ComponentName componentName = intent != null ? intent.getComponent() : null;
             return "ActivityRecord{"
@@ -2705,6 +2720,12 @@ public final class ActivityThread {
     }
 
     private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
+        // can not launch the activity that its taskId or stackId is invalid.
+        if (!r.isInStack()) {
+            Log.w(TAG,"handleLaunchActivity stack or task is invalid, can not launch it, r:" + r);
+            return;
+        }
+
         // If we are getting ready to gc after going to the background, well
         // we are back active so skip it.
         unscheduleGcIdler();