From 7d701174f423754a2dade39fd16f102c085bd865 Mon Sep 17 00:00:00 2001 From: Wale Ogunwale Date: Wed, 11 Mar 2015 15:36:30 -0700 Subject: [PATCH] Protect against NPE for ActivityRecords without a stack. 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 --- .../server/am/ActivityManagerService.java | 48 ++-- .../com/android/server/am/ActivityRecord.java | 247 ++++++++++-------- .../com/android/server/am/ActivityStack.java | 18 +- .../server/am/ActivityStackSupervisor.java | 44 +++- .../server/am/PendingIntentRecord.java | 6 +- .../com/android/server/am/TaskRecord.java | 18 +- 6 files changed, 215 insertions(+), 166 deletions(-) diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 3f8d9970723ae..7f44f4eb5889f 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -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 activities = new ArrayList( - mHeavyWeightProcess.activities); - for (int i=0; i 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 res - = new ArrayList( - maxNum < N ? maxNum : N); + final int recentsCount = mRecentTasks.size(); + ArrayList res = + new ArrayList<>(maxNum < recentsCount ? maxNum : recentsCount); final Set includedUsers; if (includeProfiles) { includedUsers = getProfileIdsLocked(userId); } else { - includedUsers = new HashSet(); + includedUsers = new HashSet<>(); } includedUsers.add(Integer.valueOf(userId)); - for (int i=0; i 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; } diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index 09dc426812694..ca2721c561ffd 100755 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -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 weakActivity; + private final WeakReference 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 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 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; } diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 43d297f08f388..b8e59ac3e15c3 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -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 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; } diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 65d2426d61d2f..cbbb11a8dfb34 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -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(mFinishingActivities); + if ((NF = mFinishingActivities.size()) > 0) { + finishes = new ArrayList<>(mFinishingActivities); mFinishingActivities.clear(); } if (mStartingUsers.size() > 0) { - startingUsers = new ArrayList(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); } diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java index 432abd22aa52b..7f2cae49f35b3 100644 --- a/services/core/java/com/android/server/am/PendingIntentRecord.java +++ b/services/core/java/com/android/server/am/PendingIntentRecord.java @@ -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 { diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java index 398f0b328f1d7..d8d361b0d045e 100644 --- a/services/core/java/com/android/server/am/TaskRecord.java +++ b/services/core/java/com/android/server/am/TaskRecord.java @@ -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; } }