Addition separation of adding vs. reparenting activity

- Removed method ActivityRecord.setTask which did only half of what
is needed when adding a task and also only did half of what is needed
for reparenting. Previous callers now need to call either
ActivityRecord.reparent() to reparent and activity or
TaskRecord.addActivityAtIndex() to add an activity to a task.
- Fixed some NPE that resulted from the above change.

Test: adb shell am instrument -w -e class
com.google.android.setupwizard.tests.activity.SetupWizardExitActivityTest
com.google.android.setupwizard.tests.activity
Bug: 34179495

Change-Id: Ic69487f51d1bd139825e6a8054a49ce143065a57
This commit is contained in:
Wale Ogunwale
2017-02-01 15:33:08 -08:00
parent f9295bcc24
commit a0cd15e1a0
4 changed files with 56 additions and 32 deletions

View File

@@ -37,6 +37,8 @@ import static android.content.pm.ActivityInfo.FLAG_MULTIPROCESS;
import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
import static android.content.pm.ActivityInfo.FLAG_STATE_NOT_NEEDED;
import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
@@ -773,7 +775,10 @@ final class ActivityRecord implements AppWindowContainerListener {
// Remove the activity from the old task and add it to the new task
prevTask.removeActivity(this);
setTask(newTask, null);
// TODO(b/34179495): This should really be set to null in removeActivity() call above,
// but really bad things that I can't track down right now happen when I do that.
// So, setting it here now and will change later when there is time for investigation.
task = null;
newTask.addActivityAtIndex(position, this);
}
@@ -821,19 +826,8 @@ final class ActivityRecord implements AppWindowContainerListener {
}
}
void setTask(TaskRecord newTask, TaskRecord taskToAffiliateWith) {
if (task != null && task.removeActivity(this) && task != newTask
&& task.getStack() != null) {
task.getStack().removeTask(task, "setTask");
}
task = newTask;
setTaskToAffiliateWith(taskToAffiliateWith);
}
void setTaskToAffiliateWith(TaskRecord taskToAffiliateWith) {
if (taskToAffiliateWith != null &&
launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE &&
launchMode != ActivityInfo.LAUNCH_SINGLE_TASK) {
if (launchMode != LAUNCH_SINGLE_INSTANCE && launchMode != LAUNCH_SINGLE_TASK) {
task.setTaskToAffiliateWith(taskToAffiliateWith);
}
}

View File

@@ -2775,7 +2775,12 @@ final class ActivityStack extends ConfigurationContainer implements StackWindowL
// Slot the activity into the history stack and proceed
if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task,
new RuntimeException("here").fillInStackTrace());
r.createWindowContainer();
// TODO: Need to investigate if it is okay for the controller to already be created by the
// time we get to this point. I think it is, but need to double check.
// Use test in b/34179495 to trace the call path.
if (r.getWindowContainerController() == null) {
r.createWindowContainer();
}
task.setFrontOfTask();
if (!isHomeOrRecentsStack() || numActivities() > 0) {
@@ -2952,8 +2957,7 @@ final class ActivityStack extends ConfigurationContainer implements StackWindowL
+ targetTask + " Callers=" + Debug.getCallers(4));
if (DEBUG_TASKS) Slog.v(TAG_TASKS,
"Pushing next activity " + p + " out to target's task " + target.task);
p.setTask(targetTask, null);
targetTask.addActivityAtBottom(p);
p.reparent(targetTask, 0 /* position - bottom */, "resetTargetTaskIfNeeded");
}
mWindowContainerController.positionChildAtBottom(

View File

@@ -1615,7 +1615,7 @@ class ActivityStarter {
mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity.mActivityType);
mStartActivity.setTask(task, taskToAffiliate);
addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
if (mLaunchBounds != null) {
final int stackId = mTargetStack.mStackId;
if (StackId.resizeStackWithLaunchBounds(stackId)) {
@@ -1625,11 +1625,14 @@ class ActivityStarter {
mStartActivity.task.updateOverrideConfiguration(mLaunchBounds);
}
}
if (DEBUG_TASKS) Slog.v(TAG_TASKS,
"Starting new activity " +
mStartActivity + " in new task " + mStartActivity.task);
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
+ " in new task " + mStartActivity.task);
} else {
mStartActivity.setTask(mReuseTask, taskToAffiliate);
addOrReparentStartingActivity(mReuseTask, "setTaskFromReuseOrCreateNewTask");
}
if (taskToAffiliate != null) {
mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
}
if (mSupervisor.isLockTaskModeViolation(mStartActivity.task)) {
@@ -1719,7 +1722,7 @@ class ActivityStarter {
// An existing activity is starting this new activity, so we want to keep the new one in
// the same task as the one that is starting it.
mStartActivity.setTask(sourceTask, null);
addOrReparentStartingActivity(sourceTask, "setTaskFromSourceRecord");
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
+ " in existing task " + mStartActivity.task + " from source " + mSourceRecord);
return START_SUCCESS;
@@ -1752,7 +1755,8 @@ class ActivityStarter {
// Check whether we should actually launch the new activity in to the task,
// or just reuse the current activity on top.
ActivityRecord top = mInTask.getTopActivity();
if (top != null && top.realActivity.equals(mStartActivity.realActivity) && top.userId == mStartActivity.userId) {
if (top != null && top.realActivity.equals(mStartActivity.realActivity)
&& top.userId == mStartActivity.userId) {
if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
|| mLaunchSingleTop || mLaunchSingleTask) {
ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
@@ -1761,7 +1765,8 @@ class ActivityStarter {
// anything if that is the case, so this is it!
return START_RETURN_INTENT_TO_CALLER;
}
top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
mStartActivity.launchedFromPackage);
return START_DELIVERED_TO_TOP;
}
}
@@ -1773,9 +1778,9 @@ class ActivityStarter {
return START_TASK_TO_FRONT;
}
mStartActivity.setTask(mInTask, null);
if (DEBUG_TASKS) Slog.v(TAG_TASKS,
"Starting new activity " + mStartActivity + " in explicit task " + mStartActivity.task);
addOrReparentStartingActivity(mInTask, "setTaskFromInTask");
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
+ " in explicit task " + mStartActivity.task);
return START_SUCCESS;
}
@@ -1790,10 +1795,18 @@ class ActivityStarter {
final TaskRecord task = (prev != null) ? prev.task : mTargetStack.createTaskRecord(
mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId), mStartActivity.info,
mIntent, null, null, true, mStartActivity.mActivityType);
mStartActivity.setTask(task, null);
mStartActivity.task.getStack().positionChildWindowContainerAtTop(mStartActivity.task);
if (DEBUG_TASKS) Slog.v(TAG_TASKS,
"Starting new activity " + mStartActivity + " in new guessed " + mStartActivity.task);
addOrReparentStartingActivity(task, "setTaskToCurrentTopOrCreateNewTask");
mTargetStack.positionChildWindowContainerAtTop(task);
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
+ " in new guessed " + mStartActivity.task);
}
private void addOrReparentStartingActivity(TaskRecord parent, String reason) {
if (mStartActivity.task == null) {
parent.addActivityToTop(mStartActivity);
} else {
mStartActivity.reparent(parent, parent.mActivities.size() /* top */, reason);
}
}
private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,

