Added StackWindowContainerController
For linking ActivityStack in AMS to TaskStack window container in WMS.
Change-Id: I8b9eaef49e62854d59b22d27f80f5935a5a4d7fc
Bug: 30060889
Test: bit FrameworksServicesTests:com.android.server.wm.StackWindowContainerControllerTests
Test: bit FrameworksServicesTests:com.android.server.wm.TaskWindowContainerControllerTests
Test: Existing test pass and manual testing.
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 19edb5c..c789f8c 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -135,9 +135,6 @@
// ids that were affected by the update, ActivityManager should resize these stacks.
int[] setNewDisplayOverrideConfiguration(in Configuration overrideConfig, int displayId);
- // Retrieves the new bounds after the configuration update evaluated by window manager.
- Rect getBoundsForNewConfiguration(int stackId);
-
void startFreezingScreen(int exitAnim, int enterAnim);
void stopFreezingScreen();
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index f6fbaf9..128536f 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -7625,12 +7625,11 @@
final float aspectRatio = r.pictureInPictureArgs.getAspectRatio();
final List<RemoteAction> actions = r.pictureInPictureArgs.getActions();
final Rect bounds = isValidPictureInPictureAspectRatio(aspectRatio)
- ? mWindowManager.getPictureInPictureBounds(DEFAULT_DISPLAY,
- aspectRatio)
+ ? mWindowManager.getPictureInPictureBounds(DEFAULT_DISPLAY, aspectRatio)
: mWindowManager.getPictureInPictureDefaultBounds(DEFAULT_DISPLAY);
mStackSupervisor.moveActivityToPinnedStackLocked(r, "enterPictureInPictureMode",
bounds, true /* moveHomeStackToFront */);
- mWindowManager.setPictureInPictureActions(actions);
+ mStackSupervisor.getStack(PINNED_STACK_ID).setPictureInPictureActions(actions);
};
if (isKeyguardLocked()) {
@@ -7678,12 +7677,11 @@
// Only update the saved args from the args that are set
r.pictureInPictureArgs.copyOnlySet(args);
- if (r.getStack().getStackId() == PINNED_STACK_ID) {
+ final ActivityStack stack = r.getStack();
+ if (stack.getStackId() == PINNED_STACK_ID) {
// If the activity is already in picture-in-picture, update the pinned stack now
- mWindowManager.setPictureInPictureAspectRatio(
- r.pictureInPictureArgs.getAspectRatio());
- mWindowManager.setPictureInPictureActions(
- r.pictureInPictureArgs.getActions());
+ stack.setPictureInPictureAspectRatio(r.pictureInPictureArgs.getAspectRatio());
+ stack.setPictureInPictureActions(r.pictureInPictureArgs.getActions());
}
}
} finally {
@@ -10221,7 +10219,9 @@
synchronized (this) {
if (animate) {
if (stackId == PINNED_STACK_ID) {
- mWindowManager.animateResizePinnedStack(bounds, animationDuration);
+ final ActivityStack pinnedStack =
+ mStackSupervisor.getStack(PINNED_STACK_ID);
+ pinnedStack.animateResizePinnedStack(bounds, animationDuration);
} else {
throw new IllegalArgumentException("Stack: " + stackId
+ " doesn't support animated resize.");
@@ -19593,7 +19593,7 @@
/** Helper method that requests bounds from WM and applies them to stack. */
private void resizeStackWithBoundsFromWindowManager(int stackId, boolean deferResume) {
- final Rect newBounds = mWindowManager.getBoundsForNewConfiguration(stackId);
+ final Rect newBounds = mStackSupervisor.getStack(stackId).getBoundsForNewConfiguration();
mStackSupervisor.resizeStackLocked(
stackId, newBounds, null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
false /* preserveWindows */, false /* allowResizeInDockedMode */, deferResume);
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 7bfea9a..973951e 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -80,6 +80,7 @@
import android.app.ActivityOptions;
import android.app.AppGlobals;
import android.app.IActivityController;
+import android.app.RemoteAction;
import android.app.ResultInfo;
import android.content.ComponentName;
import android.content.Intent;
@@ -114,6 +115,8 @@
import com.android.server.Watchdog;
import com.android.server.am.ActivityManagerService.ItemMatcher;
import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
+import com.android.server.wm.StackWindowController;
+import com.android.server.wm.StackWindowListener;
import com.android.server.wm.WindowManagerService;
import java.io.FileDescriptor;
@@ -128,7 +131,7 @@
/**
* State and management of a single stack of activities.
*/
-final class ActivityStack extends ConfigurationContainer {
+final class ActivityStack extends ConfigurationContainer implements StackWindowListener {
private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStack" : TAG_AM;
private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
@@ -240,6 +243,7 @@
final ActivityManagerService mService;
private final WindowManagerService mWindowManager;
+ private StackWindowController mWindowContainerController;
private final RecentTasks mRecentTasks;
/**
@@ -328,7 +332,7 @@
private final SparseArray<Configuration> mTmpConfigs = new SparseArray<>();
private final SparseArray<Rect> mTmpBounds = new SparseArray<>();
private final SparseArray<Rect> mTmpInsetBounds = new SparseArray<>();
- private final Rect tempRect2 = new Rect();
+ private final Rect mTmpRect2 = new Rect();
/** Run all ActivityStacks through this */
private final ActivityStackSupervisor mStackSupervisor;
@@ -441,7 +445,7 @@
}
ActivityStack(ActivityStackSupervisor.ActivityContainer activityContainer,
- RecentTasks recentTasks) {
+ RecentTasks recentTasks, boolean onTop) {
mActivityContainer = activityContainer;
mStackSupervisor = activityContainer.getOuter();
mService = mStackSupervisor.mService;
@@ -452,13 +456,25 @@
mRecentTasks = recentTasks;
mTaskPositioner = mStackId == FREEFORM_WORKSPACE_STACK_ID
? new LaunchingTaskPositioner() : null;
+ final ActivityStackSupervisor.ActivityDisplay display = mActivityContainer.mActivityDisplay;
+ mTmpRect2.setEmpty();
+ mWindowContainerController = new StackWindowController(mStackId, this,
+ display.mDisplayId, onTop, mTmpRect2);
+ activityContainer.mStack = this;
+ mStackSupervisor.mActivityContainers.put(mStackId, activityContainer);
+ postAddToDisplay(display, mTmpRect2.isEmpty() ? null : mTmpRect2, onTop);
+ }
+
+ StackWindowController getWindowContainerController() {
+ return mWindowContainerController;
}
/** Adds the stack to specified display and calls WindowManager to do the same. */
- void addToDisplay(ActivityStackSupervisor.ActivityDisplay activityDisplay, boolean onTop) {
- final Rect bounds = mWindowManager.addStackToDisplay(mStackId, activityDisplay.mDisplayId,
- onTop);
- postAddToDisplay(activityDisplay, bounds);
+ void reparent(ActivityStackSupervisor.ActivityDisplay activityDisplay, boolean onTop) {
+ removeFromDisplay();
+ mTmpRect2.setEmpty();
+ mWindowContainerController.reparent(activityDisplay.mDisplayId, mTmpRect2);
+ postAddToDisplay(activityDisplay, mTmpRect2.isEmpty() ? null : mTmpRect2, onTop);
}
/**
@@ -467,10 +483,10 @@
* @param bounds Updated bounds.
*/
private void postAddToDisplay(ActivityStackSupervisor.ActivityDisplay activityDisplay,
- Rect bounds) {
+ Rect bounds, boolean onTop) {
mDisplayId = activityDisplay.mDisplayId;
mStacks = activityDisplay.mStacks;
- mBounds = bounds;
+ mBounds = bounds != null ? new Rect(bounds) : null;
mFullscreen = mBounds == null;
if (mTaskPositioner != null) {
mTaskPositioner.setDisplay(activityDisplay.mDisplay);
@@ -478,6 +494,7 @@
}
onParentChanged();
+ activityDisplay.attachStack(this, onTop);
if (mStackId == DOCKED_STACK_ID) {
// If we created a docked stack we want to resize it so it resizes all other stacks
// in the system.
@@ -487,16 +504,6 @@
}
/**
- * Moves the stack to specified display.
- * @param activityDisplay Target display to move the stack to.
- */
- void moveToDisplay(ActivityStackSupervisor.ActivityDisplay activityDisplay) {
- removeFromDisplay();
- final Rect bounds = mWindowManager.moveStackToDisplay(mStackId, activityDisplay.mDisplayId);
- postAddToDisplay(activityDisplay, bounds);
- }
-
- /**
* Updates the inner state of the stack to remove it from its current parent, so it can be
* either destroyed completely or re-parented.
*/
@@ -518,7 +525,8 @@
void remove() {
removeFromDisplay();
mStackSupervisor.deleteActivityContainerRecord(mStackId);
- mWindowManager.removeStack(mStackId);
+ mWindowContainerController.removeContainer();
+ mWindowContainerController = null;
onParentChanged();
}
@@ -526,6 +534,42 @@
mActivityContainer.mActivityDisplay.mDisplay.getSize(out);
}
+ void animateResizePinnedStack(Rect bounds, int animationDuration) {
+ mWindowContainerController.animateResizePinnedStack(bounds, animationDuration);
+ }
+
+ void setPictureInPictureAspectRatio(float aspectRatio) {
+ mWindowContainerController.setPictureInPictureAspectRatio(aspectRatio);
+ }
+
+ void getStackDockedModeBounds(Rect outBounds, boolean ignoreVisibility) {
+ mWindowContainerController.getStackDockedModeBounds(outBounds, ignoreVisibility);
+ }
+
+ void prepareFreezingTaskBounds() {
+ mWindowContainerController.prepareFreezingTaskBounds();
+ }
+
+ void setPictureInPictureActions(List<RemoteAction> actions) {
+ mWindowContainerController.setPictureInPictureActions(actions);
+ }
+
+ void getWindowContainerBounds(Rect outBounds) {
+ if (mWindowContainerController != null) {
+ mWindowContainerController.getBounds(outBounds);
+ }
+ outBounds.setEmpty();
+ }
+
+ Rect getBoundsForNewConfiguration() {
+ return mWindowContainerController.getBoundsForNewConfiguration();
+ }
+
+ void positionChildWindowContainerAtTop(TaskRecord child) {
+ mWindowContainerController.positionChildAtTop(child.getWindowContainerController(),
+ true /* includingParents */);
+ }
+
/**
* Defers updating the bounds of the stack. If the stack was resized/repositioned while
* deferring, the bounds will update in {@link #continueUpdateBounds()}.
@@ -546,8 +590,7 @@
final boolean wasDeferred = mUpdateBoundsDeferred;
mUpdateBoundsDeferred = false;
if (wasDeferred && mUpdateBoundsDeferredCalled) {
- mStackSupervisor.resizeStackUncheckedLocked(this,
- mDeferredBounds.isEmpty() ? null : mDeferredBounds,
+ resize(mDeferredBounds.isEmpty() ? null : mDeferredBounds,
mDeferredTaskBounds.isEmpty() ? null : mDeferredTaskBounds,
mDeferredTaskInsetBounds.isEmpty() ? null : mDeferredTaskInsetBounds);
}
@@ -765,7 +808,8 @@
task = topTask();
if (task != null) {
- task.moveWindowContainerToTop(true /* includingParents */);
+ mWindowContainerController.positionChildAtTop(task.getWindowContainerController(),
+ true /* includingParents */);
}
}
@@ -784,7 +828,7 @@
mTaskHistory.remove(task);
mTaskHistory.add(0, task);
updateTaskMovement(task, false);
- task.moveWindowContainerToBottom();
+ mWindowContainerController.positionChildAtBottom(task.getWindowContainerController());
}
}
@@ -2578,7 +2622,8 @@
position = getAdjustedPositionForTask(task, position, null /* starting */);
mTaskHistory.remove(task);
mTaskHistory.add(position, task);
- task.positionWindowContainerAt(position);
+ mWindowContainerController.positionChildAt(task.getWindowContainerController(), position,
+ task.mBounds, task.getOverrideConfiguration());
updateTaskMovement(task, true);
}
@@ -2590,7 +2635,8 @@
final int position = getAdjustedPositionForTask(task, mTaskHistory.size(), starting);
mTaskHistory.add(position, task);
updateTaskMovement(task, true);
- task.moveWindowContainerToTop(true /* includingParents */);
+ mWindowContainerController.positionChildAtTop(task.getWindowContainerController(),
+ true /* includingParents */);
}
private void updateTaskReturnToForTopInsertion(TaskRecord task) {
@@ -2618,7 +2664,7 @@
// This also makes sure that non-home activities are visible under a transparent
// non-home activity.
task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
- } else if (!isHomeOrRecentsStack() && (fromHomeOrRecents || topTask != task)) {
+ } else if (!isHomeOrRecentsStack() && (fromHomeOrRecents || topTask() != task)) {
// If it's a last task over home - we default to keep its return to type not to
// make underlying task focused when this one will be finished.
int returnToType = isLastTaskOverHome
@@ -2868,7 +2914,8 @@
targetTask.addActivityAtBottom(p);
}
- targetTask.moveWindowContainerToBottom();
+ mWindowContainerController.positionChildAtBottom(
+ targetTask.getWindowContainerController());
replyChainEnd = -1;
} else if (forceReset || finishOnTaskLaunch || clearWhenTaskReset) {
// If the activity should just be removed -- either
@@ -3004,7 +3051,8 @@
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Pulling activity " + p
+ " from " + srcPos + " in to resetting task " + task);
}
- task.moveWindowContainerToTop(true /* includingParents */);
+ mWindowContainerController.positionChildAtTop(
+ task.getWindowContainerController(), true /* includingParents */);
// Now we've moved it in to place... but what if this is
// a singleTop activity and we have put it on top of another
@@ -4373,7 +4421,7 @@
}
mWindowManager.prepareAppTransition(TRANSIT_TASK_TO_BACK, false);
- tr.moveWindowContainerToBottom();
+ mWindowContainerController.positionChildAtBottom(tr.getWindowContainerController());
final TaskRecord task = mResumedActivity != null ? mResumedActivity.task : null;
if (prevIsHome || (task == tr && canGoHome) || (numTasks <= 1 && isOnHomeDisplay())) {
@@ -4436,11 +4484,24 @@
}
}
- /** Update override configurations of all tasks in the stack. */
- void updateOverrideConfiguration(Rect stackBounds, Rect tempTaskBounds,
- Rect tempTaskInsetBounds) {
+ // TODO: Figure-out a way to consolidate with resize() method below.
+ @Override
+ public void requestResize(Rect bounds) {
+ mService.resizeStack(mStackId, bounds, true /* allowResizeInDockedMode */,
+ false /* preserveWindows */, false /* animate */, -1 /* animationDuration */);
+ }
- final Rect taskBounds = tempTaskBounds != null ? tempTaskBounds : stackBounds;
+ // TODO: Can only be called from special methods in ActivityStackSupervisor.
+ // Need to consolidate those calls points into this resize method so anyone can call directly.
+ void resize(Rect bounds, Rect tempTaskBounds, Rect tempTaskInsetBounds) {
+ bounds = TaskRecord.validateBounds(bounds);
+
+ if (!updateBoundsAllowed(bounds, tempTaskBounds, tempTaskInsetBounds)) {
+ return;
+ }
+
+ // Update override configurations of all tasks in the stack.
+ final Rect taskBounds = tempTaskBounds != null ? tempTaskBounds : bounds;
final Rect insetBounds = tempTaskInsetBounds != null ? tempTaskInsetBounds : taskBounds;
mTmpBounds.clear();
@@ -4454,9 +4515,9 @@
// For freeform stack we don't adjust the size of the tasks to match that
// of the stack, but we do try to make sure the tasks are still contained
// with the bounds of the stack.
- tempRect2.set(task.mBounds);
- fitWithinBounds(tempRect2, stackBounds);
- task.updateOverrideConfiguration(tempRect2);
+ mTmpRect2.set(task.mBounds);
+ fitWithinBounds(mTmpRect2, bounds);
+ task.updateOverrideConfiguration(mTmpRect2);
} else {
task.updateOverrideConfiguration(taskBounds, insetBounds);
}
@@ -4469,11 +4530,9 @@
}
}
- // We might trigger a configuration change. Save the current task bounds for freezing.
- mWindowManager.prepareFreezingTaskBounds(mStackId);
- mFullscreen = mWindowManager.resizeStack(mStackId, stackBounds, mTmpConfigs, mTmpBounds,
+ mFullscreen = mWindowContainerController.resize(bounds, mTmpConfigs, mTmpBounds,
mTmpInsetBounds);
- setBounds(stackBounds);
+ setBounds(bounds);
}
@@ -4897,7 +4956,8 @@
addTask(task, toTop ? MAX_VALUE : 0, reason);
if (toTop) {
// TODO: figure-out a way to remove this call.
- task.moveWindowContainerToTop(true /* includingParents */);
+ mWindowContainerController.positionChildAtTop(task.getWindowContainerController(),
+ true /* includingParents */);
}
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 24ff1d7..29032f8 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -376,7 +376,7 @@
// TODO: Add listener for removal of references.
/** Mapping from (ActivityStack/TaskStack).mStackId to their current state */
- private SparseArray<ActivityContainer> mActivityContainers = new SparseArray<>();
+ SparseArray<ActivityContainer> mActivityContainers = new SparseArray<>();
/** Mapping from displayId to display current state */
private final SparseArray<ActivityDisplay> mActivityDisplays = new SparseArray<>();
@@ -2198,7 +2198,7 @@
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeStack_" + stackId);
mWindowManager.deferSurfaceLayout();
try {
- resizeStackUncheckedLocked(stack, bounds, tempTaskBounds, tempTaskInsetBounds);
+ stack.resize(bounds, tempTaskBounds, tempTaskInsetBounds);
if (!deferResume) {
stack.ensureVisibleActivitiesConfigurationLocked(
stack.topRunningActivityLocked(), preserveWindows);
@@ -2236,17 +2236,6 @@
mResizingTasksDuringAnimation.clear();
}
- void resizeStackUncheckedLocked(ActivityStack stack, Rect bounds, Rect tempTaskBounds,
- Rect tempTaskInsetBounds) {
- bounds = TaskRecord.validateBounds(bounds);
-
- if (!stack.updateBoundsAllowed(bounds, tempTaskBounds, tempTaskInsetBounds)) {
- return;
- }
-
- stack.updateOverrideConfiguration(bounds, tempTaskBounds, tempTaskInsetBounds);
- }
-
void moveTasksToFullscreenStackLocked(int fromStackId, boolean onTop) {
final ActivityStack stack = getStack(fromStackId);
if (stack == null) {
@@ -2340,8 +2329,7 @@
// Don't allow re-entry while resizing. E.g. due to docked stack detaching.
mAllowDockedStackResize = false;
ActivityRecord r = stack.topRunningActivityLocked();
- resizeStackUncheckedLocked(stack, dockedBounds, tempDockedTaskBounds,
- tempDockedTaskInsetBounds);
+ stack.resize(dockedBounds, tempDockedTaskBounds, tempDockedTaskInsetBounds);
// TODO: Checking for isAttached might not be needed as if the user passes in null
// dockedBounds then they want the docked stack to be dismissed.
@@ -2358,10 +2346,10 @@
// static stacks need to be adjusted so they don't overlap with the docked stack.
// We get the bounds to use from window manager which has been adjusted for any
// screen controls and is also the same for all stacks.
- mWindowManager.getStackDockedModeBounds(
- HOME_STACK_ID, tempRect, true /* ignoreVisibility */);
for (int i = FIRST_STATIC_STACK_ID; i <= LAST_STATIC_STACK_ID; i++) {
- if (StackId.isResizeableByDockedStack(i) && getStack(i) != null) {
+ final ActivityStack current = getStack(i);
+ if (current != null && StackId.isResizeableByDockedStack(i)) {
+ current.getStackDockedModeBounds(tempRect, true /* ignoreVisibility */);
resizeStackLocked(i, tempRect, tempOtherTaskBounds,
tempOtherTaskInsetBounds, preserveWindows,
true /* allowResizeInDockedMode */, deferResume);
@@ -2394,8 +2382,7 @@
mWindowManager.deferSurfaceLayout();
try {
ActivityRecord r = stack.topRunningActivityLocked();
- resizeStackUncheckedLocked(stack, pinnedBounds, tempPinnedTaskBounds,
- null);
+ stack.resize(pinnedBounds, tempPinnedTaskBounds, null);
stack.ensureVisibleActivitiesConfigurationLocked(r, false);
} finally {
mWindowManager.continueSurfaceLayout();
@@ -2404,14 +2391,13 @@
}
ActivityStack createStackOnDisplay(int stackId, int displayId, boolean onTop) {
- ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
+ final ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
if (activityDisplay == null) {
return null;
}
- ActivityContainer activityContainer = new ActivityContainer(stackId);
- mActivityContainers.put(stackId, activityContainer);
- activityContainer.addToDisplayLocked(activityDisplay, onTop);
+ final ActivityContainer activityContainer =
+ new ActivityContainer(stackId, activityDisplay, onTop);
return activityContainer.mStack;
}
@@ -2770,7 +2756,8 @@
}
// We might trigger a configuration change. Save the current task bounds for freezing.
- mWindowManager.prepareFreezingTaskBounds(stack.mStackId);
+ // TODO: Should this call be moved inside the resize method in WM?
+ stack.prepareFreezingTaskBounds();
// Make sure the task has the appropriate bounds/size for the stack it is in.
if (stackId == FULLSCREEN_WORKSPACE_STACK_ID && task.mBounds != null) {
@@ -2839,7 +2826,11 @@
void moveActivityToPinnedStackLocked(ActivityRecord r, String reason, Rect bounds,
boolean moveHomeStackToFront) {
+
mWindowManager.deferSurfaceLayout();
+ // Need to make sure the pinned stack exist so we can resize it below...
+ final ActivityStack stack = getStack(PINNED_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
+
try {
final TaskRecord task = r.task;
@@ -2849,9 +2840,6 @@
requestVisibleBehindLocked(r, false);
}
- // Need to make sure the pinned stack exist so we can resize it below...
- final ActivityStack stack = getStack(PINNED_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
-
// Resize the pinned stack to match the current size of the task the activity we are
// going to be moving is currently contained in. We do this to have the right starting
// animation bounds for the pinned stack to the desired bounds the caller wants.
@@ -2891,7 +2879,7 @@
ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
resumeFocusedStackTopActivityLocked();
- mWindowManager.animateResizePinnedStack(bounds, -1);
+ stack.animateResizePinnedStack(bounds, -1);
mService.mTaskChangeNotificationController.notifyActivityPinned();
}
@@ -3356,7 +3344,7 @@
stack.switchUserLocked(userId);
TaskRecord task = stack.topTask();
if (task != null) {
- task.moveWindowContainerToTop(true /* includingParents */);
+ stack.positionChildWindowContainerAtTop(task);
}
}
}
@@ -3794,7 +3782,7 @@
private StackInfo getStackInfoLocked(ActivityStack stack) {
final ActivityDisplay display = mActivityDisplays.get(DEFAULT_DISPLAY);
StackInfo info = new StackInfo();
- mWindowManager.getStackBounds(stack.mStackId, info.bounds);
+ stack.getWindowContainerBounds(info.bounds);
info.displayId = DEFAULT_DISPLAY;
info.stackId = stack.mStackId;
info.userId = stack.mCurrentUser;
@@ -4320,7 +4308,7 @@
FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION;
final int mStackId;
IActivityContainerCallback mCallback = null;
- final ActivityStack mStack;
+ ActivityStack mStack;
ActivityRecord mParentActivity = null;
String mIdString;
@@ -4334,10 +4322,11 @@
final static int CONTAINER_STATE_FINISHING = 2;
int mContainerState = CONTAINER_STATE_HAS_SURFACE;
- ActivityContainer(int stackId) {
+ ActivityContainer(int stackId, ActivityDisplay activityDisplay, boolean onTop) {
synchronized (mService) {
mStackId = stackId;
- mStack = new ActivityStack(this, mRecentTasks);
+ mActivityDisplay = activityDisplay;
+ new ActivityStack(this, mRecentTasks, onTop);
mIdString = "ActivtyContainer{" + mStackId + "}";
if (DEBUG_STACK) Slog.d(TAG_STACK, "Creating " + this);
}
@@ -4345,21 +4334,18 @@
/**
* Adds the stack to specified display. Also calls WindowManager to do the same from
- * {@link ActivityStack#addToDisplay(ActivityDisplay, boolean)}.
+ * {@link ActivityStack#reparent(ActivityDisplay, boolean)}.
* @param activityDisplay The display to add the stack to.
- * @param onTop If true the stack will be place at the top of the display, else at the
- * bottom.
*/
- void addToDisplayLocked(ActivityDisplay activityDisplay, boolean onTop) {
+ void addToDisplayLocked(ActivityDisplay activityDisplay) {
if (DEBUG_STACK) Slog.d(TAG_STACK, "addToDisplayLocked: " + this
- + " to display=" + activityDisplay + " onTop=" + onTop);
+ + " to display=" + activityDisplay);
if (mActivityDisplay != null) {
throw new IllegalStateException("ActivityContainer is already attached, " +
"displayId=" + mActivityDisplay.mDisplayId);
}
mActivityDisplay = activityDisplay;
- mStack.addToDisplay(activityDisplay, onTop);
- activityDisplay.attachActivities(mStack, onTop);
+ mStack.reparent(activityDisplay, true /* onTop */);
}
@Override
@@ -4369,7 +4355,7 @@
if (activityDisplay == null) {
return;
}
- addToDisplayLocked(activityDisplay, true /* onTop */);
+ addToDisplayLocked(activityDisplay);
}
}
@@ -4446,7 +4432,7 @@
if (DEBUG_STACK) Slog.d(TAG_STACK, "removeFromDisplayLocked: " + this
+ " current displayId=" + mActivityDisplay.mDisplayId);
- mActivityDisplay.detachActivitiesLocked(mStack);
+ mActivityDisplay.detachStack(mStack);
mActivityDisplay = null;
}
@@ -4462,8 +4448,7 @@
removeFromDisplayLocked();
mActivityDisplay = activityDisplay;
- mStack.moveToDisplay(activityDisplay);
- activityDisplay.attachActivities(mStack, ON_TOP);
+ mStack.reparent(activityDisplay, ON_TOP);
}
@Override
@@ -4553,7 +4538,8 @@
boolean mDrawn = false;
VirtualActivityContainer(ActivityRecord parent, IActivityContainerCallback callback) {
- super(getNextStackId());
+ super(getNextStackId(), parent.getStack().mActivityContainer.mActivityDisplay,
+ true /* onTop */);
mParentActivity = parent;
mCallback = callback;
mContainerState = CONTAINER_STATE_NO_SURFACE;
@@ -4585,7 +4571,7 @@
new VirtualActivityDisplay(width, height, density);
mActivityDisplay = virtualActivityDisplay;
mActivityDisplays.put(virtualActivityDisplay.mDisplayId, virtualActivityDisplay);
- addToDisplayLocked(virtualActivityDisplay, true /* onTop */);
+ addToDisplayLocked(virtualActivityDisplay);
}
if (mSurface != null) {
@@ -4674,10 +4660,9 @@
mDisplayId = display.getDisplayId();
}
- void attachActivities(ActivityStack stack, boolean onTop) {
- if (DEBUG_STACK) Slog.v(TAG_STACK,
- "attachActivities: attaching " + stack + " to displayId=" + mDisplayId
- + " onTop=" + onTop);
+ void attachStack(ActivityStack stack, boolean onTop) {
+ if (DEBUG_STACK) Slog.v(TAG_STACK, "attachStack: attaching " + stack
+ + " to displayId=" + mDisplayId + " onTop=" + onTop);
if (onTop) {
mStacks.add(stack);
} else {
@@ -4685,8 +4670,8 @@
}
}
- void detachActivitiesLocked(ActivityStack stack) {
- if (DEBUG_STACK) Slog.v(TAG_STACK, "detachActivitiesLocked: detaching " + stack
+ void detachStack(ActivityStack stack) {
+ if (DEBUG_STACK) Slog.v(TAG_STACK, "detachStack: detaching " + stack
+ " from displayId=" + mDisplayId);
mStacks.remove(stack);
}
@@ -4764,8 +4749,8 @@
}
@Override
- void detachActivitiesLocked(ActivityStack stack) {
- super.detachActivitiesLocked(stack);
+ void detachStack(ActivityStack stack) {
+ super.detachStack(stack);
if (mVirtualDisplay != null) {
mVirtualDisplay.release();
mVirtualDisplay = null;
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 8d32778..b913a23 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -1835,7 +1835,7 @@
mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId), mStartActivity.info,
mIntent, null, null, true, mStartActivity.mActivityType);
mStartActivity.setTask(task, null);
- mStartActivity.task.moveWindowContainerToTop(true /* includingParents */);
+ mStartActivity.task.getStack().positionChildWindowContainerAtTop(mStartActivity.task);
if (DEBUG_TASKS) Slog.v(TAG_TASKS,
"Starting new activity " + mStartActivity + " in new guessed " + mStartActivity.task);
}
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 2373ea8..f12d7b7 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -421,9 +421,10 @@
final Rect bounds = updateOverrideConfigurationFromLaunchBounds();
final Configuration overrideConfig = getOverrideConfiguration();
- mWindowContainerController = new TaskWindowContainerController(taskId, this, getStackId(),
- userId, bounds, overrideConfig, mResizeMode, mSupportsPictureInPicture,
- isHomeTask(), isOnTopLauncher(), onTop, showForAllUsers, lastTaskDescription);
+ mWindowContainerController = new TaskWindowContainerController(taskId, this,
+ getStack().getWindowContainerController(), userId, bounds, overrideConfig,
+ mResizeMode, mSupportsPictureInPicture, isHomeTask(), isOnTopLauncher(),
+ onTop, showForAllUsers, lastTaskDescription);
}
void removeWindowContainer() {
@@ -457,6 +458,12 @@
mWindowContainerController.setTaskDockedResizing(resizing);
}
+ // TODO: Consolidate this with the resize() method below.
+ @Override
+ public void requestResize(Rect bounds, int resizeMode) {
+ mService.resizeTask(taskId, bounds, resizeMode);
+ }
+
boolean resize(Rect bounds, int resizeMode, boolean preserveWindow, boolean deferResume) {
if (!isResizeable()) {
Slog.w(TAG, "resizeTask: task " + this + " not resizeable.");
@@ -527,25 +534,6 @@
false /* forced */);
}
- // TODO: Remove once we have a stack controller.
- void positionWindowContainerAt(int position) {
- mWindowContainerController.positionAt(position, mBounds, getOverrideConfiguration());
- }
-
- // TODO: Replace with moveChildToTop?
- void moveWindowContainerToTop(boolean includingParents) {
- if (mWindowContainerController != null) {
- mWindowContainerController.moveToTop(includingParents);
- }
- }
-
- // TODO: Replace with moveChildToBottom?
- void moveWindowContainerToBottom() {
- if (mWindowContainerController != null) {
- mWindowContainerController.moveToBottom();
- }
- }
-
void getWindowContainerBounds(Rect bounds) {
mWindowContainerController.getBounds(bounds);
}
@@ -563,7 +551,7 @@
// Must reparent first in window manager to avoid a situation where AM can delete the
// we are coming from in WM before we reparent because it became empty.
- mWindowContainerController.reparent(stackId, position);
+ mWindowContainerController.reparent(newStack.getWindowContainerController(), position);
final ActivityStack prevStack = mStack;
prevStack.removeTask(this, reason, REMOVE_TASK_MODE_MOVING);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 914cc8d..3a74ded 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -57,6 +57,7 @@
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
@@ -69,6 +70,7 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS;
@@ -634,6 +636,13 @@
*/
DisplayContent(Display display, WindowManagerService service,
WindowLayersController layersController, WallpaperController wallpaperController) {
+
+ if (service.mRoot.getDisplayContent(display.getDisplayId()) != null) {
+ throw new IllegalArgumentException("Display with ID=" + display.getDisplayId()
+ + " already exists=" + service.mRoot.getDisplayContent(display.getDisplayId())
+ + " new=" + display);
+ }
+
mDisplay = display;
mDisplayId = display.getDisplayId();
mLayersController = layersController;
@@ -957,75 +966,43 @@
out.set(mContentRect);
}
- /**
- * Adds the stack to this display.
- * @see WindowManagerService#addStackToDisplay(int, int, boolean)
- */
- Rect addStackToDisplay(int stackId, boolean onTop) {
- boolean attachedToDisplay = false;
- TaskStack stack = mService.mStackIdToStack.get(stackId);
- if (stack == null) {
- if (DEBUG_STACK) Slog.d(TAG_WM, "Create new stackId=" + stackId + " on displayId="
- + mDisplayId);
+ TaskStack addStackToDisplay(int stackId, boolean onTop) {
+ if (DEBUG_STACK) Slog.d(TAG_WM, "Create new stackId=" + stackId + " on displayId="
+ + mDisplayId);
- stack = getStackById(stackId);
- if (stack != null) {
- // It's already attached to the display...clear mDeferRemoval and move stack to
- // appropriate z-order on display as needed.
- stack.mDeferRemoval = false;
- // We're not moving the display to front when we're adding stacks, only when
- // requested to change the position of stack explicitly.
- mTaskStackContainers.positionChildAt(onTop ? POSITION_TOP : POSITION_BOTTOM, stack,
- false /* includingParents */);
- attachedToDisplay = true;
- } else {
- stack = new TaskStack(mService, stackId);
- }
-
- mService.mStackIdToStack.put(stackId, stack);
- if (stackId == DOCKED_STACK_ID) {
- mDividerControllerLocked.notifyDockedStackExistsChanged(true);
- }
+ TaskStack stack = getStackById(stackId);
+ if (stack != null) {
+ // It's already attached to the display...clear mDeferRemoval and move stack to
+ // appropriate z-order on display as needed.
+ stack.mDeferRemoval = false;
+ // We're not moving the display to front when we're adding stacks, only when
+ // requested to change the position of stack explicitly.
+ mTaskStackContainers.positionChildAt(onTop ? POSITION_TOP : POSITION_BOTTOM, stack,
+ false /* includingParents */);
} else {
- final DisplayContent currentDC = stack.getDisplayContent();
- if (currentDC != null) {
- throw new IllegalStateException("Trying to add stackId=" + stackId
- + "to displayId=" + mDisplayId + ", but it's already attached to displayId="
- + currentDC.getDisplayId());
- }
- }
-
- if (!attachedToDisplay) {
+ stack = new TaskStack(mService, stackId);
mTaskStackContainers.addStackToDisplay(stack, onTop);
}
- if (stack.getRawFullscreen()) {
- return null;
+ if (stackId == DOCKED_STACK_ID) {
+ mDividerControllerLocked.notifyDockedStackExistsChanged(true);
}
- final Rect bounds = new Rect();
- stack.getRawBounds(bounds);
- return bounds;
+ return stack;
}
- /** Removes the stack from the display and prepares for changing the parent. */
- private void removeStackFromDisplay(TaskStack stack) {
- mTaskStackContainers.removeStackFromDisplay(stack);
- }
-
- /** Moves the stack to this display and returns the updated bounds. */
- Rect moveStackToDisplay(TaskStack stack) {
- final DisplayContent currentDisplayContent = stack.getDisplayContent();
- if (currentDisplayContent == null) {
+ void moveStackToDisplay(TaskStack stack) {
+ final DisplayContent prevDc = stack.getDisplayContent();
+ if (prevDc == null) {
throw new IllegalStateException("Trying to move stackId=" + stack.mStackId
+ " which is not currently attached to any display");
}
- if (stack.getDisplayContent().getDisplayId() == mDisplayId) {
+ if (prevDc.getDisplayId() == mDisplayId) {
throw new IllegalArgumentException("Trying to move stackId=" + stack.mStackId
+ " to its current displayId=" + mDisplayId);
}
- currentDisplayContent.removeStackFromDisplay(stack);
- return addStackToDisplay(stack.mStackId, true /* onTop */);
+ prevDc.mTaskStackContainers.removeStackFromDisplay(stack);
+ mTaskStackContainers.addStackToDisplay(stack, true /* onTop */);
}
@Override
@@ -1172,7 +1149,7 @@
super.removeImmediately();
if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this);
mDimLayerController.close();
- if (mDisplayId == DEFAULT_DISPLAY) {
+ if (mDisplayId == DEFAULT_DISPLAY && mService.canDispatchPointerEvents()) {
mService.unregisterPointerEventListener(mTapDetector);
mService.unregisterPointerEventListener(mService.mMousePositionTracker);
}
@@ -1250,7 +1227,7 @@
final WindowState imeWin = mService.mInputMethodWindow;
final boolean imeVisible = imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw()
&& !mDividerControllerLocked.isImeHideRequested();
- final boolean dockVisible = mService.isStackVisibleLocked(DOCKED_STACK_ID);
+ final boolean dockVisible = isStackVisible(DOCKED_STACK_ID);
final TaskStack imeTargetStack = mService.getImeFocusStackLocked();
final int imeDockSide = (dockVisible && imeTargetStack != null) ?
imeTargetStack.getDockSide() : DOCKED_INVALID;
@@ -1447,7 +1424,7 @@
* @return The docked stack, but only if it is visible, and {@code null} otherwise.
*/
TaskStack getDockedStackLocked() {
- final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
+ final TaskStack stack = getStackById(DOCKED_STACK_ID);
return (stack != null && stack.isVisible()) ? stack : null;
}
@@ -1456,7 +1433,7 @@
* visible.
*/
TaskStack getDockedStackIgnoringVisibility() {
- return mService.mStackIdToStack.get(DOCKED_STACK_ID);
+ return getStackById(DOCKED_STACK_ID);
}
/** Find the visible, touch-deliverable window under the given point */
@@ -1532,6 +1509,9 @@
}
}
+ // TODO: This should probably be called any time a visual change is made to the hierarchy like
+ // moving containers or resizing them. Need to investigate the best way to have it automatically
+ // happen so we don't run into issues with programmers forgetting to do it.
void layoutAndAssignWindowLayersIfNeeded() {
mService.mWindowsChanged = true;
setLayoutNeeded();
@@ -2441,6 +2421,27 @@
}
}
+ void setExitingTokensHasVisible(boolean hasVisible) {
+ for (int i = mExitingTokens.size() - 1; i >= 0; i--) {
+ mExitingTokens.get(i).hasVisible = hasVisible;
+ }
+
+ // Initialize state of exiting applications.
+ mTaskStackContainers.setExitingTokensHasVisible(hasVisible);
+ }
+
+ void removeExistingTokensIfPossible() {
+ for (int i = mExitingTokens.size() - 1; i >= 0; i--) {
+ final WindowToken token = mExitingTokens.get(i);
+ if (!token.hasVisible) {
+ mExitingTokens.remove(i);
+ }
+ }
+
+ // Time to remove any exiting applications?
+ mTaskStackContainers.removeExistingAppTokensIfPossible();
+ }
+
static final class TaskForResizePointSearchResult {
boolean searchDone;
Task taskForResize;
@@ -2650,10 +2651,38 @@
return false;
}
+ void setExitingTokensHasVisible(boolean hasVisible) {
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens;
+ for (int j = appTokens.size() - 1; j >= 0; --j) {
+ appTokens.get(j).hasVisible = hasVisible;
+ }
+ }
+ }
+
+ void removeExistingAppTokensIfPossible() {
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens;
+ for (int j = appTokens.size() - 1; j >= 0; --j) {
+ final AppWindowToken token = appTokens.get(j);
+ if (!token.hasVisible && !mService.mClosingApps.contains(token)
+ && (!token.mIsExiting || token.isEmpty())) {
+ // Make sure there is no animation running on this token, so any windows
+ // associated with it will be removed as soon as their animations are
+ // complete.
+ token.mAppAnimator.clearAnimation();
+ token.mAppAnimator.animating = false;
+ if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
+ "performLayout: App token exiting now removed" + token);
+ token.removeIfPossible();
+ }
+ }
+ }
+ }
+
@Override
int getOrientation() {
- if (mService.isStackVisibleLocked(DOCKED_STACK_ID)
- || mService.isStackVisibleLocked(FREEFORM_WORKSPACE_STACK_ID)) {
+ if (isStackVisible(DOCKED_STACK_ID) || isStackVisible(FREEFORM_WORKSPACE_STACK_ID)) {
// Apps and their containers are not allowed to specify an orientation while the
// docked or freeform stack is visible...except for the home stack/task if the
// docked stack is minimized and it actually set something.
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index ed1e2d9..aaf724e 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -457,8 +457,7 @@
void registerDockedStackListener(IDockedStackListener listener) {
mDockedStackListeners.register(listener);
notifyDockedDividerVisibilityChanged(wasVisible());
- notifyDockedStackExistsChanged(
- mDisplayContent.mService.mStackIdToStack.get(DOCKED_STACK_ID) != null);
+ notifyDockedStackExistsChanged(mDisplayContent.getDockedStackIgnoringVisibility() != null);
notifyDockedStackMinimizedChanged(mMinimizedDock, 0 /* animDuration */);
notifyAdjustedForImeChanged(mAdjustedForIme, 0 /* animDuration */);
@@ -466,7 +465,7 @@
void setResizeDimLayer(boolean visible, int targetStackId, float alpha) {
mService.openSurfaceTransaction();
- final TaskStack stack = mDisplayContent.mService.mStackIdToStack.get(targetStackId);
+ final TaskStack stack = mDisplayContent.getStackById(targetStackId);
final TaskStack dockedStack = mDisplayContent.getDockedStackLocked();
boolean visibleAndValid = visible && stack != null && dockedStack != null;
if (visibleAndValid) {
@@ -544,8 +543,8 @@
if (homeTask == null || !isWithinDisplay(homeTask)) {
return;
}
- final TaskStack fullscreenStack
- = mService.mStackIdToStack.get(FULLSCREEN_WORKSPACE_STACK_ID);
+ final TaskStack fullscreenStack =
+ mDisplayContent.getStackById(FULLSCREEN_WORKSPACE_STACK_ID);
final boolean homeVisible = homeTask.getTopVisibleAppToken() != null;
final boolean homeBehind = (fullscreenStack != null && fullscreenStack.isVisible())
|| (homeStack.hasMultipleTaskWithHomeTaskNotTop());
@@ -739,7 +738,7 @@
}
private boolean animateForMinimizedDockedStack(long now) {
- final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
+ final TaskStack stack = mDisplayContent.getStackById(DOCKED_STACK_ID);
if (!mAnimationStarted) {
mAnimationStarted = true;
mAnimationStartTime = now;
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 0cc6c70..22abf30 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -382,6 +382,17 @@
}
}
+ TaskStack getStackById(int stackId) {
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
+ final DisplayContent dc = mChildren.get(i);
+ final TaskStack stack = dc.getStackById(stackId);
+ if (stack != null) {
+ return stack;
+ }
+ }
+ return null;
+ }
+
void setSecureSurfaceState(int userId, boolean disabled) {
forAllWindows((w) -> {
if (w.mHasSurface && userId == UserHandle.getUserId(w.mOwnerUid)) {
@@ -535,18 +546,7 @@
final int numDisplays = mChildren.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
final DisplayContent displayContent = mChildren.get(displayNdx);
- for (i = displayContent.mExitingTokens.size() - 1; i >= 0; i--) {
- displayContent.mExitingTokens.get(i).hasVisible = false;
- }
- }
-
- for (int stackNdx = mService.mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
- // Initialize state of exiting applications.
- final AppTokenList exitingAppTokens =
- mService.mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
- for (int tokenNdx = exitingAppTokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
- exitingAppTokens.get(tokenNdx).hasVisible = false;
- }
+ displayContent.setExitingTokensHasVisible(false);
}
mHoldScreen = null;
@@ -681,33 +681,7 @@
// Time to remove any exiting tokens?
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
final DisplayContent displayContent = mChildren.get(displayNdx);
- ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens;
- for (i = exitingTokens.size() - 1; i >= 0; i--) {
- WindowToken token = exitingTokens.get(i);
- if (!token.hasVisible) {
- exitingTokens.remove(i);
- }
- }
- }
-
- // Time to remove any exiting applications?
- for (int stackNdx = mService.mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
- // Initialize state of exiting applications.
- final AppTokenList exitingAppTokens =
- mService.mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
- for (i = exitingAppTokens.size() - 1; i >= 0; i--) {
- final AppWindowToken token = exitingAppTokens.get(i);
- if (!token.hasVisible && !mService.mClosingApps.contains(token) &&
- (!token.mIsExiting || token.isEmpty())) {
- // Make sure there is no animation running on this token, so any windows
- // associated with it will be removed as soon as their animations are complete
- token.mAppAnimator.clearAnimation();
- token.mAppAnimator.animating = false;
- if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
- "performLayout: App token exiting now removed" + token);
- token.removeIfPossible();
- }
- }
+ displayContent.removeExistingTokensIfPossible();
}
if (wallpaperDestroyed) {
diff --git a/services/core/java/com/android/server/wm/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java
new file mode 100644
index 0000000..9a6f3eb5
--- /dev/null
+++ b/services/core/java/com/android/server/wm/StackWindowController.java
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import android.app.RemoteAction;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.util.Slog;
+import android.util.SparseArray;
+import com.android.server.UiThread;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.lang.ref.WeakReference;
+import java.util.List;
+
+import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
+import static com.android.server.wm.WindowContainer.POSITION_TOP;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
+/**
+ * Controller for the stack container. This is created by activity manager to link activity stacks
+ * to the stack container they use in window manager.
+ *
+ * Test class: {@link StackWindowControllerTests}
+ */
+public class StackWindowController
+ extends WindowContainerController<TaskStack, StackWindowListener> {
+
+ final int mStackId;
+
+ private final H mHandler;
+
+ public StackWindowController(int stackId, StackWindowListener listener,
+ int displayId, boolean onTop, Rect outBounds) {
+ this(stackId, listener, displayId, onTop, outBounds, WindowManagerService.getInstance());
+ }
+
+ @VisibleForTesting
+ public StackWindowController(int stackId, StackWindowListener listener,
+ int displayId, boolean onTop, Rect outBounds, WindowManagerService service) {
+ super(listener, service);
+ mStackId = stackId;
+ mHandler = new H(new WeakReference<>(this), service.mH.getLooper());
+
+ synchronized (mWindowMap) {
+ final DisplayContent dc = mRoot.getDisplayContent(displayId);
+ if (dc == null) {
+ throw new IllegalArgumentException("Trying to add stackId=" + stackId
+ + " to unknown displayId=" + displayId);
+ }
+
+ final TaskStack stack = dc.addStackToDisplay(stackId, onTop);
+ stack.setController(this);
+ getRawBounds(outBounds);
+ }
+ }
+
+ @Override
+ public void removeContainer() {
+ synchronized (mWindowMap) {
+ if (mContainer != null) {
+ mContainer.removeIfPossible();
+ super.removeContainer();
+ }
+ }
+ }
+
+ public void reparent(int displayId, Rect outStackBounds) {
+ synchronized (mWindowMap) {
+ if (mContainer == null) {
+ throw new IllegalArgumentException("Trying to move unknown stackId=" + mStackId
+ + " to displayId=" + displayId);
+ }
+
+ final DisplayContent targetDc = mRoot.getDisplayContent(displayId);
+ if (targetDc == null) {
+ throw new IllegalArgumentException("Trying to move stackId=" + mStackId
+ + " to unknown displayId=" + displayId);
+ }
+
+ targetDc.moveStackToDisplay(mContainer);
+ getRawBounds(outStackBounds);
+ }
+ }
+
+ public void positionChildAt(TaskWindowContainerController child, int position, Rect bounds,
+ Configuration overrideConfig) {
+ synchronized (mWindowMap) {
+ if (DEBUG_STACK) Slog.i(TAG_WM, "positionChildAt: positioning task=" + child
+ + " at " + position);
+ if (child.mContainer == null) {
+ if (DEBUG_STACK) Slog.i(TAG_WM,
+ "positionChildAt: could not find task=" + this);
+ return;
+ }
+ if (mContainer == null) {
+ if (DEBUG_STACK) Slog.i(TAG_WM,
+ "positionChildAt: could not find stack for task=" + mContainer);
+ return;
+ }
+ child.mContainer.positionAt(position, bounds, overrideConfig);
+ mContainer.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
+ }
+ }
+
+ public void positionChildAtTop(TaskWindowContainerController child, boolean includingParents) {
+ if (child == null) {
+ // TODO: Fix the call-points that cause this to happen.
+ return;
+ }
+
+ synchronized(mWindowMap) {
+ final Task childTask = child.mContainer;
+ if (childTask == null) {
+ Slog.e(TAG_WM, "positionChildAtTop: task=" + child + " not found");
+ return;
+ }
+ mContainer.positionChildAt(POSITION_TOP, childTask, includingParents);
+
+ if (mService.mAppTransition.isTransitionSet()) {
+ childTask.setSendingToBottom(false);
+ }
+ mContainer.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
+ }
+ }
+
+ public void positionChildAtBottom(TaskWindowContainerController child) {
+ if (child == null) {
+ // TODO: Fix the call-points that cause this to happen.
+ return;
+ }
+
+ synchronized(mWindowMap) {
+ final Task childTask = child.mContainer;
+ if (childTask == null) {
+ Slog.e(TAG_WM, "positionChildAtBottom: task=" + child + " not found");
+ return;
+ }
+ mContainer.positionChildAt(POSITION_BOTTOM, childTask, false /* includingParents */);
+
+ if (mService.mAppTransition.isTransitionSet()) {
+ childTask.setSendingToBottom(true);
+ }
+ mContainer.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
+ }
+ }
+
+ /**
+ * Re-sizes a stack and its containing tasks.
+ *
+ * @param bounds New stack bounds. Passing in null sets the bounds to fullscreen.
+ * @param configs Configurations for tasks in the resized stack, keyed by task id.
+ * @param taskBounds Bounds for tasks in the resized stack, keyed by task id.
+ * @return True if the stack is now fullscreen.
+ */
+ public boolean resize(Rect bounds, SparseArray<Configuration> configs,
+ SparseArray<Rect> taskBounds, SparseArray<Rect> taskTempInsetBounds) {
+ synchronized (mWindowMap) {
+ if (mContainer == null) {
+ throw new IllegalArgumentException("resizeStack: stack " + this + " not found.");
+ }
+ // We might trigger a configuration change. Save the current task bounds for freezing.
+ mContainer.prepareFreezingTaskBounds();
+ if (mContainer.setBounds(bounds, configs, taskBounds, taskTempInsetBounds)
+ && mContainer.isVisible()) {
+ mContainer.getDisplayContent().setLayoutNeeded();
+ mService.mWindowPlacerLocked.performSurfacePlacement();
+ }
+ return mContainer.getRawFullscreen();
+ }
+ }
+
+ // TODO: This and similar methods should be separated into PinnedStackWindowContainerController
+ public void animateResizePinnedStack(final Rect bounds, final int animationDuration) {
+ synchronized (mWindowMap) {
+ if (mContainer == null) {
+ throw new IllegalArgumentException("Pinned stack container not found :(");
+ }
+ final Rect originalBounds = new Rect();
+ mContainer.getBounds(originalBounds);
+ mContainer.setAnimatingBounds(bounds);
+ UiThread.getHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ mService.mBoundsAnimationController.animateBounds(
+ mContainer, originalBounds, bounds, animationDuration);
+ }
+ });
+ }
+ }
+
+ /** Sets the current picture-in-picture aspect ratio. */
+ public void setPictureInPictureAspectRatio(float aspectRatio) {
+ synchronized (mWindowMap) {
+ if (!mService.mSupportsPictureInPicture || mContainer == null) {
+ return;
+ }
+
+ final int displayId = mContainer.getDisplayContent().getDisplayId();
+ final Rect toBounds = mService.getPictureInPictureBounds(displayId, aspectRatio);
+ animateResizePinnedStack(toBounds, -1 /* duration */);
+ }
+ }
+
+ public void getStackDockedModeBounds(Rect outBounds, boolean ignoreVisibility) {
+ synchronized (mWindowMap) {
+ if (mContainer != null) {
+ mContainer.getStackDockedModeBoundsLocked(outBounds, ignoreVisibility);
+ return;
+ }
+ outBounds.setEmpty();
+ }
+ }
+
+ public void prepareFreezingTaskBounds() {
+ synchronized (mWindowMap) {
+ if (mContainer == null) {
+ throw new IllegalArgumentException("prepareFreezingTaskBounds: stack " + this
+ + " not found.");
+ }
+ mContainer.prepareFreezingTaskBounds();
+ }
+ }
+
+ /** Sets the current picture-in-picture actions. */
+ public void setPictureInPictureActions(List<RemoteAction> actions) {
+ synchronized (mWindowMap) {
+ if (!mService.mSupportsPictureInPicture || mContainer == null) {
+ return;
+ }
+
+ mContainer.getDisplayContent().getPinnedStackController().setActions(actions);
+ }
+ }
+
+ private void getRawBounds(Rect outBounds) {
+ if (mContainer.getRawFullscreen()) {
+ outBounds.setEmpty();
+ } else {
+ mContainer.getRawBounds(outBounds);
+ }
+ }
+
+ public void getBounds(Rect outBounds) {
+ synchronized (mWindowMap) {
+ if (mContainer != null) {
+ mContainer.getBounds(outBounds);
+ return;
+ }
+ outBounds.setEmpty();
+ }
+ }
+
+ public Rect getBoundsForNewConfiguration() {
+ synchronized(mWindowMap) {
+ final Rect outBounds = new Rect();
+ mContainer.getBoundsForNewConfiguration(outBounds);
+ return outBounds;
+ }
+ }
+
+ void requestResize(Rect bounds) {
+ mHandler.obtainMessage(H.REQUEST_RESIZE, bounds).sendToTarget();
+ }
+
+ @Override
+ public String toString() {
+ return "{StackWindowController stackId=" + mStackId + "}";
+ }
+
+ private static final class H extends Handler {
+
+ static final int REQUEST_RESIZE = 0;
+
+ private final WeakReference<StackWindowController> mController;
+
+ H(WeakReference<StackWindowController> controller, Looper looper) {
+ super(looper);
+ mController = controller;
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ final StackWindowController controller = mController.get();
+ final StackWindowListener listener = (controller != null)
+ ? controller.mListener : null;
+ if (listener == null) {
+ return;
+ }
+ switch (msg.what) {
+ case REQUEST_RESIZE:
+ listener.requestResize((Rect) msg.obj);
+ break;
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/wm/StackWindowListener.java b/services/core/java/com/android/server/wm/StackWindowListener.java
new file mode 100644
index 0000000..c763c17
--- /dev/null
+++ b/services/core/java/com/android/server/wm/StackWindowListener.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import android.graphics.Rect;
+
+/**
+ * Interface used by the creator of {@link StackWindowController} to listen to changes with
+ * the stack container.
+ */
+public interface StackWindowListener extends WindowContainerListener {
+
+ /** Called when the stack container would like its controller to resize. */
+ void requestResize(Rect bounds);
+}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index c5ed6ec..d96e1ef 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -27,7 +27,6 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import static com.android.server.wm.WindowManagerService.H.RESIZE_TASK;
import android.app.ActivityManager.StackId;
import android.app.ActivityManager.TaskDescription;
@@ -567,11 +566,10 @@
displayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
if (setBounds(mTmpRect2, getOverrideConfiguration()) != BOUNDS_CHANGE_NONE) {
- // Post message to inform activity manager of the bounds change simulating a one-way
- // call. We do this to prevent a deadlock between window manager lock and activity
- // manager lock been held.
- mService.mH.obtainMessage(RESIZE_TASK, mTaskId,
- RESIZE_MODE_SYSTEM_SCREEN_ROTATION, mBounds).sendToTarget();
+ final TaskWindowContainerController controller = getController();
+ if (controller != null) {
+ controller.requestResize(mBounds, RESIZE_MODE_SYSTEM_SCREEN_ROTATION);
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 53292bb..d3eae8c 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -35,17 +35,12 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import static com.android.server.wm.WindowManagerService.H.RESIZE_STACK;
import static com.android.server.wm.WindowManagerService.LAYER_OFFSET_DIM;
import android.app.ActivityManager.StackId;
-import android.app.IActivityManager;
import android.content.res.Configuration;
-import android.graphics.Point;
-import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.Region;
-import android.os.Debug;
import android.os.RemoteException;
import android.util.EventLog;
import android.util.Slog;
@@ -53,11 +48,9 @@
import android.view.DisplayInfo;
import android.view.Surface;
-import android.view.WindowManagerPolicy;
import com.android.internal.policy.DividerSnapAlgorithm;
import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
import com.android.internal.policy.DockedDividerUtils;
-import com.android.internal.policy.PipSnapAlgorithm;
import com.android.server.EventLogTags;
import java.io.PrintWriter;
@@ -206,14 +199,6 @@
}
}
- boolean isFullscreenBounds(Rect bounds) {
- if (mDisplayContent == null || bounds == null) {
- return true;
- }
- mDisplayContent.getLogicalDisplayRect(mTmpRect);
- return mTmpRect.equals(bounds);
- }
-
/**
* Overrides the adjusted bounds, i.e. sets temporary layout bounds which are different from
* the normal task bounds.
@@ -658,7 +643,7 @@
final Rect oldBounds = new Rect(mBounds);
Rect bounds = null;
- final TaskStack dockedStack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
+ final TaskStack dockedStack = dc.getDockedStackIgnoringVisibility();
if (mStackId == DOCKED_STACK_ID
|| (dockedStack != null && StackId.isResizeableByDockedStack(mStackId)
&& !dockedStack.fillsParent())) {
@@ -697,7 +682,7 @@
return;
}
- final TaskStack dockedStack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
+ final TaskStack dockedStack = mDisplayContent.getDockedStackIgnoringVisibility();
if (dockedStack == null) {
// Not sure why you are calling this method when there is no docked stack...
throw new IllegalStateException(
@@ -805,8 +790,12 @@
final Rect bounds = new Rect();
getStackDockedModeBoundsLocked(bounds, true /*ignoreVisibility*/);
- mService.mH.obtainMessage(RESIZE_STACK, DOCKED_STACK_ID,
- 1 /*allowResizeInDockedMode*/, bounds).sendToTarget();
+ getController().requestResize(bounds);
+ }
+
+ @Override
+ StackWindowController getController() {
+ return (StackWindowController) super.getController();
}
@Override
diff --git a/services/core/java/com/android/server/wm/TaskWindowContainerController.java b/services/core/java/com/android/server/wm/TaskWindowContainerController.java
index fbc3389..11667c0 100644
--- a/services/core/java/com/android/server/wm/TaskWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/TaskWindowContainerController.java
@@ -27,6 +27,8 @@
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
+import java.lang.ref.WeakReference;
+
import static com.android.server.EventLogTags.WM_TASK_CREATED;
import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
@@ -43,43 +45,38 @@
public class TaskWindowContainerController
extends WindowContainerController<Task, TaskWindowContainerListener> {
- private static final int REPORT_SNAPSHOT_CHANGED = 0;
-
private final int mTaskId;
-
- private final Handler mHandler = new Handler(Looper.getMainLooper()) {
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case REPORT_SNAPSHOT_CHANGED:
- if (mListener != null) {
- mListener.onSnapshotChanged((TaskSnapshot) msg.obj);
- }
- break;
- }
- }
- };
+ private final H mHandler;
public TaskWindowContainerController(int taskId, TaskWindowContainerListener listener,
- int stackId, int userId, Rect bounds, Configuration overrideConfig, int resizeMode,
- boolean supportsPictureInPicture, boolean homeTask, boolean isOnTopLauncher,
- boolean toTop, boolean showForAllUsers, TaskDescription taskDescription) {
- super(listener, WindowManagerService.getInstance());
+ StackWindowController stackController, int userId, Rect bounds,
+ Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture,
+ boolean homeTask, boolean isOnTopLauncher, boolean toTop, boolean showForAllUsers,
+ TaskDescription taskDescription) {
+ this(taskId, listener, stackController, userId, bounds, overrideConfig, resizeMode,
+ supportsPictureInPicture, homeTask, isOnTopLauncher, toTop, showForAllUsers,
+ taskDescription, WindowManagerService.getInstance());
+ }
+
+ public TaskWindowContainerController(int taskId, TaskWindowContainerListener listener,
+ StackWindowController stackController, int userId, Rect bounds,
+ Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture,
+ boolean homeTask, boolean isOnTopLauncher, boolean toTop, boolean showForAllUsers,
+ TaskDescription taskDescription, WindowManagerService service) {
+ super(listener, service);
mTaskId = taskId;
+ mHandler = new H(new WeakReference<>(this), service.mH.getLooper());
synchronized(mWindowMap) {
if (DEBUG_STACK) Slog.i(TAG_WM, "TaskWindowContainerController: taskId=" + taskId
- + " stackId=" + stackId + " bounds=" + bounds);
+ + " stack=" + stackController + " bounds=" + bounds);
- // TODO: Pass controller for the stack to get the container object when stack is
- // switched to use controller.
- final TaskStack stack = mService.mStackIdToStack.get(stackId);
+ final TaskStack stack = stackController.mContainer;
if (stack == null) {
- throw new IllegalArgumentException("TaskWindowContainerController: invalid stackId="
- + stackId);
+ throw new IllegalArgumentException("TaskWindowContainerController: invalid stack="
+ + stackController);
}
- EventLog.writeEvent(WM_TASK_CREATED, taskId, stackId);
+ EventLog.writeEvent(WM_TASK_CREATED, taskId, stack.mStackId);
final Task task = createTask(taskId, stack, userId, bounds, overrideConfig, resizeMode,
supportsPictureInPicture, homeTask, isOnTopLauncher, taskDescription);
final int position = toTop ? POSITION_TOP : POSITION_BOTTOM;
@@ -124,21 +121,22 @@
}
}
- public void reparent(int stackId, int position) {
+ public void reparent(StackWindowController stackController, int position) {
synchronized (mWindowMap) {
if (DEBUG_STACK) Slog.i(TAG_WM, "reparent: moving taskId=" + mTaskId
- + " to stackId=" + stackId + " at " + position);
+ + " to stack=" + stackController + " at " + position);
if (mContainer == null) {
if (DEBUG_STACK) Slog.i(TAG_WM,
"reparent: could not find taskId=" + mTaskId);
return;
}
- final TaskStack stack = mService.mStackIdToStack.get(stackId);
+ final TaskStack stack = stackController.mContainer;
if (stack == null) {
- throw new IllegalArgumentException("reparent: could not find stackId=" + stackId);
+ throw new IllegalArgumentException("reparent: could not find stack="
+ + stackController);
}
mContainer.reparent(stack, position);
- mService.mWindowPlacerLocked.performSurfacePlacement();
+ mContainer.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
}
}
@@ -158,68 +156,11 @@
}
if (mContainer.resizeLocked(bounds, overrideConfig, forced) && relayout) {
- mContainer.getDisplayContent().setLayoutNeeded();
- mService.mWindowPlacerLocked.performSurfacePlacement();
+ mContainer.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
}
}
}
- // TODO: Move to positionChildAt() in stack controller once we have a stack controller.
- public void positionAt(int position, Rect bounds, Configuration overrideConfig) {
- synchronized (mWindowMap) {
- if (DEBUG_STACK) Slog.i(TAG_WM, "positionChildAt: positioning taskId=" + mTaskId
- + " at " + position);
- if (mContainer == null) {
- if (DEBUG_STACK) Slog.i(TAG_WM,
- "positionAt: could not find taskId=" + mTaskId);
- return;
- }
- final TaskStack stack = mContainer.mStack;
- if (stack == null) {
- if (DEBUG_STACK) Slog.i(TAG_WM,
- "positionAt: could not find stack for task=" + mContainer);
- return;
- }
- mContainer.positionAt(position, bounds, overrideConfig);
- final DisplayContent displayContent = stack.getDisplayContent();
- displayContent.setLayoutNeeded();
- mService.mWindowPlacerLocked.performSurfacePlacement();
- }
- }
-
- // TODO: Replace with moveChildToTop in stack controller?
- public void moveToTop(boolean includingParents) {
- synchronized(mWindowMap) {
- if (mContainer == null) {
- Slog.e(TAG_WM, "moveToTop: taskId=" + mTaskId + " not found");
- return;
- }
- final TaskStack stack = mContainer.mStack;
- stack.positionChildAt(POSITION_TOP, mContainer, includingParents);
-
- if (mService.mAppTransition.isTransitionSet()) {
- mContainer.setSendingToBottom(false);
- }
- stack.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
- }
- }
-
- // TODO: Replace with moveChildToBottom in stack controller?
- public void moveToBottom() {
- synchronized(mWindowMap) {
- if (mContainer == null) {
- Slog.e(TAG_WM, "moveTaskToBottom: taskId=" + mTaskId + " not found");
- return;
- }
- final TaskStack stack = mContainer.mStack;
- stack.positionChildAt(POSITION_BOTTOM, mContainer, false /* includingParents */);
- if (mService.mAppTransition.isTransitionSet()) {
- mContainer.setSendingToBottom(true);
- }
- stack.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
- }
- }
-
public void getBounds(Rect bounds) {
synchronized (mWindowMap) {
if (mContainer != null) {
@@ -276,11 +217,46 @@
}
void reportSnapshotChanged(TaskSnapshot snapshot) {
- mHandler.obtainMessage(REPORT_SNAPSHOT_CHANGED, snapshot).sendToTarget();
+ mHandler.obtainMessage(H.REPORT_SNAPSHOT_CHANGED, snapshot).sendToTarget();
+ }
+
+ void requestResize(Rect bounds, int resizeMode) {
+ mHandler.obtainMessage(H.REQUEST_RESIZE, resizeMode, 0, bounds).sendToTarget();
}
@Override
public String toString() {
return "{TaskWindowContainerController taskId=" + mTaskId + "}";
}
+
+ private static final class H extends Handler {
+
+ static final int REPORT_SNAPSHOT_CHANGED = 0;
+ static final int REQUEST_RESIZE = 1;
+
+ private final WeakReference<TaskWindowContainerController> mController;
+
+ H(WeakReference<TaskWindowContainerController> controller, Looper looper) {
+ super(looper);
+ mController = controller;
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ final TaskWindowContainerController controller = mController.get();
+ final TaskWindowContainerListener listener = (controller != null)
+ ? controller.mListener : null;
+ if (listener == null) {
+ return;
+ }
+ switch (msg.what) {
+ case REPORT_SNAPSHOT_CHANGED:
+ listener.onSnapshotChanged((TaskSnapshot) msg.obj);
+ break;
+ case REQUEST_RESIZE:
+ listener.requestResize((Rect) msg.obj, msg.arg1);
+ break;
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/TaskWindowContainerListener.java b/services/core/java/com/android/server/wm/TaskWindowContainerListener.java
index 61b202d..af67de3 100644
--- a/services/core/java/com/android/server/wm/TaskWindowContainerListener.java
+++ b/services/core/java/com/android/server/wm/TaskWindowContainerListener.java
@@ -17,14 +17,17 @@
package com.android.server.wm;
import android.app.ActivityManager.TaskSnapshot;
+import android.graphics.Rect;
/**
- * Interface used by the creator of the controller to listen to changes with the container.
+ * Interface used by the creator of {@link TaskWindowContainerController} to listen to changes with
+ * the task container.
*/
public interface TaskWindowContainerListener extends WindowContainerListener {
- /**
- * Called when the snapshot of this task has changed.
- */
+ /** Called when the snapshot of this task has changed. */
void onSnapshotChanged(TaskSnapshot snapshot);
+
+ /** Called when the task container would like its controller to resize. */
+ void requestResize(Rect bounds, int resizeMode);
}
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index feceb8e..c32e689 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -447,7 +447,7 @@
private void findWallpaperTarget(DisplayContent dc) {
mFindResults.reset();
- if (mService.isStackVisibleLocked(FREEFORM_WORKSPACE_STACK_ID)) {
+ if (dc.isStackVisible(FREEFORM_WORKSPACE_STACK_ID)) {
// In freeform mode we set the wallpaper as its own target, so we don't need an
// additional window to make it visible.
mFindResults.setUseTopWallpaperAsTarget(true);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index c8f4bd2..1987f90 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -706,12 +706,7 @@
final WindowAnimator mAnimator;
- private final BoundsAnimationController mBoundsAnimationController;
-
- /** All of the TaskStacks in the window manager, unordered. For an ordered list call
- * DisplayContent.getStacks(). */
- // TODO: Don't believe this is needed with the WindowContainer model.
- SparseArray<TaskStack> mStackIdToStack = new SparseArray<>();
+ final BoundsAnimationController mBoundsAnimationController;
private final PointerEventDispatcher mPointerEventDispatcher;
@@ -2573,16 +2568,6 @@
}
}
- @Override
- public Rect getBoundsForNewConfiguration(int stackId) {
- synchronized(mWindowMap) {
- final TaskStack stack = mStackIdToStack.get(stackId);
- final Rect outBounds = new Rect();
- stack.getBoundsForNewConfiguration(outBounds);
- return outBounds;
- }
- }
-
void setFocusTaskRegionLocked() {
final Task focusedTask = mFocusedApp != null ? mFocusedApp.mTask : null;
if (focusedTask != null) {
@@ -2827,11 +2812,6 @@
}
}
- boolean isStackVisibleLocked(int stackId) {
- final TaskStack stack = mStackIdToStack.get(stackId);
- return (stack != null && stack.isVisible());
- }
-
public void setDockedStackCreateState(int mode, Rect bounds) {
synchronized (mWindowMap) {
setDockedStackCreateStateLocked(mode, bounds);
@@ -2880,17 +2860,19 @@
}
final Rect stackBounds;
- final DisplayContent displayContent;
- final TaskStack stack = mStackIdToStack.get(PINNED_STACK_ID);
+ final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
+ if (displayContent == null) {
+ return null;
+ }
+
+ final TaskStack stack = displayContent.getStackById(PINNED_STACK_ID);
if (stack != null) {
// If the stack exists, then use its final bounds to calculate the new aspect ratio
// bounds.
- displayContent = stack.getDisplayContent();
stackBounds = new Rect();
stack.getAnimatingBounds(stackBounds);
} else {
// Otherwise, just calculate the aspect ratio bounds from the default bounds
- displayContent = mRoot.getDisplayContent(displayId);
stackBounds = displayContent.getPinnedStackController().getDefaultBounds();
}
return displayContent.getPinnedStackController().getAspectRatioBounds(stackBounds,
@@ -2898,119 +2880,10 @@
}
}
- /**
- * Sets the current picture-in-picture aspect ratio.
- */
- public void setPictureInPictureAspectRatio(float aspectRatio) {
- synchronized (mWindowMap) {
- final TaskStack stack = mStackIdToStack.get(PINNED_STACK_ID);
- if (!mSupportsPictureInPicture || stack == null) {
- return;
- }
-
- final int displayId = stack.getDisplayContent().getDisplayId();
- final Rect toBounds = getPictureInPictureBounds(displayId, aspectRatio);
- animateResizePinnedStack(toBounds, -1 /* duration */);
- }
- }
-
- /**
- * Sets the current picture-in-picture actions.
- */
- public void setPictureInPictureActions(List<RemoteAction> actions) {
- synchronized (mWindowMap) {
- final TaskStack stack = mStackIdToStack.get(PINNED_STACK_ID);
- if (!mSupportsPictureInPicture || stack == null) {
- return;
- }
-
- stack.getDisplayContent().getPinnedStackController().setActions(actions);
- }
- }
-
- /**
- * Place a TaskStack on a DisplayContent. Will create a new TaskStack if none is found with
- * specified stackId.
- * @param stackId The unique identifier of the new stack.
- * @param displayId The unique identifier of the DisplayContent.
- * @param onTop If true the stack will be place at the top of the display,
- * else at the bottom.
- * @return The bounds that the stack has after adding. null means fullscreen.
- */
- public Rect addStackToDisplay(int stackId, int displayId, boolean onTop) {
- final long origId = Binder.clearCallingIdentity();
- try {
- synchronized (mWindowMap) {
- final DisplayContent dc = mRoot.getDisplayContent(displayId);
- if (dc == null) {
- throw new IllegalArgumentException("Trying to add stackId=" + stackId
- + " to unknown displayId=" + displayId);
- }
-
- return dc.addStackToDisplay(stackId, onTop);
- }
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
- }
-
- /**
- * Move a TaskStack from current DisplayContent to specified one.
- * @param stackId The unique identifier of the new stack.
- * @param displayId The unique identifier of the new display.
- */
- public Rect moveStackToDisplay(int stackId, int displayId) {
- final long origId = Binder.clearCallingIdentity();
- try {
- synchronized (mWindowMap) {
- TaskStack stack = mStackIdToStack.get(stackId);
- if (stack == null) {
- throw new IllegalArgumentException("Trying to move unknown stackId=" + stackId
- + " to displayId=" + displayId);
- }
-
- final DisplayContent targetDisplayContent = mRoot.getDisplayContent(displayId);
- if (targetDisplayContent == null) {
- throw new IllegalArgumentException("Trying to move stackId=" + stackId
- + " to unknown displayId=" + displayId);
- }
-
- return targetDisplayContent.moveStackToDisplay(stack);
- }
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
- }
-
- /**
- * Remove a TaskStack completely.
- * @param stackId The unique identifier of the stack.
- */
- public void removeStack(int stackId) {
- synchronized (mWindowMap) {
- final TaskStack stack = mStackIdToStack.get(stackId);
- if (stack != null) {
- stack.removeIfPossible();
- mStackIdToStack.remove(stackId);
- }
- }
- }
-
- public void getStackDockedModeBounds(int stackId, Rect bounds, boolean ignoreVisibility) {
- synchronized (mWindowMap) {
- final TaskStack stack = mStackIdToStack.get(stackId);
- if (stack != null) {
- stack.getStackDockedModeBoundsLocked(bounds, ignoreVisibility);
- return;
- }
- bounds.setEmpty();
- }
- }
-
@Override
public void getStackBounds(int stackId, Rect bounds) {
synchronized (mWindowMap) {
- final TaskStack stack = mStackIdToStack.get(stackId);
+ final TaskStack stack = mRoot.getStackById(stackId);
if (stack != null) {
stack.getBounds(bounds);
return;
@@ -3035,43 +2908,6 @@
}
/**
- * Re-sizes a stack and its containing tasks.
- * @param stackId Id of stack to resize.
- * @param bounds New stack bounds. Passing in null sets the bounds to fullscreen.
- * @param configs Configurations for tasks in the resized stack, keyed by task id.
- * @param taskBounds Bounds for tasks in the resized stack, keyed by task id.
- * @return True if the stack is now fullscreen.
- * */
- public boolean resizeStack(int stackId, Rect bounds,
- SparseArray<Configuration> configs, SparseArray<Rect> taskBounds,
- SparseArray<Rect> taskTempInsetBounds) {
- synchronized (mWindowMap) {
- final TaskStack stack = mStackIdToStack.get(stackId);
- if (stack == null) {
- throw new IllegalArgumentException("resizeStack: stackId " + stackId
- + " not found.");
- }
- if (stack.setBounds(bounds, configs, taskBounds, taskTempInsetBounds)
- && stack.isVisible()) {
- stack.getDisplayContent().setLayoutNeeded();
- mWindowPlacerLocked.performSurfacePlacement();
- }
- return stack.getRawFullscreen();
- }
- }
-
- public void prepareFreezingTaskBounds(int stackId) {
- synchronized (mWindowMap) {
- final TaskStack stack = mStackIdToStack.get(stackId);
- if (stack == null) {
- throw new IllegalArgumentException("prepareFreezingTaskBounds: stackId " + stackId
- + " not found.");
- }
- stack.prepareFreezingTaskBounds();
- }
- }
-
- /**
* Starts deferring layout passes. Useful when doing multiple changes but to optimize
* performance, only one layout pass should be done. This can be called multiple times, and
* layouting will be resumed once the last caller has called {@link #continueSurfaceLayout}
@@ -3505,8 +3341,9 @@
// Notify whether the docked stack exists for the current user
final DisplayContent displayContent = getDefaultDisplayContentLocked();
- displayContent.mDividerControllerLocked
- .notifyDockedStackExistsChanged(hasDockedTasksForUser(newUserId));
+ final TaskStack stack = displayContent.getDockedStackIgnoringVisibility();
+ displayContent.mDividerControllerLocked.notifyDockedStackExistsChanged(
+ stack != null && stack.hasTaskForUser(newUserId));
// If the display is already prepared, update the density.
// Otherwise, we'll update it when it's prepared.
@@ -3519,15 +3356,6 @@
}
}
- /** Returns whether there is a docked task for the current user. */
- boolean hasDockedTasksForUser(int userId) {
- final TaskStack stack = mStackIdToStack.get(DOCKED_STACK_ID);
- if (stack == null) {
- return false;
- }
- return stack.hasTaskForUser(userId);
- }
-
/* Called by WindowState */
boolean isCurrentProfileLocked(int userId) {
if (userId == mCurrentUserId) return true;
@@ -5417,8 +5245,6 @@
public static final int UPDATE_DOCKED_STACK_DIVIDER = 41;
- public static final int RESIZE_STACK = 42;
- public static final int RESIZE_TASK = 43;
public static final int TEAR_DOWN_DRAG_AND_DROP_INPUT = 44;
public static final int WINDOW_REPLACEMENT_TIMEOUT = 46;
@@ -5844,23 +5670,6 @@
}
}
break;
- case RESIZE_TASK: {
- try {
- mActivityManager.resizeTask(msg.arg1, (Rect) msg.obj, msg.arg2);
- } catch (RemoteException e) {
- // This will not happen since we are in the same process.
- }
- }
- break;
- case RESIZE_STACK: {
- try {
- mActivityManager.resizeStack(
- msg.arg1, (Rect) msg.obj, msg.arg2 == 1, false, false, -1);
- } catch (RemoteException e) {
- // This will not happen since we are in the same process.
- }
- }
- break;
case WINDOW_REPLACEMENT_TIMEOUT: {
synchronized (mWindowMap) {
for (int i = mWindowReplacementTimeouts.size() - 1; i >= 0; i--) {
@@ -7646,26 +7455,6 @@
}
}
- public void animateResizePinnedStack(final Rect bounds, final int animationDuration) {
- synchronized (mWindowMap) {
- final TaskStack stack = mStackIdToStack.get(PINNED_STACK_ID);
- if (stack == null) {
- Slog.w(TAG, "animateResizePinnedStack: stackId " + PINNED_STACK_ID + " not found.");
- return;
- }
- final Rect originalBounds = new Rect();
- stack.getBounds(originalBounds);
- stack.setAnimatingBounds(bounds);
- UiThread.getHandler().post(new Runnable() {
- @Override
- public void run() {
- mBoundsAnimationController.animateBounds(
- stack, originalBounds, bounds, animationDuration);
- }
- });
- }
- }
-
public void setForceResizableTasks(boolean forceResizableTasks) {
synchronized (mWindowMap) {
mForceResizableTasks = forceResizableTasks;
@@ -8123,7 +7912,8 @@
@Override
public boolean isStackVisible(int stackId) {
synchronized (mWindowMap) {
- return WindowManagerService.this.isStackVisibleLocked(stackId);
+ final DisplayContent dc = getDefaultDisplayContentLocked();
+ return dc.isStackVisible(stackId);
}
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 10aebe6..13358da8 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2304,6 +2304,7 @@
final WindowState win = mService.windowForClientLocked(mSession, mClient, false);
Slog.i(TAG, "WIN DEATH: " + win);
if (win != null) {
+ final DisplayContent dc = getDisplayContent();
if (win.mAppToken != null && win.mAppToken.findMainWindow() == win) {
mService.mTaskSnapshotController.onAppDied(win.mAppToken);
}
@@ -2313,7 +2314,7 @@
// just in case they have the divider at an unstable position. Better
// also reset drag resizing state, because the owner can't do it
// anymore.
- final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
+ final TaskStack stack = dc.getDockedStackIgnoringVisibility();
if (stack != null) {
stack.resetDockedStackToMiddle();
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
index 1d9875f..154fa91 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -119,6 +119,7 @@
sWm.mRoot.performSurfacePlacement(false /* recoveringMemory */);
assertEquals(SCREEN_ORIENTATION_REVERSE_LANDSCAPE, sWm.mLastOrientation);
assertTrue(appWindow.resizeReported);
+ appWindow.removeImmediately();
}
@Test
@@ -148,5 +149,6 @@
sWm.updateRotation(false, false);
sWm.mRoot.performSurfacePlacement(false /* recoveringMemory */);
assertTrue(appWindow.resizeReported);
+ appWindow.removeImmediately();
}
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
index 85931e8..e54e319 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -236,7 +236,7 @@
assertEquals(dc, token.getDisplayContent());
// Move stack to first display.
- sWm.moveStackToDisplay(stack.mStackId, sDisplayContent.getDisplayId());
+ sDisplayContent.moveStackToDisplay(stack);
assertEquals(sDisplayContent.getDisplayId(), stack.getDisplayContent().getDisplayId());
assertEquals(sDisplayContent, stack.getParent().getParent());
assertEquals(sDisplayContent, stack.getDisplayContent());
diff --git a/services/tests/servicestests/src/com/android/server/wm/StackWindowControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/StackWindowControllerTests.java
new file mode 100644
index 0000000..7a789d4
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/StackWindowControllerTests.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
+
+import android.graphics.Rect;
+import android.hardware.display.DisplayManagerGlobal;
+import android.view.Display;
+import android.view.DisplayInfo;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test class for {@link StackWindowController}.
+ *
+ * Build/Install/Run:
+ * bit FrameworksServicesTests:com.android.server.wm.StackWindowControllerTests
+ */
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class StackWindowControllerTests extends WindowTestsBase {
+ @Test
+ public void testRemoveContainer() throws Exception {
+ final StackWindowController stackController =
+ createStackControllerOnDisplay(sDisplayContent);
+ final TestTaskWindowContainerController taskController =
+ new TestTaskWindowContainerController(stackController);
+
+ final TaskStack stack = stackController.mContainer;
+ final Task task = taskController.mContainer;
+ assertNotNull(stack);
+ assertNotNull(task);
+ stackController.removeContainer();
+ // Assert that the container was removed.
+ assertNull(stackController.mContainer);
+ assertNull(taskController.mContainer);
+ assertNull(stack.getDisplayContent());
+ assertNull(task.getDisplayContent());
+ assertNull(task.mStack);
+ }
+
+ @Test
+ public void testRemoveContainer_deferRemoval() throws Exception {
+ final StackWindowController stackController =
+ createStackControllerOnDisplay(sDisplayContent);
+ final TestTaskWindowContainerController taskController =
+ new TestTaskWindowContainerController(stackController);
+
+ final TaskStack stack = stackController.mContainer;
+ final TestTask task = (TestTask) taskController.mContainer;
+ // Stack removal is deferred if one of its child is animating.
+ task.setLocalIsAnimating(true);
+
+ stackController.removeContainer();
+ // For the case of deferred removal the stack controller will no longer be connected to the
+ // container, but the task controller will still be connected to the its container until
+ // the stack window container is removed.
+ assertNull(stackController.mContainer);
+ assertNull(stack.getController());
+ assertNotNull(taskController.mContainer);
+ assertNotNull(task.getController());
+
+ stack.removeImmediately();
+ assertNull(taskController.mContainer);
+ assertNull(task.getController());
+ }
+
+ @Test
+ public void testReparent() throws Exception {
+ // Create first stack on primary display.
+ final StackWindowController stack1Controller =
+ createStackControllerOnDisplay(sDisplayContent);
+ final TaskStack stack1 = stack1Controller.mContainer;
+ final TestTaskWindowContainerController taskController =
+ new TestTaskWindowContainerController(stack1Controller);
+ final TestTask task1 = (TestTask) taskController.mContainer;
+ task1.mOnDisplayChangedCalled = false;
+
+ // Create second display and put second stack on it.
+ final Display display = new Display(DisplayManagerGlobal.getInstance(),
+ sDisplayContent.getDisplayId() + 1, new DisplayInfo(), DEFAULT_DISPLAY_ADJUSTMENTS);
+ final DisplayContent dc = new DisplayContent(display, sWm, sLayersController,
+ new WallpaperController(sWm));
+ sWm.mRoot.addChild(dc, 1);
+
+ final StackWindowController stack2Controller =
+ createStackControllerOnDisplay(dc);
+ final TaskStack stack2 = stack2Controller.mContainer;
+
+ // Reparent
+ stack1Controller.reparent(dc.getDisplayId(), new Rect());
+ assertEquals(dc, stack1.getDisplayContent());
+ final int stack1PositionInParent = stack1.getParent().mChildren.indexOf(stack1);
+ final int stack2PositionInParent = stack1.getParent().mChildren.indexOf(stack2);
+ assertEquals(stack1PositionInParent, stack2PositionInParent + 1);
+ assertTrue(task1.mOnDisplayChangedCalled);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java
index bb9bc9e..462bd68 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java
@@ -17,17 +17,16 @@
package com.android.server.wm;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
-import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.junit.Before;
+import org.junit.After;
-import android.hardware.display.DisplayManagerGlobal;
+import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import android.view.Display;
-import android.view.DisplayInfo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -46,95 +45,69 @@
@RunWith(AndroidJUnit4.class)
public class TaskStackContainersTests extends WindowTestsBase {
+ private TaskStack mPinnedStack;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ mPinnedStack = new StackWindowController(PINNED_STACK_ID, null,
+ sDisplayContent.getDisplayId(), true /* onTop */, new Rect(), sWm).mContainer;
+
+ // Stack should contain visible app window to be considered visible.
+ final Task pinnedTask = createTaskInStack(mPinnedStack, 0 /* userId */);
+ assertFalse(mPinnedStack.isVisible());
+ final TestAppWindowToken pinnedApp = new TestAppWindowToken(sDisplayContent);
+ pinnedTask.addChild(pinnedApp, 0 /* addPos */);
+ assertTrue(mPinnedStack.isVisible());
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ mPinnedStack.removeImmediately();
+ }
+
@Test
public void testStackPositionChildAt() throws Exception {
// Test that always-on-top stack can't be moved to position other than top.
final TaskStack stack1 = createTaskStackOnDisplay(sDisplayContent);
final TaskStack stack2 = createTaskStackOnDisplay(sDisplayContent);
- final TaskStack pinnedStack = addPinnedStack();
final WindowContainer taskStackContainer = stack1.getParent();
final int stack1Pos = taskStackContainer.mChildren.indexOf(stack1);
final int stack2Pos = taskStackContainer.mChildren.indexOf(stack2);
- final int pinnedStackPos = taskStackContainer.mChildren.indexOf(pinnedStack);
+ final int pinnedStackPos = taskStackContainer.mChildren.indexOf(mPinnedStack);
assertGreaterThan(pinnedStackPos, stack2Pos);
assertGreaterThan(stack2Pos, stack1Pos);
- taskStackContainer.positionChildAt(WindowContainer.POSITION_BOTTOM, pinnedStack, false);
+ taskStackContainer.positionChildAt(WindowContainer.POSITION_BOTTOM, mPinnedStack, false);
assertEquals(taskStackContainer.mChildren.get(stack1Pos), stack1);
assertEquals(taskStackContainer.mChildren.get(stack2Pos), stack2);
- assertEquals(taskStackContainer.mChildren.get(pinnedStackPos), pinnedStack);
+ assertEquals(taskStackContainer.mChildren.get(pinnedStackPos), mPinnedStack);
- taskStackContainer.positionChildAt(1, pinnedStack, false);
+ taskStackContainer.positionChildAt(1, mPinnedStack, false);
assertEquals(taskStackContainer.mChildren.get(stack1Pos), stack1);
assertEquals(taskStackContainer.mChildren.get(stack2Pos), stack2);
- assertEquals(taskStackContainer.mChildren.get(pinnedStackPos), pinnedStack);
+ assertEquals(taskStackContainer.mChildren.get(pinnedStackPos), mPinnedStack);
}
+
@Test
public void testStackPositionBelowPinnedStack() throws Exception {
// Test that no stack can be above pinned stack.
- final TaskStack pinnedStack = addPinnedStack();
final TaskStack stack1 = createTaskStackOnDisplay(sDisplayContent);
final WindowContainer taskStackContainer = stack1.getParent();
final int stackPos = taskStackContainer.mChildren.indexOf(stack1);
- final int pinnedStackPos = taskStackContainer.mChildren.indexOf(pinnedStack);
+ final int pinnedStackPos = taskStackContainer.mChildren.indexOf(mPinnedStack);
assertGreaterThan(pinnedStackPos, stackPos);
taskStackContainer.positionChildAt(WindowContainer.POSITION_TOP, stack1, false);
assertEquals(taskStackContainer.mChildren.get(stackPos), stack1);
- assertEquals(taskStackContainer.mChildren.get(pinnedStackPos), pinnedStack);
+ assertEquals(taskStackContainer.mChildren.get(pinnedStackPos), mPinnedStack);
taskStackContainer.positionChildAt(taskStackContainer.mChildren.size() - 1, stack1, false);
assertEquals(taskStackContainer.mChildren.get(stackPos), stack1);
- assertEquals(taskStackContainer.mChildren.get(pinnedStackPos), pinnedStack);
- }
-
- @Test
- public void testReparentBetweenDisplays() throws Exception {
- // Create first stack on primary display.
- final TaskStack stack1 = createTaskStackOnDisplay(sDisplayContent);
- final TestTaskWindowContainerController taskController =
- new TestTaskWindowContainerController(stack1.mStackId);
- final TestTask task1 = (TestTask) taskController.mContainer;
- task1.mOnDisplayChangedCalled = false;
-
- // Create second display and put second stack on it.
- final Display display = new Display(DisplayManagerGlobal.getInstance(),
- sDisplayContent.getDisplayId() + 1, new DisplayInfo(),
- DEFAULT_DISPLAY_ADJUSTMENTS);
- final DisplayContent dc = new DisplayContent(display, sWm, sLayersController,
- new WallpaperController(sWm));
- sWm.mRoot.addChild(dc, 1);
- final TaskStack stack2 = createTaskStackOnDisplay(dc);
-
- // Reparent and check state.DisplayContent.java:2572
- sWm.moveStackToDisplay(stack1.mStackId, dc.getDisplayId());
- assertEquals(dc, stack1.getDisplayContent());
- final int stack1PositionInParent = stack1.getParent().mChildren.indexOf(stack1);
- final int stack2PositionInParent = stack1.getParent().mChildren.indexOf(stack2);
- assertEquals(stack1PositionInParent, stack2PositionInParent + 1);
- assertTrue(task1.mOnDisplayChangedCalled);
- }
-
- private TaskStack addPinnedStack() {
- TaskStack pinnedStack = sWm.mStackIdToStack.get(PINNED_STACK_ID);
- if (pinnedStack == null) {
- sDisplayContent.addStackToDisplay(PINNED_STACK_ID, true);
- pinnedStack = sWm.mStackIdToStack.get(PINNED_STACK_ID);
- }
-
- if (!pinnedStack.isVisible()) {
- // Stack should contain visible app window to be considered visible.
- final Task pinnedTask = createTaskInStack(pinnedStack, 0 /* userId */);
- assertFalse(pinnedStack.isVisible());
- final TestAppWindowToken pinnedApp = new TestAppWindowToken(sDisplayContent);
- pinnedTask.addChild(pinnedApp, 0 /* addPos */);
- assertTrue(pinnedStack.isVisible());
- }
-
- return pinnedStack;
+ assertEquals(taskStackContainer.mChildren.get(pinnedStackPos), mPinnedStack);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java
index 7cd3f64..3ee1da43 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java
@@ -18,14 +18,14 @@
import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
-import org.junit.Test;
-
import android.hardware.display.DisplayManagerGlobal;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.view.Display;
import android.view.DisplayInfo;
+import org.junit.Test;
+import org.junit.runner.RunWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -40,7 +40,7 @@
*/
@SmallTest
@Presubmit
-@org.junit.runner.RunWith(AndroidJUnit4.class)
+@RunWith(AndroidJUnit4.class)
public class TaskWindowContainerControllerTests extends WindowTestsBase {
@Test
@@ -57,7 +57,7 @@
}
@Test
- public void testRemoveContainer_DeferRemoval() throws Exception {
+ public void testRemoveContainer_deferRemoval() throws Exception {
final TestTaskWindowContainerController taskController =
new TestTaskWindowContainerController();
final TestAppWindowContainerController appController =
@@ -83,58 +83,66 @@
@Test
public void testReparent() throws Exception {
- final TaskStack stack1 = createTaskStackOnDisplay(sDisplayContent);
+ final StackWindowController stackController1 =
+ createStackControllerOnDisplay(sDisplayContent);
final TestTaskWindowContainerController taskController =
- new TestTaskWindowContainerController(stack1.mStackId);
- final TaskStack stack2 = createTaskStackOnDisplay(sDisplayContent);
+ new TestTaskWindowContainerController(stackController1);
+ final StackWindowController stackController2 =
+ createStackControllerOnDisplay(sDisplayContent);
final TestTaskWindowContainerController taskController2 =
- new TestTaskWindowContainerController(stack2.mStackId);
+ new TestTaskWindowContainerController(stackController2);
boolean gotException = false;
try {
- taskController.reparent(stack1.mStackId, 0);
+ taskController.reparent(stackController1, 0);
} catch (IllegalArgumentException e) {
gotException = true;
}
assertTrue("Should not be able to reparent to the same parent", gotException);
+ final StackWindowController stackController3 =
+ createStackControllerOnDisplay(sDisplayContent);
+ stackController3.setContainer(null);
gotException = false;
try {
- taskController.reparent(sNextStackId + 1, 0);
+ taskController.reparent(stackController3, 0);
} catch (IllegalArgumentException e) {
gotException = true;
}
- assertTrue("Should not be able to reparent to a stackId that doesn't exist", gotException);
+ assertTrue("Should not be able to reparent to a stack that doesn't have a container",
+ gotException);
- taskController.reparent(stack2.mStackId, 0);
- assertEquals(stack2, taskController.mContainer.getParent());
+ taskController.reparent(stackController2, 0);
+ assertEquals(stackController2.mContainer, taskController.mContainer.getParent());
assertEquals(0, ((TestTask) taskController.mContainer).positionInParent());
assertEquals(1, ((TestTask) taskController2.mContainer).positionInParent());
}
@Test
- public void testReparentBetweenDisplays() throws Exception {
+ public void testReparent_BetweenDisplays() throws Exception {
// Create first stack on primary display.
- final TaskStack stack1 = createTaskStackOnDisplay(sDisplayContent);
+ final StackWindowController stack1Controller =
+ createStackControllerOnDisplay(sDisplayContent);
+ final TaskStack stack1 = stack1Controller.mContainer;
final TestTaskWindowContainerController taskController =
- new TestTaskWindowContainerController(stack1.mStackId);
+ new TestTaskWindowContainerController(stack1Controller);
final TestTask task1 = (TestTask) taskController.mContainer;
task1.mOnDisplayChangedCalled = false;
// Create second display and put second stack on it.
final Display display = new Display(DisplayManagerGlobal.getInstance(),
- sDisplayContent.getDisplayId() + 1, new DisplayInfo(),
- DEFAULT_DISPLAY_ADJUSTMENTS);
+ sDisplayContent.getDisplayId() + 1, new DisplayInfo(), DEFAULT_DISPLAY_ADJUSTMENTS);
final DisplayContent dc = new DisplayContent(display, sWm, sLayersController,
new WallpaperController(sWm));
sWm.mRoot.addChild(dc, 1);
- final TaskStack stack2 = createTaskStackOnDisplay(dc);
+ final StackWindowController stack2Controller = createStackControllerOnDisplay(dc);
+ final TaskStack stack2 = stack2Controller.mContainer;
final TestTaskWindowContainerController taskController2 =
- new TestTaskWindowContainerController(stack2.mStackId);
+ new TestTaskWindowContainerController(stack2Controller);
final TestTask task2 = (TestTask) taskController2.mContainer;
// Reparent and check state
- taskController.reparent(stack2.mStackId, 0);
+ taskController.reparent(stack2Controller, 0);
assertEquals(stack2, task1.getParent());
assertEquals(0, task1.positionInParent());
assertEquals(1, task2.positionInParent());
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index 847f34d..72157b6 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -28,6 +28,7 @@
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
+import android.app.ActivityManager.TaskSnapshot;
import android.content.Context;
import android.os.IBinder;
import android.support.test.InstrumentationRegistry;
@@ -95,6 +96,10 @@
sWm = TestWindowManagerPolicy.getWindowManagerService(context);
sPolicy = (TestWindowManagerPolicy) sWm.mPolicy;
sLayersController = new WindowLayersController(sWm);
+ sDisplayContent = sWm.mRoot.getDisplayContent(context.getDisplay().getDisplayId());
+ if (sDisplayContent != null) {
+ sDisplayContent.removeImmediately();
+ }
sDisplayContent = new DisplayContent(context.getDisplay(), sWm, sLayersController,
new WallpaperController(sWm));
sWm.mRoot.addChild(sDisplayContent, 0);
@@ -173,9 +178,13 @@
/** Creates a {@link TaskStack} and adds it to the specified {@link DisplayContent}. */
static TaskStack createTaskStackOnDisplay(DisplayContent dc) {
- final int stackId = sNextStackId++;
- dc.addStackToDisplay(stackId, true);
- return sWm.mStackIdToStack.get(stackId);
+ return createStackControllerOnDisplay(dc).mContainer;
+ }
+
+ static StackWindowController createStackControllerOnDisplay(DisplayContent dc) {
+ final int stackId = ++sNextStackId;
+ return new StackWindowController(stackId, null, dc.getDisplayId(),
+ true /* onTop */, new Rect(), sWm);
}
/**Creates a {@link Task} and adds it to the specified {@link TaskStack}. */
@@ -235,6 +244,8 @@
boolean mShouldDeferRemoval = false;
boolean mOnDisplayChangedCalled = false;
+ private boolean mUseLocalIsAnimating = false;
+ private boolean mIsAnimating = false;
TestTask(int taskId, TaskStack stack, int userId, WindowManagerService service, Rect bounds,
Configuration overrideConfig, boolean isOnTopLauncher, int resizeMode,
@@ -258,6 +269,16 @@
super.onDisplayChanged(dc);
mOnDisplayChangedCalled = true;
}
+
+ @Override
+ boolean isAnimating() {
+ return mUseLocalIsAnimating ? mIsAnimating : super.isAnimating();
+ }
+
+ void setLocalIsAnimating(boolean isAnimating) {
+ mUseLocalIsAnimating = true;
+ mIsAnimating = isAnimating;
+ }
}
/**
@@ -267,15 +288,25 @@
class TestTaskWindowContainerController extends TaskWindowContainerController {
TestTaskWindowContainerController() {
- this(createTaskStackOnDisplay(sDisplayContent).mStackId);
+ this(createStackControllerOnDisplay(sDisplayContent));
}
- TestTaskWindowContainerController(int stackId) {
- super(sNextTaskId++, snapshot -> {}, stackId, 0 /* userId */, null /* bounds */,
+ TestTaskWindowContainerController(StackWindowController stackController) {
+ super(sNextTaskId++, new TaskWindowContainerListener() {
+ @Override
+ public void onSnapshotChanged(TaskSnapshot snapshot) {
+
+ }
+
+ @Override
+ public void requestResize(Rect bounds, int resizeMode) {
+
+ }
+ }, stackController, 0 /* userId */, null /* bounds */,
EMPTY /* overrideConfig*/, RESIZE_MODE_UNRESIZEABLE,
false /* supportsPictureInPicture */, false /* homeTask*/,
false /* isOnTopLauncher */, true /* toTop*/, true /* showForAllUsers */,
- new TaskDescription());
+ new TaskDescription(), sWm);
}
@Override
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 5ed5460..56898f1 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -340,12 +340,6 @@
}
@Override
- public Rect getBoundsForNewConfiguration(int stackId) throws RemoteException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
public void setScreenCaptureDisabled(int userId, boolean disabled) {
// TODO Auto-generated method stub
}