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