Merge "Protect against NPE for ActivityRecords without a stack."

This commit is contained in:
Wale Ogunwale
2015-03-12 22:31:04 +00:00
committed by Android (Google) Code Review
6 changed files with 215 additions and 166 deletions

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

View File

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

View 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;
@@ -2797,7 +2798,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),
@@ -2900,7 +2901,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();
@@ -2976,9 +2977,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);
@@ -3125,7 +3125,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();
@@ -3366,7 +3366,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);
}
@@ -3947,7 +3947,7 @@ final class ActivityStack {
}
}
}
final ActivityRecord r = ActivityRecord.forToken(token);
final ActivityRecord r = ActivityRecord.forTokenLocked(token);
if (r == null) {
return false;
}

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

View 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 {

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