View File

@@ -51,6 +51,7 @@ import android.util.Slog;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.util.XmlUtils;
import com.android.server.wm.AppWindowContainerController;
import com.android.server.wm.TaskWindowContainerController;
import com.android.server.wm.TaskWindowContainerListener;
@@ -1033,6 +1034,12 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta
* be in the current task or unparented to any task.
*/
void addActivityAtIndex(int index, ActivityRecord r) {
if (r.task != null && r.task != this) {
throw new IllegalArgumentException("Can not add r=" + " to task=" + this
+ " current parent=" + r.task);
}
r.task = this;
// Remove r first, and if it wasn't already in the list and it's fullscreen, count it.
if (!mActivities.remove(r) && r.fullscreen) {
// Was not previously in list.
@@ -1063,6 +1070,7 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta
}
}
index = Math.min(size, index);
mActivities.add(index, r);
updateEffectiveIntent();
if (r.isPersistable()) {
@@ -1071,7 +1079,12 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta
// Sync. with window manager
updateOverrideConfigurationFromLaunchBounds();
mWindowContainerController.positionChildAt(r.getWindowContainerController(), index);
final AppWindowContainerController appController = r.getWindowContainerController();
if (appController != null) {
// Only attempt to move in WM if the child has a controller. It is possible we haven't
// created controller for the activity we are starting yet.
mWindowContainerController.positionChildAt(appController, index);
}
r.onOverrideConfigurationSent();
}