diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index 767deb98379ab3d75f3b830d7fa1134c06d2784c..f32717a3bea96955354adfa8c01e731507e91036 100644 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -779,11 +779,13 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo * @param task The new parent {@link TaskRecord}. */ void setTask(TaskRecord task) { - setTask(task, false /*reparenting*/); + setTask(task /* task */, false /* reparenting */); } /** * This method should only be called by {@link TaskRecord#removeActivity(ActivityRecord)}. + * @param task The new parent task. + * @param reparenting Whether we're in the middle of reparenting. */ void setTask(TaskRecord task, boolean reparenting) { // Do nothing if the {@link TaskRecord} is the same as the current {@link getTask}. @@ -791,12 +793,19 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo return; } - final ActivityStack stack = getStack(); + final ActivityStack oldStack = getStack(); + final ActivityStack newStack = task != null ? task.getStack() : null; + + // Inform old stack (if present) of activity removal and new stack (if set) of activity + // addition. + if (oldStack != newStack) { + if (!reparenting && oldStack != null) { + oldStack.onActivityRemovedFromStack(this); + } - // If the new {@link TaskRecord} is from a different {@link ActivityStack}, remove this - // {@link ActivityRecord} from its current {@link ActivityStack}. - if (!reparenting && stack != null && (task == null || stack != task.getStack())) { - stack.onActivityRemovedFromStack(this); + if (newStack != null) { + newStack.onActivityAddedToStack(this); + } } this.task = task; @@ -1073,8 +1082,15 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo // Must reparent first in window manager mWindowContainerController.reparent(newTask.getWindowContainerController(), position); + // Reparenting prevents informing the parent stack of activity removal in the case that + // the new stack has the same parent. we must manually signal here if this is not the case. + final ActivityStack prevStack = prevTask.getStack(); + + if (prevStack != newTask.getStack()) { + prevStack.onActivityRemovedFromStack(this); + } // Remove the activity from the old task and add it to the new task. - prevTask.removeActivity(this, true /*reparenting*/); + prevTask.removeActivity(this, true /* reparenting */); newTask.addActivityAtIndex(position, this); } diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 4fd77a5c1504e056a56df41989fd91d3aa82e55d..eb482c1b14e279f256551d921e8010108798540d 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -489,13 +489,13 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai */ void onActivityStateChanged(ActivityRecord record, ActivityState state, String reason) { if (record == mResumedActivity && state != RESUMED) { - clearResumedActivity(reason + " - onActivityStateChanged"); + setResumedActivity(null, reason + " - onActivityStateChanged"); } if (state == RESUMED) { if (DEBUG_STACK) Slog.v(TAG_STACK, "set resumed activity to:" + record + " reason:" + reason); - mResumedActivity = record; + setResumedActivity(record, reason + " - onActivityStateChanged"); mService.setResumedActivityUncheckLocked(record, reason); mStackSupervisor.mRecentTasks.add(record.getTask()); } @@ -2309,14 +2309,14 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai return mResumedActivity; } - /** - * Clears reference to currently resumed activity. - */ - private void clearResumedActivity(String reason) { - if (DEBUG_STACK) Slog.d(TAG_STACK, "clearResumedActivity: " + mResumedActivity + " reason:" - + reason); + private void setResumedActivity(ActivityRecord r, String reason) { + if (mResumedActivity == r) { + return; + } - mResumedActivity = null; + if (DEBUG_STACK) Slog.d(TAG_STACK, "setResumedActivity stack:" + this + " + from: " + + mResumedActivity + " to:" + r + " reason:" + reason); + mResumedActivity = r; } @GuardedBy("mService") @@ -4022,14 +4022,20 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai * an activity moves away from the stack. */ void onActivityRemovedFromStack(ActivityRecord r) { - if (mResumedActivity == r) { - clearResumedActivity("onActivityRemovedFromStack"); + removeTimeoutsForActivityLocked(r); + + if (mResumedActivity != null && mResumedActivity == r) { + setResumedActivity(null, "onActivityRemovedFromStack"); } - if (mPausingActivity == r) { + if (mPausingActivity != null && mPausingActivity == r) { mPausingActivity = null; } + } - removeTimeoutsForActivityLocked(r); + void onActivityAddedToStack(ActivityRecord r) { + if(r.getState() == RESUMED) { + setResumedActivity(r, "onActivityAddedToStack"); + } } /** diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java index 737105d8bdf1193f005d652fb34ea2612c9826c2..0e418ad4cb88517e6b9591f6f4da63e2920dc8cb 100644 --- a/services/core/java/com/android/server/am/TaskRecord.java +++ b/services/core/java/com/android/server/am/TaskRecord.java @@ -927,7 +927,26 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi if (stack != null && !stack.isInStackLocked(this)) { throw new IllegalStateException("Task must be added as a Stack child first."); } + final ActivityStack oldStack = mStack; mStack = stack; + + // If the new {@link TaskRecord} is from a different {@link ActivityStack}, remove this + // {@link ActivityRecord} from its current {@link ActivityStack}. + + if (oldStack != mStack) { + for (int i = getChildCount() - 1; i >= 0; --i) { + final ActivityRecord activity = getChildAt(i); + + if (oldStack != null) { + oldStack.onActivityRemovedFromStack(activity); + } + + if (mStack != null) { + stack.onActivityAddedToStack(activity); + } + } + } + onParentChanged(); } @@ -1232,6 +1251,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi index = Math.min(size, index); mActivities.add(index, r); + updateEffectiveIntent(); if (r.isPersistable()) { mService.notifyTaskPersisterLocked(this, false); @@ -1257,7 +1277,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi * @return true if this was the last activity in the task. */ boolean removeActivity(ActivityRecord r) { - return removeActivity(r, false /*reparenting*/); + return removeActivity(r, false /* reparenting */); } boolean removeActivity(ActivityRecord r, boolean reparenting) { @@ -1266,7 +1286,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi "Activity=" + r + " does not belong to task=" + this); } - r.setTask(null /*task*/, reparenting); + r.setTask(null /* task */, reparenting /* reparenting */); if (mActivities.remove(r) && r.fullscreen) { // Was previously in list. diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java index c78fcd3858fcd657e2be8d5ba330ddc8a15281a6..4b8dcc1e56c1a15e091c38337299f7e9692ff69d 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java @@ -103,7 +103,42 @@ public class ActivityStackTests extends ActivityTestsBase { assertEquals(mStack.getResumedActivity(), r); r.setState(PAUSING, "testResumedActivity"); assertEquals(mStack.getResumedActivity(), null); + } + + @Test + public void testResumedActivityFromTaskReparenting() { + final ActivityRecord r = new ActivityBuilder(mService).setTask(mTask).build(); + // Ensure moving task between two stacks updates resumed activity + r.setState(RESUMED, "testResumedActivityFromTaskReparenting"); + assertEquals(mStack.getResumedActivity(), r); + + final ActivityStack destStack = mService.mStackSupervisor.getDefaultDisplay().createStack( + WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); + + mTask.reparent(destStack, true /* toTop */, TaskRecord.REPARENT_KEEP_STACK_AT_FRONT, + false /* animate */, true /* deferResume*/, + "testResumedActivityFromTaskReparenting"); + + assertEquals(mStack.getResumedActivity(), null); + assertEquals(destStack.getResumedActivity(), r); + } + + @Test + public void testResumedActivityFromActivityReparenting() { + final ActivityRecord r = new ActivityBuilder(mService).setTask(mTask).build(); + // Ensure moving task between two stacks updates resumed activity + r.setState(RESUMED, "testResumedActivityFromActivityReparenting"); + assertEquals(mStack.getResumedActivity(), r); + final ActivityStack destStack = mService.mStackSupervisor.getDefaultDisplay().createStack( + WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); + final TaskRecord destTask = new TaskBuilder(mSupervisor).setStack(destStack).build(); + + mTask.removeActivity(r); + destTask.addActivityToTop(r); + + assertEquals(mStack.getResumedActivity(), null); + assertEquals(destStack.getResumedActivity(), r); } @Test @@ -543,5 +578,4 @@ public class ActivityStackTests extends ActivityTestsBase { assertEquals(expected, mStack.shouldSleepActivities()); } - }