diff options
3 files changed, 111 insertions, 67 deletions
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 7e47006ecc2b..4793d6af1485 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -2992,84 +2992,87 @@ public final class ActivityStackSupervisor implements DisplayListener { } Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeStack_" + stackId); - - ActivityRecord r = stack.topRunningActivityLocked(); - - mTmpBounds.clear(); - mTmpConfigs.clear(); - ArrayList<TaskRecord> tasks = stack.getAllTasks(); - for (int i = tasks.size() - 1; i >= 0; i--) { - TaskRecord task = tasks.get(i); - if (task.mResizeable) { - if (stack.mStackId == FREEFORM_WORKSPACE_STACK_ID) { - // 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, bounds); - task.updateOverrideConfiguration(tempRect2); - } else { - task.updateOverrideConfiguration(bounds); + mWindowManager.deferSurfaceLayout(); + try { + ActivityRecord r = stack.topRunningActivityLocked(); + + mTmpBounds.clear(); + mTmpConfigs.clear(); + ArrayList<TaskRecord> tasks = stack.getAllTasks(); + for (int i = tasks.size() - 1; i >= 0; i--) { + TaskRecord task = tasks.get(i); + if (task.mResizeable) { + if (stack.mStackId == FREEFORM_WORKSPACE_STACK_ID) { + // 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, bounds); + task.updateOverrideConfiguration(tempRect2); + } else { + task.updateOverrideConfiguration(bounds); + } } - } - mTmpConfigs.put(task.taskId, task.mOverrideConfig); - mTmpBounds.put(task.taskId, task.mBounds); - } - stack.mFullscreen = mWindowManager.resizeStack(stackId, bounds, mTmpConfigs, mTmpBounds); - if (stack.mStackId == DOCKED_STACK_ID) { - // Dock stack funness...Yay! - if (stack.mFullscreen) { - // The dock stack went fullscreen which is kinda like dismissing it. - // In this case we make all other static stacks fullscreen and move all - // docked stack tasks to the fullscreen stack. - for (int i = FIRST_STATIC_STACK_ID; i <= LAST_STATIC_STACK_ID; i++) { - if (i != DOCKED_STACK_ID && getStack(i) != null) { - resizeStackLocked(i, null, preserveWindows, true); + mTmpConfigs.put(task.taskId, task.mOverrideConfig); + mTmpBounds.put(task.taskId, task.mBounds); + } + stack.mFullscreen = mWindowManager.resizeStack(stackId, bounds, mTmpConfigs, mTmpBounds); + if (stack.mStackId == DOCKED_STACK_ID) { + // Dock stack funness...Yay! + if (stack.mFullscreen) { + // The dock stack went fullscreen which is kinda like dismissing it. + // In this case we make all other static stacks fullscreen and move all + // docked stack tasks to the fullscreen stack. + for (int i = FIRST_STATIC_STACK_ID; i <= LAST_STATIC_STACK_ID; i++) { + if (i != DOCKED_STACK_ID && getStack(i) != null) { + resizeStackLocked(i, null, preserveWindows, true); + } } - } - final int count = tasks.size(); - for (int i = 0; i < count; i++) { - moveTaskToStackLocked(tasks.get(i).taskId, - FULLSCREEN_WORKSPACE_STACK_ID, ON_TOP, FORCE_FOCUS); - } + final int count = tasks.size(); + for (int i = 0; i < count; i++) { + moveTaskToStackLocked(tasks.get(i).taskId, + FULLSCREEN_WORKSPACE_STACK_ID, ON_TOP, FORCE_FOCUS); + } - // stack shouldn't contain anymore activities, so nothing to resume. - r = null; - } else { - // Docked stacks occupy a dedicated region on screen so the size of all other - // 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); - - for (int i = FIRST_STATIC_STACK_ID; i <= LAST_STATIC_STACK_ID; i++) { - if (i != DOCKED_STACK_ID) { - ActivityStack otherStack = getStack(i); - if (otherStack != null) { - resizeStackLocked(i, tempRect, PRESERVE_WINDOWS, true); + // stack shouldn't contain anymore activities, so nothing to resume. + r = null; + } else { + // Docked stacks occupy a dedicated region on screen so the size of all other + // 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); + + for (int i = FIRST_STATIC_STACK_ID; i <= LAST_STATIC_STACK_ID; i++) { + if (i != DOCKED_STACK_ID) { + ActivityStack otherStack = getStack(i); + if (otherStack != null) { + resizeStackLocked(i, tempRect, PRESERVE_WINDOWS, true); + } } } } + // Since we are resizing the stack, all other operations should strive to preserve + // windows. + preserveWindows = true; } - // Since we are resizing the stack, all other operations should strive to preserve - // windows. - preserveWindows = true; - } - stack.setBounds(bounds); + stack.setBounds(bounds); - if (r != null) { - final boolean updated = stack.ensureActivityConfigurationLocked(r, 0, preserveWindows); - // And we need to make sure at this point that all other activities - // are made visible with the correct configuration. - ensureActivitiesVisibleLocked(r, 0, preserveWindows); - if (!updated) { - resumeTopActivitiesLocked(stack, null, null); + if (r != null) { + final boolean updated = stack.ensureActivityConfigurationLocked(r, 0, preserveWindows); + // And we need to make sure at this point that all other activities + // are made visible with the correct configuration. + ensureActivitiesVisibleLocked(r, 0, preserveWindows); + if (!updated) { + resumeTopActivitiesLocked(stack, null, null); + } } + } finally { + mWindowManager.continueSurfaceLayout(); + Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); } - - Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); } void resizeTaskLocked(TaskRecord task, Rect bounds, int resizeMode, boolean preserveWindow) { diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 8a2442ae0789..62553cf6a2b0 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -4679,7 +4679,7 @@ public class WindowManagerService extends IWindowManager.Stub throw new IllegalArgumentException("resizeStack: stackId " + stackId + " not found."); } - if (stack.setBounds(bounds, configs, taskBounds)) { + if (stack.setBounds(bounds, configs, taskBounds) && stack.isVisibleLocked()) { stack.resizeWindows(); stack.getDisplayContent().layoutNeeded = true; mWindowPlacerLocked.performSurfacePlacement(); @@ -4732,6 +4732,26 @@ public class WindowManagerService extends IWindowManager.Stub } } + /** + * 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} + */ + public void deferSurfaceLayout() { + synchronized (mWindowMap) { + mWindowPlacerLocked.deferLayout(); + } + } + + /** + * Resumes layout passes after deferring them. See {@link #deferSurfaceLayout()} + */ + public void continueSurfaceLayout() { + synchronized (mWindowMap) { + mWindowPlacerLocked.continueLayout(); + } + } + public void getTaskBounds(int taskId, Rect bounds) { synchronized (mWindowMap) { Task task = mTaskIdToTask.get(taskId); diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java index e2f4dd9b21ac..b267860ce80e 100644 --- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java +++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java @@ -112,13 +112,34 @@ class WindowSurfacePlacer { private int mPreferredModeId = 0; private boolean mTraversalScheduled; + private int mDeferDepth = 0; public WindowSurfacePlacer(WindowManagerService service) { mService = service; mWallpaperControllerLocked = mService.mWallpaperControllerLocked; } + /** + * See {@link WindowManagerService#deferSurfaceLayout()} + */ + void deferLayout() { + mDeferDepth++; + } + + /** + * See {@link WindowManagerService#continueSurfaceLayout()} + */ + void continueLayout() { + mDeferDepth--; + if (mDeferDepth <= 0) { + performSurfacePlacement(); + } + } + final void performSurfacePlacement() { + if (mDeferDepth > 0) { + return; + } int loopCount = 6; do { mTraversalScheduled = false; |