diff options
12 files changed, 339 insertions, 90 deletions
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 15f636107ff0..141c89972227 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -752,6 +752,15 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM return true; } + case MOVE_STACK_TO_DISPLAY_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + int stackId = data.readInt(); + int displayId = data.readInt(); + moveStackToDisplay(stackId, displayId); + reply.writeNoException(); + return true; + } + case MOVE_TASK_TO_FRONT_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); int task = data.readInt(); @@ -3885,6 +3894,19 @@ class ActivityManagerProxy implements IActivityManager reply.recycle(); return list; } + public void moveStackToDisplay(int stackId, int displayId) throws RemoteException + { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeInt(stackId); + data.writeInt(displayId); + mRemote.transact(MOVE_STACK_TO_DISPLAY_TRANSACTION, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + } + @Override public void moveTaskToFront(int task, int flags, Bundle options) throws RemoteException { Parcel data = Parcel.obtain(); diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java index c075ed675948..cada1b854a8e 100644 --- a/core/java/android/app/ActivityView.java +++ b/core/java/android/app/ActivityView.java @@ -448,13 +448,6 @@ public class ActivityView extends ViewGroup { mGuard.open("release"); } - void attachToDisplay(int displayId) { - try { - mIActivityContainer.attachToDisplay(displayId); - } catch (RemoteException e) { - } - } - void setSurface(Surface surface, int width, int height, int density) throws RemoteException { mIActivityContainer.setSurface(surface, width, height, density); diff --git a/core/java/android/app/IActivityContainer.aidl b/core/java/android/app/IActivityContainer.aidl index 170aff34b065..1ff3c87bef6e 100644 --- a/core/java/android/app/IActivityContainer.aidl +++ b/core/java/android/app/IActivityContainer.aidl @@ -25,7 +25,7 @@ import android.view.Surface; /** @hide */ interface IActivityContainer { - void attachToDisplay(int displayId); + void addToDisplay(int displayId); void setSurface(in Surface surface, int width, int height, int density); int startActivity(in Intent intent); int startActivityIntentSender(in IIntentSender intentSender); diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 032365137a39..7166789ba571 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -143,6 +143,7 @@ public interface IActivityManager extends IInterface { public List<RunningServiceInfo> getServices(int maxNum, int flags) throws RemoteException; public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() throws RemoteException; + public void moveStackToDisplay(int stackId, int displayId) throws RemoteException; public void moveTaskToFront(int task, int flags, Bundle options) throws RemoteException; public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) throws RemoteException; public void moveTaskBackwards(int task) throws RemoteException; @@ -1100,4 +1101,5 @@ public interface IActivityManager extends IInterface { int REQUEST_ACTIVITY_RELAUNCH = IBinder.FIRST_CALL_TRANSACTION+400; int UPDATE_DISPLAY_OVERRIDE_CONFIGURATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 401; int UNREGISTER_TASK_STACK_LISTENER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+402; + int MOVE_STACK_TO_DISPLAY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 403; } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 5d41d36a3e9a..5aee770251c2 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -9513,6 +9513,22 @@ public class ActivityManagerService extends ActivityManagerNative } @Override + public void moveStackToDisplay(int stackId, int displayId) { + enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "moveStackToDisplay()"); + + synchronized (this) { + final long ident = Binder.clearCallingIdentity(); + try { + if (DEBUG_STACK) Slog.d(TAG_STACK, "moveStackToDisplay: moving stackId=" + stackId + + " to displayId=" + displayId); + mStackSupervisor.moveStackToDisplayLocked(stackId, displayId); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + } + + @Override public boolean removeTask(int taskId) { enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS, "removeTask()"); synchronized (this) { diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 8234f3506c24..3efd3004002c 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -215,6 +215,8 @@ final class ActivityManagerShellCommand extends ShellCommand { return runGetInactive(pw); case "send-trim-memory": return runSendTrimMemory(pw); + case "display": + return runDisplay(pw); case "stack": return runStack(pw); case "task": @@ -1631,12 +1633,23 @@ final class ActivityManagerShellCommand extends ShellCommand { return 0; } + int runDisplay(PrintWriter pw) throws RemoteException { + String op = getNextArgRequired(); + switch (op) { + case "move-stack": + return runDisplayMoveStack(pw); + default: + getErrPrintWriter().println("Error: unknown command '" + op + "'"); + return -1; + } + } + int runStack(PrintWriter pw) throws RemoteException { String op = getNextArgRequired(); switch (op) { case "start": return runStackStart(pw); - case "movetask": + case "move-task": return runStackMoveTask(pw); case "resize": return runStackResize(pw); @@ -1691,6 +1704,15 @@ final class ActivityManagerShellCommand extends ShellCommand { return new Rect(left, top, right, bottom); } + int runDisplayMoveStack(PrintWriter pw) throws RemoteException { + String stackIdStr = getNextArgRequired(); + int stackId = Integer.parseInt(stackIdStr); + String displayIdStr = getNextArgRequired(); + int displayId = Integer.parseInt(displayIdStr); + mInterface.moveStackToDisplay(stackId, displayId); + return 0; + } + int runStackStart(PrintWriter pw) throws RemoteException { String displayIdStr = getNextArgRequired(); int displayId = Integer.parseInt(displayIdStr); @@ -2450,10 +2472,13 @@ final class ActivityManagerShellCommand extends ShellCommand { pw.println(" send-trim-memory [--user <USER_ID>] <PROCESS>"); pw.println(" [HIDDEN|RUNNING_MODERATE|BACKGROUND|RUNNING_LOW|MODERATE|RUNNING_CRITICAL|COMPLETE]"); pw.println(" Send a memory trim event to a <PROCESS>."); + pw.println(" display [COMMAND] [...]: sub-commands for operating on displays."); + pw.println(" move-stack <STACK_ID> <DISPLAY_ID>"); + pw.println(" Move <STACK_ID> from its current display to <DISPLAY_ID>."); pw.println(" stack [COMMAND] [...]: sub-commands for operating on activity stacks."); pw.println(" start <DISPLAY_ID> <INTENT>"); pw.println(" Start a new activity on <DISPLAY_ID> using <INTENT>"); - pw.println(" movetask <TASK_ID> <STACK_ID> [true|false]"); + pw.println(" move-task <TASK_ID> <STACK_ID> [true|false]"); pw.println(" Move <TASK_ID> from its current stack to the top (true) or"); pw.println(" bottom (false) of <STACK_ID>."); pw.println(" resize <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>"); diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 1c3a885176a0..0d7998071e99 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -449,10 +449,23 @@ final class ActivityStack extends ConfigurationContainer { ? new LaunchingTaskPositioner() : null; } - void attachDisplay(ActivityStackSupervisor.ActivityDisplay activityDisplay, boolean onTop) { + /** 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); + } + + /** + * Updates internal state after adding to new display. + * @param activityDisplay New display to which this stack was attached. + * @param bounds Updated bounds. + */ + private void postAddToDisplay(ActivityStackSupervisor.ActivityDisplay activityDisplay, + Rect bounds) { mDisplayId = activityDisplay.mDisplayId; mStacks = activityDisplay.mStacks; - mBounds = mWindowManager.attachStack(mStackId, activityDisplay.mDisplayId, onTop); + mBounds = bounds; mFullscreen = mBounds == null; if (mTaskPositioner != null) { mTaskPositioner.setDisplay(activityDisplay.mDisplay); @@ -468,7 +481,21 @@ final class ActivityStack extends ConfigurationContainer { } } - void remove() { + /** + * 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. + */ + private void removeFromDisplay() { mDisplayId = Display.INVALID_DISPLAY; mStacks = null; if (mTaskPositioner != null) { @@ -480,6 +507,11 @@ final class ActivityStack extends ConfigurationContainer { mStackSupervisor.resizeDockedStackLocked( null, null, null, null, null, PRESERVE_WINDOWS); } + } + + /** Removes the stack completely. Also calls WindowManager to do the same on its side. */ + void remove() { + removeFromDisplay(); mStackSupervisor.deleteActivityContainerRecord(mStackId); mWindowManager.removeStack(mStackId); onParentChanged(); @@ -696,11 +728,7 @@ final class ActivityStack extends ConfigurationContainer { } mStacks.add(addIndex, this); - - // TODO(multi-display): Needs to also work if focus is moving to the non-home display. - if (isOnHomeDisplay()) { - mStackSupervisor.setFocusStackUnchecked(reason, this); - } + mStackSupervisor.setFocusStackUnchecked(reason, this); if (task != null) { insertTaskAtTop(task, null); return; diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index eed8dd78e83c..61676716278d 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -2300,7 +2300,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer ActivityContainer activityContainer = new ActivityContainer(stackId); mActivityContainers.put(stackId, activityContainer); - activityContainer.attachToDisplayLocked(activityDisplay, onTop); + activityContainer.addToDisplayLocked(activityDisplay, onTop); return activityContainer.mStack; } @@ -2364,6 +2364,40 @@ public class ActivityStackSupervisor extends ConfigurationContainer } /** + * Move stack with all its existing content to specified display. + * @param stackId Id of stack to move. + * @param displayId Id of display to move stack to. + */ + void moveStackToDisplayLocked(int stackId, int displayId) { + final ActivityDisplay activityDisplay = mActivityDisplays.get(displayId); + if (activityDisplay == null) { + throw new IllegalArgumentException("moveStackToDisplayLocked: Unknown displayId=" + + displayId); + } + final ActivityContainer activityContainer = mActivityContainers.get(stackId); + if (activityContainer != null) { + if (activityContainer.isAttachedLocked()) { + if (activityContainer.getDisplayId() == displayId) { + throw new IllegalArgumentException("Trying to move stackId=" + stackId + + " to its current displayId=" + displayId); + } + + activityContainer.moveToDisplayLocked(activityDisplay); + } else { + throw new IllegalStateException("moveStackToDisplayLocked: Stack with stackId=" + + stackId + " is not attached to any display."); + } + } else { + throw new IllegalArgumentException("moveStackToDisplayLocked: Unknown stackId=" + + stackId); + } + + ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */, + !PRESERVE_WINDOWS); + // TODO(multi-display): resize stacks properly if moved from split-screen. + } + + /** * Moves the specified task record to the input stack id. * WARNING: This method performs an unchecked/raw move of the task and * can leave the system in an unstable state if used incorrectly. @@ -4032,22 +4066,33 @@ public class ActivityStackSupervisor extends ConfigurationContainer } } - void attachToDisplayLocked(ActivityDisplay activityDisplay, boolean onTop) { - if (DEBUG_STACK) Slog.d(TAG_STACK, "attachToDisplayLocked: " + this + /** + * Adds the stack to specified display. Also calls WindowManager to do the same from + * {@link ActivityStack#addToDisplay(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) { + if (DEBUG_STACK) Slog.d(TAG_STACK, "addToDisplayLocked: " + this + " to display=" + activityDisplay + " onTop=" + onTop); + if (mActivityDisplay != null) { + throw new IllegalStateException("ActivityContainer is already attached, " + + "displayId=" + mActivityDisplay.mDisplayId); + } mActivityDisplay = activityDisplay; - mStack.attachDisplay(activityDisplay, onTop); + mStack.addToDisplay(activityDisplay, onTop); activityDisplay.attachActivities(mStack, onTop); } @Override - public void attachToDisplay(int displayId) { + public void addToDisplay(int displayId) { synchronized (mService) { ActivityDisplay activityDisplay = mActivityDisplays.get(displayId); if (activityDisplay == null) { return; } - attachToDisplayLocked(activityDisplay, true); + addToDisplayLocked(activityDisplay, true); } } @@ -4103,16 +4148,44 @@ public class ActivityStackSupervisor extends ConfigurationContainer } } + /** Remove the stack completely. */ void removeLocked() { if (DEBUG_STACK) Slog.d(TAG_STACK, "removeLocked: " + this + " from display=" + mActivityDisplay + " Callers=" + Debug.getCallers(2)); if (mActivityDisplay != null) { - mActivityDisplay.detachActivitiesLocked(mStack); - mActivityDisplay = null; + removeFromDisplayLocked(); } mStack.remove(); } + /** + * Remove the stack from its current {@link ActivityDisplay}, so it can be either destroyed + * completely or re-parented. + */ + private void removeFromDisplayLocked() { + if (DEBUG_STACK) Slog.d(TAG_STACK, "removeFromDisplayLocked: " + this + + " current displayId=" + mActivityDisplay.mDisplayId); + + mActivityDisplay.detachActivitiesLocked(mStack); + mActivityDisplay = null; + } + + /** + * Move the stack to specified display. + * @param activityDisplay Target display to move the stack to. + */ + void moveToDisplayLocked(ActivityDisplay activityDisplay) { + if (DEBUG_STACK) Slog.d(TAG_STACK, "moveToDisplayLocked: " + this + " from display=" + + mActivityDisplay + " to display=" + activityDisplay + + " Callers=" + Debug.getCallers(2)); + + removeFromDisplayLocked(); + + mActivityDisplay = activityDisplay; + mStack.moveToDisplay(activityDisplay); + activityDisplay.attachActivities(mStack, ON_TOP); + } + @Override public final int startActivity(Intent intent) { return mService.startActivity(intent, this); @@ -4232,7 +4305,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer new VirtualActivityDisplay(width, height, density); mActivityDisplay = virtualActivityDisplay; mActivityDisplays.put(virtualActivityDisplay.mDisplayId, virtualActivityDisplay); - attachToDisplayLocked(virtualActivityDisplay, true); + addToDisplayLocked(virtualActivityDisplay, true); } if (mSurface != null) { diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 5d55ac7cf41c..ec4cdf2b0f3d 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -76,6 +76,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEAT import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION; 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_VISIBILITY; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT; @@ -193,6 +194,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo // Accessed directly by all users. private boolean mLayoutNeeded; int pendingLayoutChanges; + // TODO(multi-display): remove some of the usages. final boolean isDefaultDisplay; /** Window tokens that are in the process of exiting, but still on screen for animations. */ @@ -568,9 +570,72 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo out.set(mContentRect); } - /** Refer to {@link WindowManagerService#attachStack(int, int, boolean)} */ - void attachStack(TaskStack stack, boolean onTop) { - mTaskStackContainers.attachStack(stack, onTop); + /** + * 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); + + 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; + moveStack(stack, onTop); + attachedToDisplay = true; + } else { + stack = new TaskStack(mService, stackId); + } + + mService.mStackIdToStack.put(stackId, stack); + if (stackId == DOCKED_STACK_ID) { + mDividerControllerLocked.notifyDockedStackExistsChanged(true); + } + } 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) { + mTaskStackContainers.addStackToDisplay(stack, onTop); + } + + if (stack.getRawFullscreen()) { + return null; + } + final Rect bounds = new Rect(); + stack.getRawBounds(bounds); + return bounds; + } + + /** 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) { + throw new IllegalStateException("Trying to move stackId=" + stack.mStackId + + " which is not currently attached to any display"); + } + if (stack.getDisplayContent().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 */); } void moveStack(TaskStack stack, boolean toTop) { @@ -2427,7 +2492,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("On entry to LockedInner", pendingLayoutChanges); - if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) { + // TODO(multi-display): For now adjusting wallpaper only on primary display to avoid + // the wallpaper window jumping across displays. + // Remove check for default display when there will be support for multiple wallpaper + // targets (on different displays). + if (isDefaultDisplay && (pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) { adjustWallpaperWindows(); } @@ -3111,7 +3180,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo */ private final class TaskStackContainers extends DisplayChildWindowContainer<TaskStack> { - void attachStack(TaskStack stack, boolean onTop) { + /** + * Adds the stack to this container. + * @see WindowManagerService#addStackToDisplay(int, int, boolean) + */ + void addStackToDisplay(TaskStack stack, boolean onTop) { if (stack.mStackId == HOME_STACK_ID) { if (mHomeStack != null) { throw new IllegalArgumentException("attachStack: HOME_STACK_ID (0) not first."); @@ -3122,6 +3195,21 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo stack.onDisplayChanged(DisplayContent.this); } + /** Removes the stack from its container and prepare for changing the parent. */ + void removeStackFromDisplay(TaskStack stack) { + removeChild(stack); + stack.onRemovedFromDisplay(); + // TODO: remove when window list will be gone. + // Manually remove records from window list and tap excluded windows list. + for (int i = mWindows.size() - 1; i >= 0; --i) { + final WindowState windowState = mWindows.get(i); + if (stack == windowState.getStack()) { + mWindows.remove(i); + mTapExcludedWindows.remove(windowState); + } + } + } + void moveStack(TaskStack stack, boolean toTop) { if (StackId.isAlwaysOnTop(stack.mStackId) && !toTop) { // This stack is always-on-top silly... diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 6325cdaaf1c1..f0381352be42 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -215,49 +215,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent> { return dc; } - /** Adds the input stack id to the input display id and returns the bounds of the added stack.*/ - Rect addStackToDisplay(int stackId, int displayId, boolean onTop) { - final DisplayContent dc = getDisplayContent(displayId); - if (dc == null) { - Slog.w(TAG_WM, "addStackToDisplay: Trying to add stackId=" + stackId - + " to unknown displayId=" + displayId + " callers=" + Debug.getCallers(6)); - return null; - } - - boolean attachedToDisplay = false; - TaskStack stack = mService.mStackIdToStack.get(stackId); - if (stack == null) { - if (DEBUG_STACK) Slog.d(TAG_WM, "attachStack: stackId=" + stackId); - - stack = dc.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; - dc.moveStack(stack, onTop); - attachedToDisplay = true; - } else { - stack = new TaskStack(mService, stackId); - } - - mService.mStackIdToStack.put(stackId, stack); - if (stackId == DOCKED_STACK_ID) { - dc.mDividerControllerLocked.notifyDockedStackExistsChanged(true); - } - } - - if (!attachedToDisplay) { - dc.attachStack(stack, onTop); - } - - if (stack.getRawFullscreen()) { - return null; - } - final Rect bounds = new Rect(); - stack.getRawBounds(bounds); - return bounds; - } - boolean isLayoutNeeded() { final int numDisplays = mChildren.size(); for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index 60ba025667f6..a0270c605fed 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -793,6 +793,14 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye void removeImmediately() { super.removeImmediately(); + onRemovedFromDisplay(); + } + + /** + * Removes the stack it from its current parent, so it can be either destroyed completely or + * re-parented. + */ + void onRemovedFromDisplay() { mDisplayContent.mDimLayerController.removeDimLayerUser(this); EventLog.writeEvent(EventLogTags.WM_STACK_REMOVED, mStackId); @@ -800,15 +808,13 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye mAnimationBackgroundSurface.destroySurface(); mAnimationBackgroundSurface = null; } - final DockedStackDividerController dividerController = - mDisplayContent.mDividerControllerLocked; - mDisplayContent = null; - - mService.mWindowPlacerLocked.requestTraversal(); if (mStackId == DOCKED_STACK_ID) { - dividerController.notifyDockedStackExistsChanged(false); + mDisplayContent.mDividerControllerLocked.notifyDockedStackExistsChanged(false); } + + mDisplayContent = null; + mService.mWindowPlacerLocked.requestTraversal(); } void resetAnimationBackgroundAnimator() { diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 4bfe8b2b2a4a..77237526faf4 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2721,11 +2721,11 @@ public class WindowManagerService extends IWindowManager.Stub } void setFocusTaskRegionLocked() { - if (mFocusedApp != null) { - final Task task = mFocusedApp.mTask; - final DisplayContent displayContent = task.getDisplayContent(); + final Task focusedTask = mFocusedApp != null ? mFocusedApp.mTask : null; + if (focusedTask != null) { + final DisplayContent displayContent = focusedTask.getDisplayContent(); if (displayContent != null) { - displayContent.setTouchExcludeRegion(task); + displayContent.setTouchExcludeRegion(focusedTask); } } } @@ -3425,24 +3425,63 @@ public class WindowManagerService extends IWindowManager.Stub } /** - * Create a new TaskStack and place it on a DisplayContent. + * 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 initial bounds the stack was created with. null means fullscreen. + * else at the bottom. + * @return The bounds that the stack has after adding. null means fullscreen. */ - public Rect attachStack(int stackId, int displayId, boolean onTop) { + public Rect addStackToDisplay(int stackId, int displayId, boolean onTop) { final long origId = Binder.clearCallingIdentity(); try { synchronized (mWindowMap) { - return mRoot.addStackToDisplay(stackId, displayId, onTop); + 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); |