Merge "Reparent the activity in the task with associated window containers."

This commit is contained in:
TreeHugger Robot
2017-01-27 19:05:54 +00:00
committed by Android (Google) Code Review
7 changed files with 157 additions and 10 deletions

View File

@@ -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)

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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.

View File

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

View File

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