OSDN Git Service

Protect against NPE for ActivityRecords without a stack.
authorWale Ogunwale <ogunwale@google.com>
Wed, 11 Mar 2015 22:36:30 +0000 (15:36 -0700)
committerWale Ogunwale <ogunwale@google.com>
Thu, 12 Mar 2015 22:03:22 +0000 (15:03 -0700)
A previous change allowed us to remove stack that no longer contained
any task. This was causing some NPE when an ActivityRecord.Token or
some other cached ActivityRecord later gets converted back to an
ActivityRecord and we try to access its stack.

Bug: 19552874
Change-Id: Ie9454bbce56591b337f97af40f8c00b8597becdf

services/core/java/com/android/server/am/ActivityManagerService.java
services/core/java/com/android/server/am/ActivityRecord.java
services/core/java/com/android/server/am/ActivityStack.java
services/core/java/com/android/server/am/ActivityStackSupervisor.java
services/core/java/com/android/server/am/PendingIntentRecord.java
services/core/java/com/android/server/am/TaskRecord.java

index 3f8d997..7f44f4e 100644 (file)
@@ -1757,7 +1757,7 @@ public final class ActivityManagerService extends ActivityManagerNative
             }
             case ENTER_ANIMATION_COMPLETE_MSG: {
                 synchronized (ActivityManagerService.this) {
-                    ActivityRecord r = ActivityRecord.forToken((IBinder) msg.obj);
+                    ActivityRecord r = ActivityRecord.forTokenLocked((IBinder) msg.obj);
                     if (r != null && r.app != null && r.app.thread != null) {
                         try {
                             r.app.thread.scheduleEnterAnimationComplete(r.appToken);
@@ -2520,7 +2520,7 @@ public final class ActivityManagerService extends ActivityManagerNative
     public void notifyActivityDrawn(IBinder token) {
         if (DEBUG_VISBILITY) Slog.d(TAG, "notifyActivityDrawn: token=" + token);
         synchronized (this) {
-            ActivityRecord r= mStackSupervisor.isInAnyStackLocked(token);
+            ActivityRecord r = mStackSupervisor.isInAnyStackLocked(token);
             if (r != null) {
                 r.task.stack.notifyActivityDrawnLocked(r);
             }
@@ -3955,11 +3955,10 @@ public final class ActivityManagerService extends ActivityManagerNative
                 return;
             }
 
-            ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
-                    mHeavyWeightProcess.activities);
-            for (int i=0; i<activities.size(); i++) {
+            ArrayList<ActivityRecord> activities = new ArrayList<>(mHeavyWeightProcess.activities);
+            for (int i = 0; i < activities.size(); i++) {
                 ActivityRecord r = activities.get(i);
-                if (!r.finishing) {
+                if (!r.finishing && r.isInStackLocked()) {
                     r.task.stack.finishActivityLocked(r, Activity.RESULT_CANCELED,
                             null, "finish-heavy", true);
                 }
@@ -4086,7 +4085,7 @@ public final class ActivityManagerService extends ActivityManagerNative
             final long origId = Binder.clearCallingIdentity();
             try {
                 ActivityRecord r = ActivityRecord.isInStackLocked(token);
-                if (r.task == null || r.task.stack == null) {
+                if (r == null) {
                     return false;
                 }
                 return r.task.stack.safelyDestroyActivityLocked(r, "app-req");
@@ -7797,20 +7796,19 @@ public final class ActivityManagerService extends ActivityManagerNative
                     android.Manifest.permission.GET_DETAILED_TASKS)
                     == PackageManager.PERMISSION_GRANTED;
 
-            final int N = mRecentTasks.size();
-            ArrayList<ActivityManager.RecentTaskInfo> res
-                    = new ArrayList<ActivityManager.RecentTaskInfo>(
-                            maxNum < N ? maxNum : N);
+            final int recentsCount = mRecentTasks.size();
+            ArrayList<ActivityManager.RecentTaskInfo> res =
+                    new ArrayList<>(maxNum < recentsCount ? maxNum : recentsCount);
 
             final Set<Integer> includedUsers;
             if (includeProfiles) {
                 includedUsers = getProfileIdsLocked(userId);
             } else {
-                includedUsers = new HashSet<Integer>();
+                includedUsers = new HashSet<>();
             }
             includedUsers.add(Integer.valueOf(userId));
 
-            for (int i=0; i<N && maxNum > 0; i++) {
+            for (int i = 0; i < recentsCount && maxNum > 0; i++) {
                 TaskRecord tr = mRecentTasks.get(i);
                 // Only add calling user or related users recent tasks
                 if (!includedUsers.contains(Integer.valueOf(tr.userId))) {
@@ -8292,7 +8290,7 @@ public final class ActivityManagerService extends ActivityManagerNative
             if (parentActivityToken == null) {
                 throw new IllegalArgumentException("parent token must not be null");
             }
-            ActivityRecord r = ActivityRecord.forToken(parentActivityToken);
+            ActivityRecord r = ActivityRecord.forTokenLocked(parentActivityToken);
             if (r == null) {
                 return null;
             }
@@ -8494,7 +8492,7 @@ public final class ActivityManagerService extends ActivityManagerNative
         long ident = Binder.clearCallingIdentity();
         try {
             synchronized (this) {
-                final ActivityRecord r = ActivityRecord.forToken(token);
+                final ActivityRecord r = ActivityRecord.forTokenLocked(token);
                 if (r == null) {
                     return;
                 }
@@ -16573,8 +16571,8 @@ public final class ActivityManagerService extends ActivityManagerNative
     @Override
     public boolean shouldUpRecreateTask(IBinder token, String destAffinity) {
         synchronized (this) {
-            ActivityRecord srec = ActivityRecord.forToken(token);
-            if (srec.task != null && srec.task.stack != null) {
+            ActivityRecord srec = ActivityRecord.forTokenLocked(token);
+            if (srec != null) {
                 return srec.task.stack.shouldUpRecreateTaskLocked(srec, destAffinity);
             }
         }
@@ -16585,16 +16583,19 @@ public final class ActivityManagerService extends ActivityManagerNative
             Intent resultData) {
 
         synchronized (this) {
-            final ActivityStack stack = ActivityRecord.getStackLocked(token);
-            if (stack != null) {
-                return stack.navigateUpToLocked(token, destIntent, resultCode, resultData);
+            final ActivityRecord r = ActivityRecord.forTokenLocked(token);
+            if (r != null) {
+                return r.task.stack.navigateUpToLocked(r, destIntent, resultCode, resultData);
             }
             return false;
         }
     }
 
     public int getLaunchedFromUid(IBinder activityToken) {
-        ActivityRecord srec = ActivityRecord.forToken(activityToken);
+        ActivityRecord srec;
+        synchronized (this) {
+            srec = ActivityRecord.forTokenLocked(activityToken);
+        }
         if (srec == null) {
             return -1;
         }
@@ -16602,7 +16603,10 @@ public final class ActivityManagerService extends ActivityManagerNative
     }
 
     public String getLaunchedFromPackage(IBinder activityToken) {
-        ActivityRecord srec = ActivityRecord.forToken(activityToken);
+        ActivityRecord srec;
+        synchronized (this) {
+            srec = ActivityRecord.forTokenLocked(activityToken);
+        }
         if (srec == null) {
             return null;
         }
index 09dc426..ca2721c 100755 (executable)
@@ -17,6 +17,7 @@
 package com.android.server.am;
 
 import static com.android.server.am.ActivityManagerDebugConfig.*;
+import static com.android.server.am.ActivityManagerService.DEBUG_SWITCH;
 import static com.android.server.am.ActivityManagerService.DEBUG_THUMBNAILS;
 import static com.android.server.am.TaskPersister.DEBUG_PERSISTER;
 import static com.android.server.am.TaskPersister.DEBUG_RESTORER;
@@ -319,44 +320,83 @@ final class ActivityRecord {
     }
 
     static class Token extends IApplicationToken.Stub {
-        final WeakReference<ActivityRecord> weakActivity;
+        private final WeakReference<ActivityRecord> weakActivity;
+        private final ActivityManagerService mService;
 
-        Token(ActivityRecord activity) {
+        Token(ActivityRecord activity, ActivityManagerService service) {
             weakActivity = new WeakReference<>(activity);
+            mService = service;
         }
 
-        @Override public void windowsDrawn() {
-            ActivityRecord activity = weakActivity.get();
-            if (activity != null) {
-                activity.windowsDrawn();
+        @Override
+        public void windowsDrawn() {
+            synchronized (mService) {
+                ActivityRecord r = tokenToActivityRecordLocked(this);
+                if (r != null) {
+                    r.windowsDrawnLocked();
+                }
             }
         }
 
-        @Override public void windowsVisible() {
-            ActivityRecord activity = weakActivity.get();
-            if (activity != null) {
-                activity.windowsVisible();
+        @Override
+        public void windowsVisible() {
+            synchronized (mService) {
+                ActivityRecord r = tokenToActivityRecordLocked(this);
+                if (r != null) {
+                    r.windowsVisibleLocked();
+                }
             }
         }
 
-        @Override public void windowsGone() {
-            ActivityRecord activity = weakActivity.get();
-            if (activity != null) {
-                activity.windowsGone();
+        @Override
+        public void windowsGone() {
+            synchronized (mService) {
+                ActivityRecord r = tokenToActivityRecordLocked(this);
+                if (r != null) {
+                    if (DEBUG_SWITCH) Log.v(TAG, "windowsGone(): " + r);
+                    r.nowVisible = false;
+                    return;
+                }
             }
         }
 
-        @Override public boolean keyDispatchingTimedOut(String reason) {
-            ActivityRecord activity = weakActivity.get();
-            return activity != null && activity.keyDispatchingTimedOut(reason);
+        @Override
+        public boolean keyDispatchingTimedOut(String reason) {
+            ActivityRecord r;
+            ActivityRecord anrActivity;
+            ProcessRecord anrApp;
+            synchronized (mService) {
+                r = tokenToActivityRecordLocked(this);
+                if (r == null) {
+                    return false;
+                }
+                anrActivity = r.getWaitingHistoryRecordLocked();
+                anrApp = r != null ? r.app : null;
+            }
+            return mService.inputDispatchingTimedOut(anrApp, anrActivity, r, false, reason);
         }
 
-        @Override public long getKeyDispatchingTimeout() {
-            ActivityRecord activity = weakActivity.get();
-            if (activity != null) {
-                return activity.getKeyDispatchingTimeout();
+        @Override
+        public long getKeyDispatchingTimeout() {
+            synchronized (mService) {
+                ActivityRecord r = tokenToActivityRecordLocked(this);
+                if (r == null) {
+                    return 0;
+                }
+                r = r.getWaitingHistoryRecordLocked();
+                return ActivityManagerService.getInputDispatchingTimeoutLocked(r);
             }
-            return 0;
+        }
+
+        private static final ActivityRecord tokenToActivityRecordLocked(Token token) {
+            if (token == null) {
+                return null;
+            }
+            ActivityRecord r = token.weakActivity.get();
+            if (r == null || r.task == null || r.task.stack == null) {
+                return null;
+            }
+            return r;
         }
 
         @Override
@@ -371,9 +411,9 @@ final class ActivityRecord {
         }
     }
 
-    static ActivityRecord forToken(IBinder token) {
+    static ActivityRecord forTokenLocked(IBinder token) {
         try {
-            return token != null ? ((Token)token).weakActivity.get() : null;
+            return Token.tokenToActivityRecordLocked((Token)token);
         } catch (ClassCastException e) {
             Slog.w(TAG, "Bad activity token: " + token, e);
             return null;
@@ -391,7 +431,7 @@ final class ActivityRecord {
             boolean _componentSpecified, ActivityStackSupervisor supervisor,
             ActivityContainer container, Bundle options) {
         service = _service;
-        appToken = new Token(this);
+        appToken = new Token(this, service);
         info = aInfo;
         launchedFromUid = _launchedFromUid;
         launchedFromPackage = _launchedFromPackage;
@@ -528,13 +568,8 @@ final class ActivityRecord {
     }
 
     void setTask(TaskRecord newTask, TaskRecord taskToAffiliateWith) {
-        if (task != null && task.removeActivity(this)) {
-            if (task != newTask) {
-                task.stack.removeTask(task, "setTask");
-            } else {
-                Slog.d(TAG, "!!! REMOVE THIS LOG !!! setTask: nearly removed stack=" +
-                        (newTask == null ? null : newTask.stack));
-            }
+        if (task != null && task.removeActivity(this) && task != newTask && task.stack != null) {
+            task.stack.removeTask(task, "setTask");
         }
         task = newTask;
         setTaskToAffiliateWith(taskToAffiliateWith);
@@ -580,6 +615,10 @@ final class ActivityRecord {
         return inHistory;
     }
 
+    boolean isInStackLocked() {
+        return task != null && task.stack != null && task.stack.isInStackLocked(this) != null;
+    }
+
     boolean isHomeActivity() {
         return mActivityType == HOME_ACTIVITY_TYPE;
     }
@@ -599,9 +638,10 @@ final class ActivityRecord {
                         (intent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0);
     }
 
-    void makeFinishing() {
+    void makeFinishingLocked() {
         if (!finishing) {
-            if (this == task.stack.getVisibleBehindActivity()) {
+            if (task != null && task.stack != null
+                    && this == task.stack.getVisibleBehindActivity()) {
                 // A finishing activity should not remain as visible in the background
                 mStackSupervisor.requestVisibleBehindLocked(this, false);
             }
@@ -670,8 +710,9 @@ final class ActivityRecord {
         // stack.
         final ReferrerIntent rintent = new ReferrerIntent(intent, referrer);
         boolean unsent = true;
-        if ((state == ActivityState.RESUMED || (service.isSleeping()
-                        && task.stack.topRunningActivityLocked(null) == this))
+        if ((state == ActivityState.RESUMED
+                || (service.isSleeping() && task.stack != null
+                    && task.stack.topRunningActivityLocked(null) == this))
                 && app != null && app.thread != null) {
             try {
                 ArrayList<ReferrerIntent> ar = new ArrayList<>(1);
@@ -842,19 +883,27 @@ final class ActivityRecord {
     }
 
     boolean continueLaunchTickingLocked() {
-        if (launchTickTime != 0) {
-            final ActivityStack stack = task.stack;
-            Message msg = stack.mHandler.obtainMessage(ActivityStack.LAUNCH_TICK_MSG, this);
-            stack.mHandler.removeMessages(ActivityStack.LAUNCH_TICK_MSG);
-            stack.mHandler.sendMessageDelayed(msg, ActivityStack.LAUNCH_TICK);
-            return true;
+        if (launchTickTime == 0) {
+            return false;
         }
-        return false;
+
+        final ActivityStack stack = task.stack;
+        if (stack == null) {
+            return false;
+        }
+
+        Message msg = stack.mHandler.obtainMessage(ActivityStack.LAUNCH_TICK_MSG, this);
+        stack.mHandler.removeMessages(ActivityStack.LAUNCH_TICK_MSG);
+        stack.mHandler.sendMessageDelayed(msg, ActivityStack.LAUNCH_TICK);
+        return true;
     }
 
     void finishLaunchTickingLocked() {
         launchTickTime = 0;
-        task.stack.mHandler.removeMessages(ActivityStack.LAUNCH_TICK_MSG);
+        final ActivityStack stack = task.stack;
+        if (stack != null) {
+            stack.mHandler.removeMessages(ActivityStack.LAUNCH_TICK_MSG);
+        }
     }
 
     // IApplicationToken
@@ -885,8 +934,8 @@ final class ActivityRecord {
         if (displayStartTime != 0) {
             reportLaunchTimeLocked(curTime);
         }
-        if (fullyDrawnStartTime != 0) {
-            final ActivityStack stack = task.stack;
+        final ActivityStack stack = task.stack;
+        if (fullyDrawnStartTime != 0 && stack != null) {
             final long thisTime = curTime - fullyDrawnStartTime;
             final long totalTime = stack.mFullyDrawnStartTime != 0
                     ? (curTime - stack.mFullyDrawnStartTime) : thisTime;
@@ -911,13 +960,16 @@ final class ActivityRecord {
             if (totalTime > 0) {
                 //service.mUsageStatsService.noteFullyDrawnTime(realActivity, (int) totalTime);
             }
-            fullyDrawnStartTime = 0;
             stack.mFullyDrawnStartTime = 0;
         }
+        fullyDrawnStartTime = 0;
     }
 
     private void reportLaunchTimeLocked(final long curTime) {
         final ActivityStack stack = task.stack;
+        if (stack == null) {
+            return;
+        }
         final long thisTime = curTime - displayStartTime;
         final long totalTime = stack.mLaunchStartTime != 0
                 ? (curTime - stack.mLaunchStartTime) : thisTime;
@@ -947,60 +999,47 @@ final class ActivityRecord {
         stack.mLaunchStartTime = 0;
     }
 
-    public void windowsDrawn() {
-        synchronized(service) {
-            if (displayStartTime != 0) {
-                reportLaunchTimeLocked(SystemClock.uptimeMillis());
-            }
-            mStackSupervisor.sendWaitingVisibleReportLocked(this);
-            startTime = 0;
-            finishLaunchTickingLocked();
-            if (task != null) {
-                task.hasBeenVisible = true;
-            }
+    void windowsDrawnLocked() {
+        if (displayStartTime != 0) {
+            reportLaunchTimeLocked(SystemClock.uptimeMillis());
+        }
+        mStackSupervisor.sendWaitingVisibleReportLocked(this);
+        startTime = 0;
+        finishLaunchTickingLocked();
+        if (task != null) {
+            task.hasBeenVisible = true;
         }
     }
 
-    public void windowsVisible() {
-        synchronized(service) {
-            mStackSupervisor.reportActivityVisibleLocked(this);
-            if (ActivityManagerService.DEBUG_SWITCH) Log.v(TAG, "windowsVisible(): " + this);
-            if (!nowVisible) {
-                nowVisible = true;
-                lastVisibleTime = SystemClock.uptimeMillis();
-                if (!idle) {
-                    // Instead of doing the full stop routine here, let's just
-                    // hide any activities we now can, and let them stop when
-                    // the normal idle happens.
-                    mStackSupervisor.processStoppingActivitiesLocked(false);
-                } else {
-                    // If this activity was already idle, then we now need to
-                    // make sure we perform the full stop of any activities
-                    // that are waiting to do so.  This is because we won't
-                    // do that while they are still waiting for this one to
-                    // become visible.
-                    final int N = mStackSupervisor.mWaitingVisibleActivities.size();
-                    if (N > 0) {
-                        for (int i=0; i<N; i++) {
-                            ActivityRecord r = mStackSupervisor.mWaitingVisibleActivities.get(i);
-                            if (ActivityManagerService.DEBUG_SWITCH) Log.v(TAG,
-                                    "Was waiting for visible: " + r);
-                        }
-                        mStackSupervisor.mWaitingVisibleActivities.clear();
-                        mStackSupervisor.scheduleIdleLocked();
+    void windowsVisibleLocked() {
+        mStackSupervisor.reportActivityVisibleLocked(this);
+        if (DEBUG_SWITCH) Log.v(TAG, "windowsVisibleLocked(): " + this);
+        if (!nowVisible) {
+            nowVisible = true;
+            lastVisibleTime = SystemClock.uptimeMillis();
+            if (!idle) {
+                // Instead of doing the full stop routine here, let's just hide any activities
+                // we now can, and let them stop when the normal idle happens.
+                mStackSupervisor.processStoppingActivitiesLocked(false);
+            } else {
+                // If this activity was already idle, then we now need to make sure we perform
+                // the full stop of any activities that are waiting to do so. This is because
+                // we won't do that while they are still waiting for this one to become visible.
+                final int size = mStackSupervisor.mWaitingVisibleActivities.size();
+                if (size > 0) {
+                    for (int i = 0; i < size; i++) {
+                        ActivityRecord r = mStackSupervisor.mWaitingVisibleActivities.get(i);
+                        if (DEBUG_SWITCH) Log.v(TAG, "Was waiting for visible: " + r);
                     }
+                    mStackSupervisor.mWaitingVisibleActivities.clear();
+                    mStackSupervisor.scheduleIdleLocked();
                 }
-                service.scheduleAppGcsLocked();
             }
+            service.scheduleAppGcsLocked();
         }
     }
 
-    public void windowsGone() {
-        if (ActivityManagerService.DEBUG_SWITCH) Log.v(TAG, "windowsGone(): " + this);
-        nowVisible = false;
-    }
-
-    private ActivityRecord getWaitingHistoryRecordLocked() {
+    ActivityRecord getWaitingHistoryRecordLocked() {
         // First find the real culprit...  if we are waiting
         // for another app to start, then we have paused dispatching
         // for this activity.
@@ -1021,24 +1060,6 @@ final class ActivityRecord {
         return r;
     }
 
-    public boolean keyDispatchingTimedOut(String reason) {
-        ActivityRecord r;
-        ProcessRecord anrApp;
-        synchronized(service) {
-            r = getWaitingHistoryRecordLocked();
-            anrApp = r != null ? r.app : null;
-        }
-        return service.inputDispatchingTimedOut(anrApp, r, this, false, reason);
-    }
-
-    /** Returns the key dispatching timeout for this application token. */
-    public long getKeyDispatchingTimeout() {
-        synchronized(service) {
-            ActivityRecord r = getWaitingHistoryRecordLocked();
-            return ActivityManagerService.getInputDispatchingTimeoutLocked(r);
-        }
-    }
-
     /**
      * This method will return true if the activity is either visible, is becoming visible, is
      * currently pausing, or is resumed.
@@ -1066,14 +1087,14 @@ final class ActivityRecord {
     }
 
     static void activityResumedLocked(IBinder token) {
-        final ActivityRecord r = ActivityRecord.forToken(token);
+        final ActivityRecord r = ActivityRecord.forTokenLocked(token);
         if (DEBUG_SAVED_STATE) Slog.i(TAG, "Resumed activity; dropping state of: " + r);
         r.icicle = null;
         r.haveState = false;
     }
 
     static int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
-        final ActivityRecord r = ActivityRecord.forToken(token);
+        final ActivityRecord r = ActivityRecord.forTokenLocked(token);
         if (r == null) {
             return INVALID_TASK_ID;
         }
@@ -1086,7 +1107,7 @@ final class ActivityRecord {
     }
 
     static ActivityRecord isInStackLocked(IBinder token) {
-        final ActivityRecord r = ActivityRecord.forToken(token);
+        final ActivityRecord r = ActivityRecord.forTokenLocked(token);
         return (r != null) ? r.task.stack.isInStackLocked(r) : null;
     }
 
index 43d297f..b8e59ac 100644 (file)
@@ -461,7 +461,7 @@ final class ActivityStack {
     }
 
     ActivityRecord isInStackLocked(IBinder token) {
-        final ActivityRecord r = ActivityRecord.forToken(token);
+        final ActivityRecord r = ActivityRecord.forTokenLocked(token);
         return isInStackLocked(r);
     }
 
@@ -470,7 +470,8 @@ final class ActivityStack {
             return null;
         }
         final TaskRecord task = r.task;
-        if (task != null && task.mActivities.contains(r) && mTaskHistory.contains(task)) {
+        if (task != null && task.stack != null
+                && task.mActivities.contains(r) && mTaskHistory.contains(task)) {
             if (task.stack != this) Slog.w(TAG,
                     "Illegal state! task does not point to stack it is in.");
             return r;
@@ -2795,7 +2796,7 @@ final class ActivityStack {
             return false;
         }
 
-        r.makeFinishing();
+        r.makeFinishingLocked();
         final TaskRecord task = r.task;
         EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
                 r.userId, System.identityHashCode(r),
@@ -2898,7 +2899,7 @@ final class ActivityStack {
                 || prevState == ActivityState.INITIALIZING) {
             // If this activity is already stopped, we can just finish
             // it right now.
-            r.makeFinishing();
+            r.makeFinishingLocked();
             boolean activityRemoved = destroyActivityLocked(r, true, "finish-imm");
             if (activityRemoved) {
                 mStackSupervisor.resumeTopActivitiesLocked();
@@ -2974,9 +2975,8 @@ final class ActivityStack {
         return false;
     }
 
-    final boolean navigateUpToLocked(IBinder token, Intent destIntent, int resultCode,
+    final boolean navigateUpToLocked(ActivityRecord srec, Intent destIntent, int resultCode,
             Intent resultData) {
-        final ActivityRecord srec = ActivityRecord.forToken(token);
         final TaskRecord task = srec.task;
         final ArrayList<ActivityRecord> activities = task.mActivities;
         final int start = activities.indexOf(srec);
@@ -3123,7 +3123,7 @@ final class ActivityStack {
     private void removeActivityFromHistoryLocked(ActivityRecord r, String reason) {
         mStackSupervisor.removeChildActivityContainers(r);
         finishActivityResultsLocked(r, Activity.RESULT_CANCELED, null);
-        r.makeFinishing();
+        r.makeFinishingLocked();
         if (DEBUG_ADD_REMOVE) {
             RuntimeException here = new RuntimeException("here");
             here.fillInStackTrace();
@@ -3364,7 +3364,7 @@ final class ActivityStack {
     final void activityDestroyedLocked(IBinder token, String reason) {
         final long origId = Binder.clearCallingIdentity();
         try {
-            ActivityRecord r = ActivityRecord.forToken(token);
+            ActivityRecord r = ActivityRecord.forTokenLocked(token);
             if (r != null) {
                 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
             }
@@ -3945,7 +3945,7 @@ final class ActivityStack {
                 }
             }
         }
-        final ActivityRecord r = ActivityRecord.forToken(token);
+        final ActivityRecord r = ActivityRecord.forTokenLocked(token);
         if (r == null) {
             return false;
         }
index 65d2426..cbbb11a 100644 (file)
@@ -394,6 +394,10 @@ public final class ActivityStackSupervisor implements DisplayListener {
      * Use {@link ActivityStack#isStackVisibleLocked} to determine if a specific
      * stack is visible or not. */
     boolean isFrontStack(ActivityStack stack) {
+        if (stack == null) {
+            return false;
+        }
+
         final ActivityRecord parent = stack.mActivityContainer.mParentActivity;
         if (parent != null) {
             stack = parent.task.stack;
@@ -1380,6 +1384,9 @@ public final class ActivityStackSupervisor implements DisplayListener {
                 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
             }
             resultRecord = sourceRecord.resultTo;
+            if (resultRecord != null && !resultRecord.isInStackLocked()) {
+                resultRecord = null;
+            }
             resultWho = sourceRecord.resultWho;
             requestCode = sourceRecord.requestCode;
             sourceRecord.resultTo = null;
@@ -1564,7 +1571,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
 
             ActivityStack stack;
 
-            if (task != null) {
+            if (task != null && task.stack != null) {
                 stack = task.stack;
                 if (stack.isOnHomeDisplay()) {
                     if (mFocusedStack != stack) {
@@ -1672,7 +1679,8 @@ public final class ActivityStackSupervisor implements DisplayListener {
                 && !launchSingleTask && !launchSingleInstance
                 && (launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
 
-        if (r.resultTo != null && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
+        if (r.resultTo != null && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0
+                && r.resultTo.task.stack != null) {
             // For whatever reason this activity is being launched into a new
             // task...  yet the caller has requested a result back.  Well, that
             // is pretty messed up, so instead immediately send back a cancel
@@ -2074,7 +2082,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
             }
 
         } else {
-            if (r.resultTo != null) {
+            if (r.resultTo != null && r.resultTo.task.stack != null) {
                 r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho,
                         r.requestCode, Activity.RESULT_CANCELED, null);
             }
@@ -2307,7 +2315,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
         boolean booting = false;
         boolean activityRemoved = false;
 
-        ActivityRecord r = ActivityRecord.forToken(token);
+        ActivityRecord r = ActivityRecord.forTokenLocked(token);
         if (r != null) {
             if (DEBUG_IDLE) Slog.d(TAG, "activityIdleInternalLocked: Callers=" +
                     Debug.getCallers(4));
@@ -2355,13 +2363,13 @@ public final class ActivityStackSupervisor implements DisplayListener {
         // Atomically retrieve all of the other things to do.
         stops = processStoppingActivitiesLocked(true);
         NS = stops != null ? stops.size() : 0;
-        if ((NF=mFinishingActivities.size()) > 0) {
-            finishes = new ArrayList<ActivityRecord>(mFinishingActivities);
+        if ((NF = mFinishingActivities.size()) > 0) {
+            finishes = new ArrayList<>(mFinishingActivities);
             mFinishingActivities.clear();
         }
 
         if (mStartingUsers.size() > 0) {
-            startingUsers = new ArrayList<UserStartedState>(mStartingUsers);
+            startingUsers = new ArrayList<>(mStartingUsers);
             mStartingUsers.clear();
         }
 
@@ -2370,10 +2378,12 @@ public final class ActivityStackSupervisor implements DisplayListener {
         for (int i = 0; i < NS; i++) {
             r = stops.get(i);
             final ActivityStack stack = r.task.stack;
-            if (r.finishing) {
-                stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);
-            } else {
-                stack.stopActivityLocked(r);
+            if (stack != null) {
+                if (r.finishing) {
+                    stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);
+                } else {
+                    stack.stopActivityLocked(r);
+                }
             }
         }
 
@@ -2381,7 +2391,10 @@ public final class ActivityStackSupervisor implements DisplayListener {
         // waiting for the next one to start.
         for (int i = 0; i < NF; i++) {
             r = finishes.get(i);
-            activityRemoved |= r.task.stack.destroyActivityLocked(r, true, "finish-idle");
+            final ActivityStack stack = r.task.stack;
+            if (stack != null) {
+                activityRemoved |= stack.destroyActivityLocked(r, true, "finish-idle");
+            }
         }
 
         if (!booting) {
@@ -2550,6 +2563,11 @@ public final class ActivityStackSupervisor implements DisplayListener {
             // we'll just indicate that this task returns to the home task.
             task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
         }
+        if (task.stack == null) {
+            Slog.e(TAG, "findTaskToMoveToFrontLocked: can't move task="
+                    + task + " to front. Stack is null");
+            return;
+        }
         task.stack.moveTaskToFrontLocked(task, false /* noAnimation */, options, reason);
         if (DEBUG_STACK) Slog.d(TAG, "findTaskToMoveToFront: moved to front of stack="
                 + task.stack);
@@ -3769,7 +3787,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
                 } break;
                 case LAUNCH_TASK_BEHIND_COMPLETE: {
                     synchronized (mService) {
-                        ActivityRecord r = ActivityRecord.forToken((IBinder) msg.obj);
+                        ActivityRecord r = ActivityRecord.forTokenLocked((IBinder) msg.obj);
                         if (r != null) {
                             handleLaunchTaskBehindCompleteLocked(r);
                         }
index 432abd2..7f2cae4 100644 (file)
@@ -275,8 +275,10 @@ final class PendingIntentRecord extends IIntentSender.Stub {
                         }
                         break;
                     case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
-                        key.activity.task.stack.sendActivityResultLocked(-1, key.activity,
-                                key.who, key.requestCode, code, finalIntent);
+                        if (key.activity.task.stack != null) {
+                            key.activity.task.stack.sendActivityResultLocked(-1, key.activity,
+                                    key.who, key.requestCode, code, finalIntent);
+                        }
                         break;
                     case ActivityManager.INTENT_SENDER_BROADCAST:
                         try {
index 398f0b3..d8d361b 100644 (file)
@@ -500,10 +500,12 @@ final class TaskRecord {
     }
 
     ActivityRecord topRunningActivityLocked(ActivityRecord notTop) {
-        for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
-            ActivityRecord r = mActivities.get(activityNdx);
-            if (!r.finishing && r != notTop && stack.okToShowLocked(r)) {
-                return r;
+        if (stack != null) {
+            for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
+                ActivityRecord r = mActivities.get(activityNdx);
+                if (!r.finishing && r != notTop && stack.okToShowLocked(r)) {
+                    return r;
+                }
             }
         }
         return null;
@@ -666,7 +668,7 @@ final class TaskRecord {
                     if (opts != null) {
                         ret.updateOptionsLocked(opts);
                     }
-                    if (stack.finishActivityLocked(
+                    if (stack != null && stack.finishActivityLocked(
                             r, Activity.RESULT_CANCELED, null, "clear-task-stack", false)) {
                         --activityNdx;
                         --numActivities;
@@ -679,8 +681,10 @@ final class TaskRecord {
                 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
                         && (launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {
                     if (!ret.finishing) {
-                        stack.finishActivityLocked(
-                                ret, Activity.RESULT_CANCELED, null, "clear-task-top", false);
+                        if (stack != null) {
+                            stack.finishActivityLocked(
+                                    ret, Activity.RESULT_CANCELED, null, "clear-task-top", false);
+                        }
                         return null;
                     }
                 }