Merge "Reparent the activity in the task with associated window containers."
This commit is contained in:
committed by
Android (Google) Code Review
commit
ffc7b78434
@@ -729,7 +729,6 @@ final class ActivityRecord implements AppWindowContainerListener {
|
||||
if (mWindowContainerController != null) {
|
||||
throw new IllegalArgumentException("Window container=" + mWindowContainerController
|
||||
+ " already created for r=" + this);
|
||||
|
||||
}
|
||||
|
||||
inHistory = true;
|
||||
@@ -754,6 +753,26 @@ final class ActivityRecord implements AppWindowContainerListener {
|
||||
mWindowContainerController = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reparents this activity into {@param newTask} at the provided {@param position}. The caller
|
||||
* should ensure that the {@param newTask} is not already the parent of this activity.
|
||||
*/
|
||||
void reparent(TaskRecord newTask, int position, String reason) {
|
||||
final TaskRecord prevTask = task;
|
||||
if (prevTask == newTask) {
|
||||
throw new IllegalArgumentException(reason + ": task=" + newTask
|
||||
+ " is already the parent of r=" + this);
|
||||
}
|
||||
|
||||
// Must reparent first in window manager
|
||||
mWindowContainerController.reparent(newTask.getWindowContainerController(), position);
|
||||
|
||||
// Remove the activity from the old task and add it to the new task
|
||||
prevTask.removeActivity(this);
|
||||
setTask(newTask, null);
|
||||
newTask.addActivityAtIndex(position, this);
|
||||
}
|
||||
|
||||
private boolean isHomeIntent(Intent intent) {
|
||||
return Intent.ACTION_MAIN.equals(intent.getAction())
|
||||
&& intent.hasCategory(Intent.CATEGORY_HOME)
|
||||
|
||||
@@ -3069,8 +3069,7 @@ final class ActivityStack extends ConfigurationContainer implements StackWindowL
|
||||
+ " to task=" + task + ":" + taskInsertionPoint);
|
||||
for (int srcPos = start; srcPos >= i; --srcPos) {
|
||||
final ActivityRecord p = activities.get(srcPos);
|
||||
p.setTask(task, null);
|
||||
task.addActivityAtIndex(taskInsertionPoint, p);
|
||||
p.reparent(task, taskInsertionPoint, "resetAffinityTaskIfNeededLocked");
|
||||
|
||||
if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE,
|
||||
"Removing and adding activity " + p + " to stack at " + task
|
||||
@@ -5097,12 +5096,17 @@ final class ActivityStack extends ConfigurationContainer implements StackWindowL
|
||||
final boolean wasResumed = wasFocused && (prevStack.mResumedActivity == r);
|
||||
final boolean wasPaused = prevStack.mPausingActivity == r;
|
||||
|
||||
// Create a new task for the activity to be parented in
|
||||
final TaskRecord task = createTaskRecord(
|
||||
mStackSupervisor.getNextTaskIdForUserLocked(r.userId),
|
||||
r.info, r.intent, null, null, true, r.mActivityType);
|
||||
r.setTask(task, null);
|
||||
task.addActivityToTop(r);
|
||||
// This is a new task, so reparenting it to position 0 will move it to the top
|
||||
r.reparent(task, 0 /* position */, "moveActivityToStack");
|
||||
|
||||
// Notify the task actiivties if it was moved to/from a pinned stack
|
||||
mStackSupervisor.scheduleReportPictureInPictureModeChangedIfNeeded(task, prevStack);
|
||||
|
||||
// Resume the activity if necessary after it has moved
|
||||
moveToFrontAndResumeStateIfNeeded(r, wasFocused, wasResumed, wasPaused,
|
||||
"moveActivityToStack");
|
||||
if (wasResumed) {
|
||||
|
||||
@@ -1028,8 +1028,10 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta
|
||||
addActivityAtIndex(mActivities.size(), r);
|
||||
}
|
||||
|
||||
// TODO: Figure-out if any of the call points expect the window container to be reparented and
|
||||
// correct them to use the right method.
|
||||
/**
|
||||
* Adds an activity {@param r} at the given {@param index}. The activity {@param r} must either
|
||||
* be in the current task or unparented to any task.
|
||||
*/
|
||||
void addActivityAtIndex(int index, ActivityRecord r) {
|
||||
// Remove r first, and if it wasn't already in the list and it's fullscreen, count it.
|
||||
if (!mActivities.remove(r) && r.fullscreen) {
|
||||
|
||||
@@ -41,6 +41,7 @@ import android.util.Slog;
|
||||
import android.view.IApplicationToken;
|
||||
import android.view.WindowManagerPolicy.StartingSurface;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.AttributeCache;
|
||||
/**
|
||||
* Controller for the app window token container. This is created by activity manager to link
|
||||
@@ -202,7 +203,7 @@ public class AppWindowContainerController
|
||||
+ " controller=" + taskController);
|
||||
}
|
||||
|
||||
atoken = new AppWindowToken(mService, token, voiceInteraction, task.getDisplayContent(),
|
||||
atoken = createAppWindow(mService, token, voiceInteraction, task.getDisplayContent(),
|
||||
inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdkVersion,
|
||||
requestedOrientation, rotationAnimationHint, configChanges, launchTaskBehind,
|
||||
alwaysFocusable, this);
|
||||
@@ -212,6 +213,18 @@ public class AppWindowContainerController
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
AppWindowToken createAppWindow(WindowManagerService service, IApplicationToken token,
|
||||
boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
|
||||
boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
|
||||
int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
|
||||
boolean alwaysFocusable, AppWindowContainerController controller) {
|
||||
return new AppWindowToken(service, token, voiceInteraction, dc,
|
||||
inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk, orientation,
|
||||
rotationAnimationHint, configChanges, launchTaskBehind, alwaysFocusable,
|
||||
controller);
|
||||
}
|
||||
|
||||
public void removeContainer(int displayId) {
|
||||
synchronized(mWindowMap) {
|
||||
final DisplayContent dc = mRoot.getDisplayContent(displayId);
|
||||
@@ -230,6 +243,25 @@ public class AppWindowContainerController
|
||||
throw new UnsupportedOperationException("Use removeContainer(displayId) instead.");
|
||||
}
|
||||
|
||||
public void reparent(TaskWindowContainerController taskController, int position) {
|
||||
synchronized (mWindowMap) {
|
||||
if (DEBUG_ADD_REMOVE) Slog.i(TAG_WM, "reparent: moving app token=" + mToken
|
||||
+ " to task=" + taskController + " at " + position);
|
||||
if (mContainer == null) {
|
||||
if (DEBUG_ADD_REMOVE) Slog.i(TAG_WM,
|
||||
"reparent: could not find app token=" + mToken);
|
||||
return;
|
||||
}
|
||||
final Task task = taskController.mContainer;
|
||||
if (task == null) {
|
||||
throw new IllegalArgumentException("reparent: could not find task="
|
||||
+ taskController);
|
||||
}
|
||||
mContainer.reparent(task, position);
|
||||
mContainer.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
|
||||
}
|
||||
}
|
||||
|
||||
public Configuration setOrientation(int requestedOrientation, int displayId,
|
||||
Configuration displayConfig, boolean freezeScreenIfNeeded) {
|
||||
synchronized(mWindowMap) {
|
||||
|
||||
@@ -850,6 +850,27 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
|
||||
}
|
||||
}
|
||||
|
||||
void reparent(Task task, int position) {
|
||||
if (task == mTask) {
|
||||
throw new IllegalArgumentException(
|
||||
"window token=" + this + " already child of task=" + mTask);
|
||||
}
|
||||
if (DEBUG_ADD_REMOVE) Slog.i(TAG, "reParentWindowToken: removing window token=" + this
|
||||
+ " from task=" + mTask);
|
||||
final DisplayContent prevDisplayContent = getDisplayContent();
|
||||
|
||||
getParent().removeChild(this);
|
||||
task.addChild(this, position);
|
||||
|
||||
// Relayout display(s).
|
||||
final DisplayContent displayContent = task.getDisplayContent();
|
||||
displayContent.setLayoutNeeded();
|
||||
if (prevDisplayContent != displayContent) {
|
||||
onDisplayChanged(displayContent);
|
||||
prevDisplayContent.setLayoutNeeded();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean canFreezeBounds() {
|
||||
// For freeform windows, we can't freeze the bounds at the moment because this would make
|
||||
// the resizing unresponsive.
|
||||
|
||||
@@ -29,6 +29,7 @@ import static android.content.res.Configuration.EMPTY;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* Test class for {@link AppWindowContainerController}.
|
||||
@@ -135,9 +136,50 @@ public class AppWindowContainerControllerTests extends WindowTestsBase {
|
||||
assertHasStartingWindow(controller2.getAppWindowToken());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReparent() throws Exception {
|
||||
final TestTaskWindowContainerController taskController1 =
|
||||
new TestTaskWindowContainerController(
|
||||
createStackControllerOnDisplay(sDisplayContent));
|
||||
final TestAppWindowContainerController appWindowController1 = createAppWindowController(
|
||||
taskController1);
|
||||
final TestTaskWindowContainerController taskController2 =
|
||||
new TestTaskWindowContainerController(
|
||||
createStackControllerOnDisplay(sDisplayContent));
|
||||
final TestAppWindowContainerController appWindowController2 = createAppWindowController(
|
||||
taskController2);
|
||||
final TestTaskWindowContainerController taskController3 =
|
||||
new TestTaskWindowContainerController(
|
||||
createStackControllerOnDisplay(sDisplayContent));
|
||||
|
||||
try {
|
||||
appWindowController1.reparent(taskController1, 0);
|
||||
fail("Should not be able to reparent to the same parent");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// Expected
|
||||
}
|
||||
|
||||
try {
|
||||
taskController3.setContainer(null);
|
||||
appWindowController1.reparent(taskController3, 0);
|
||||
fail("Should not be able to reparent to a task that doesn't have a container");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// Expected
|
||||
}
|
||||
|
||||
// Reparent the app window and ensure that it is moved
|
||||
appWindowController1.reparent(taskController2, 0);
|
||||
assertEquals(taskController2.mContainer, appWindowController1.mContainer.getParent());
|
||||
assertEquals(0, ((TestAppWindowToken) appWindowController1.mContainer).positionInParent());
|
||||
assertEquals(1, ((TestAppWindowToken) appWindowController2.mContainer).positionInParent());
|
||||
}
|
||||
|
||||
private TestAppWindowContainerController createAppWindowController() {
|
||||
final TestTaskWindowContainerController taskController =
|
||||
new TestTaskWindowContainerController();
|
||||
return createAppWindowController(new TestTaskWindowContainerController());
|
||||
}
|
||||
|
||||
private TestAppWindowContainerController createAppWindowController(
|
||||
TestTaskWindowContainerController taskController) {
|
||||
return new TestAppWindowContainerController(taskController);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,6 +242,16 @@ class WindowTestsBase {
|
||||
super(sWm, null, false, dc);
|
||||
}
|
||||
|
||||
TestAppWindowToken(WindowManagerService service, IApplicationToken token,
|
||||
boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
|
||||
boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
|
||||
int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
|
||||
boolean alwaysFocusable, AppWindowContainerController controller) {
|
||||
super(service, token, voiceInteraction, dc, inputDispatchingTimeoutNanos, fullscreen,
|
||||
showForAllUsers, targetSdk, orientation, rotationAnimationHint, configChanges,
|
||||
launchTaskBehind, alwaysFocusable, controller);
|
||||
}
|
||||
|
||||
int getWindowsCount() {
|
||||
return mChildren.size();
|
||||
}
|
||||
@@ -257,6 +267,10 @@ class WindowTestsBase {
|
||||
WindowState getLastChild() {
|
||||
return mChildren.getLast();
|
||||
}
|
||||
|
||||
int positionInParent() {
|
||||
return getParent().mChildren.indexOf(this);
|
||||
}
|
||||
}
|
||||
|
||||
/* Used so we can gain access to some protected members of the {@link Task} class */
|
||||
@@ -357,6 +371,19 @@ class WindowTestsBase {
|
||||
mToken = token;
|
||||
}
|
||||
|
||||
@Override
|
||||
AppWindowToken createAppWindow(WindowManagerService service, IApplicationToken token,
|
||||
boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
|
||||
boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
|
||||
int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
|
||||
boolean alwaysFocusable, AppWindowContainerController controller) {
|
||||
return new TestAppWindowToken(service, token, voiceInteraction, dc,
|
||||
inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk,
|
||||
orientation,
|
||||
rotationAnimationHint, configChanges, launchTaskBehind, alwaysFocusable,
|
||||
controller);
|
||||
}
|
||||
|
||||
AppWindowToken getAppWindowToken() {
|
||||
return (AppWindowToken) sDisplayContent.getWindowToken(mToken.asBinder());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user