diff options
13 files changed, 142 insertions, 94 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java index f3e7384fa9ce..e488cc91f9ba 100644 --- a/services/core/java/com/android/server/wm/ActivityDisplay.java +++ b/services/core/java/com/android/server/wm/ActivityDisplay.java @@ -740,7 +740,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> } private void onSplitScreenModeDismissed() { - mRootActivityContainer.mWindowManager.deferSurfaceLayout(); + mService.deferWindowLayout(); try { // Adjust the windowing mode of any stack in secondary split-screen to fullscreen. for (int i = mStacks.size() - 1; i >= 0; --i) { @@ -764,12 +764,12 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> mHomeStack.moveToFront("onSplitScreenModeDismissed"); topFullscreenStack.moveToFront("onSplitScreenModeDismissed"); } - mRootActivityContainer.mWindowManager.continueSurfaceLayout(); + mService.continueWindowLayout(); } } private void onSplitScreenModeActivated() { - mRootActivityContainer.mWindowManager.deferSurfaceLayout(); + mService.deferWindowLayout(); try { // Adjust the windowing mode of any affected by split-screen to split-screen secondary. for (int i = mStacks.size() - 1; i >= 0; --i) { @@ -784,7 +784,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> false /* creating */); } } finally { - mRootActivityContainer.mWindowManager.continueSurfaceLayout(); + mService.continueWindowLayout(); } } @@ -1002,12 +1002,9 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> Configuration values = new Configuration(); mDisplayContent.computeScreenConfiguration(values); - if (mService.mWindowManager != null) { - final Message msg = PooledLambda.obtainMessage( - ActivityManagerInternal::updateOomLevelsForDisplay, mService.mAmInternal, - mDisplayId); - mService.mH.sendMessage(msg); - } + mService.mH.sendMessage(PooledLambda.obtainMessage( + ActivityManagerInternal::updateOomLevelsForDisplay, mService.mAmInternal, + mDisplayId)); Settings.System.clearConfiguration(values); updateDisplayOverrideConfigurationLocked(values, null /* starting */, @@ -1026,9 +1023,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> int changes = 0; boolean kept = true; - if (mService.mWindowManager != null) { - mService.mWindowManager.deferSurfaceLayout(); - } + mService.deferWindowLayout(); try { if (values != null) { if (mDisplayId == DEFAULT_DISPLAY) { @@ -1045,9 +1040,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> kept = mService.ensureConfigAndVisibilityAfterUpdate(starting, changes); } finally { - if (mService.mWindowManager != null) { - mService.mWindowManager.continueSurfaceLayout(); - } + mService.continueWindowLayout(); } if (result != null) { @@ -1096,6 +1089,8 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> mService.mWindowManager.setNewDisplayOverrideConfiguration( overrideConfiguration, mDisplayContent); } + mService.addWindowLayoutReasons( + ActivityTaskManagerService.LAYOUT_REASON_CONFIG_CHANGED); } @Override diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 61bf2cea0b86..7a667315c6c3 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -1703,7 +1703,7 @@ final class ActivityRecord extends ConfigurationContainer { // is not visible if it only contains finishing activities. && mRootActivityContainer.isTopDisplayFocusedStack(stack); - mAtmService.mWindowManager.deferSurfaceLayout(); + mAtmService.deferWindowLayout(); try { makeFinishingLocked(); final TaskRecord task = getTaskRecord(); @@ -1809,7 +1809,7 @@ final class ActivityRecord extends ConfigurationContainer { return FINISH_RESULT_REQUESTED; } finally { - mAtmService.mWindowManager.continueSurfaceLayout(); + mAtmService.continueWindowLayout(); } } @@ -2547,6 +2547,8 @@ final class ActivityRecord extends ConfigurationContainer { return; } mAppWindowToken.setVisibility(visible, mDeferHidingClient); + mAtmService.addWindowLayoutReasons( + ActivityTaskManagerService.LAYOUT_REASON_VISIBILITY_CHANGED); mStackSupervisor.getActivityMetricsLogger().notifyVisibilityChanged(this); } diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java index 29e87b782014..8bb37bbdfc87 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -757,7 +757,6 @@ class ActivityStack extends ConfigurationContainer { return; } - final WindowManagerService wm = mService.mWindowManager; final ActivityRecord topActivity = getTopActivity(); // For now, assume that the Stack's windowing mode is what will actually be used @@ -779,7 +778,7 @@ class ActivityStack extends ConfigurationContainer { topTask.taskId, FORCED_RESIZEABLE_REASON_SPLIT_SCREEN, packageName); } - wm.deferSurfaceLayout(); + mService.deferWindowLayout(); try { if (!animate && topActivity != null) { mStackSupervisor.mNoAnimActivities.add(topActivity); @@ -850,7 +849,7 @@ class ActivityStack extends ConfigurationContainer { // If task moved to docked stack - show recents if needed. mService.mWindowManager.showRecentApps(); } - wm.continueSurfaceLayout(); + mService.continueWindowLayout(); } if (!deferEnsuringVisibility) { @@ -1750,11 +1749,11 @@ class ActivityStack extends ConfigurationContainer { if (mPausingActivity == r) { if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + r + (timeout ? " (due to timeout)" : " (pause complete)")); - mService.mWindowManager.deferSurfaceLayout(); + mService.deferWindowLayout(); try { completePauseLocked(true /* resumeNext */, null /* resumingActivity */); } finally { - mService.mWindowManager.continueSurfaceLayout(); + mService.continueWindowLayout(); } return; } else { @@ -4360,7 +4359,7 @@ class ActivityStack extends ConfigurationContainer { } Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "stack.resize_" + mStackId); - mWindowManager.deferSurfaceLayout(); + mService.deferWindowLayout(); try { // Update override configurations of all tasks in the stack. final Rect taskBounds = tempTaskBounds != null ? tempTaskBounds : bounds; @@ -4384,7 +4383,7 @@ class ActivityStack extends ConfigurationContainer { topRunningActivityLocked(), preserveWindows); } } finally { - mWindowManager.continueSurfaceLayout(); + mService.continueWindowLayout(); Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); } } diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java index 7a3f022d60bf..1aa1d483f707 100644 --- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java @@ -1495,7 +1495,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { private void moveTasksToFullscreenStackInSurfaceTransaction(ActivityStack fromStack, int toDisplayId, boolean onTop) { - mWindowManager.deferSurfaceLayout(); + mService.deferWindowLayout(); try { final int windowingMode = fromStack.getWindowingMode(); final boolean inPinnedWindowingMode = windowingMode == WINDOWING_MODE_PINNED; @@ -1561,7 +1561,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { mRootActivityContainer.resumeFocusedStacksTopActivities(); } finally { mAllowDockedStackResize = true; - mWindowManager.continueSurfaceLayout(); + mService.continueWindowLayout(); } } @@ -1630,7 +1630,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { } Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeDockedStack"); - mWindowManager.deferSurfaceLayout(); + mService.deferWindowLayout(); try { // Don't allow re-entry while resizing. E.g. due to docked stack detaching. mAllowDockedStackResize = false; @@ -1694,7 +1694,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { } } finally { mAllowDockedStackResize = true; - mWindowManager.continueSurfaceLayout(); + mService.continueWindowLayout(); Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); } } @@ -1718,9 +1718,8 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { } Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizePinnedStack"); - mWindowManager.deferSurfaceLayout(); + mService.deferWindowLayout(); try { - ActivityRecord r = stack.topRunningActivityLocked(); Rect insetBounds = null; if (tempPinnedTaskBounds != null && stack.isAnimatingBoundsToFullscreen()) { // Use 0,0 as the position for the inset rect because we are headed for fullscreen. @@ -1739,7 +1738,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { stack.resize(pinnedBounds, tempPinnedTaskBounds, insetBounds, !PRESERVE_WINDOWS, !DEFER_RESUME); } finally { - mWindowManager.continueSurfaceLayout(); + mService.continueWindowLayout(); Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); } } @@ -2731,7 +2730,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { + taskId + " can't be launch in the home/recents stack."); } - mWindowManager.deferSurfaceLayout(); + mService.deferWindowLayout(); try { if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) { mWindowManager.setDockedStackCreateStateLocked( @@ -2822,7 +2821,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { mWindowManager.checkSplitScreenMinimizedChanged(false /* animate */); } } - mWindowManager.continueSurfaceLayout(); + mService.continueWindowLayout(); } } diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 641b00aeb70b..55db1a06664e 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -1400,7 +1400,7 @@ class ActivityStarter { int result = START_CANCELED; final ActivityStack startedActivityStack; try { - mService.mWindowManager.deferSurfaceLayout(); + mService.deferWindowLayout(); result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags, doResume, options, inTask, outActivity, restrictedBgActivity); } finally { @@ -1436,7 +1436,7 @@ class ActivityStarter { startedActivityStack.remove(); } } - mService.mWindowManager.continueSurfaceLayout(); + mService.continueWindowLayout(); } postStartActivityProcessing(r, result, startedActivityStack); diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index ed7e12c00515..2f7acba595c2 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -124,6 +124,7 @@ import static com.android.server.wm.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT; import static com.android.server.wm.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE; import android.Manifest; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; @@ -598,6 +599,19 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { */ int mTopProcessState = ActivityManager.PROCESS_STATE_TOP; + @Retention(RetentionPolicy.SOURCE) + @IntDef({ + LAYOUT_REASON_CONFIG_CHANGED, + LAYOUT_REASON_VISIBILITY_CHANGED, + }) + @interface LayoutReason {} + static final int LAYOUT_REASON_CONFIG_CHANGED = 0x1; + static final int LAYOUT_REASON_VISIBILITY_CHANGED = 0x2; + + /** The reasons to perform surface placement. */ + @LayoutReason + private int mLayoutReasons; + // Whether we should show our dialogs (ANR, crash, etc) or just perform their default action // automatically. Important for devices without direct input devices. private boolean mShowDialogs = true; @@ -4388,17 +4402,19 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { mAmInternal.enforceCallingPermission(CHANGE_CONFIGURATION, "updateConfiguration()"); synchronized (mGlobalLock) { - if (values == null && mWindowManager != null) { + if (mWindowManager == null) { + Slog.w(TAG, "Skip updateConfiguration because mWindowManager isn't set"); + return false; + } + + if (values == null) { // sentinel: fetch the current configuration from the window manager values = mWindowManager.computeNewConfiguration(DEFAULT_DISPLAY); } - if (mWindowManager != null) { - final Message msg = PooledLambda.obtainMessage( - ActivityManagerInternal::updateOomLevelsForDisplay, mAmInternal, - DEFAULT_DISPLAY); - mH.sendMessage(msg); - } + mH.sendMessage(PooledLambda.obtainMessage( + ActivityManagerInternal::updateOomLevelsForDisplay, mAmInternal, + DEFAULT_DISPLAY)); final long origId = Binder.clearCallingIdentity(); try { @@ -5099,9 +5115,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { int changes = 0; boolean kept = true; - if (mWindowManager != null) { - mWindowManager.deferSurfaceLayout(); - } + deferWindowLayout(); try { if (values != null) { changes = updateGlobalConfigurationLocked(values, initLocale, persistent, userId, @@ -5110,9 +5124,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { kept = ensureConfigAndVisibilityAfterUpdate(starting, changes); } finally { - if (mWindowManager != null) { - mWindowManager.continueSurfaceLayout(); - } + continueWindowLayout(); } if (result != null) { @@ -5240,6 +5252,34 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { return changes; } + /** @see WindowSurfacePlacer#deferLayout */ + void deferWindowLayout() { + if (!mWindowManager.mWindowPlacerLocked.isLayoutDeferred()) { + // Reset the reasons at the first entrance because we only care about the changes in the + // deferred scope. + mLayoutReasons = 0; + } + + mWindowManager.mWindowPlacerLocked.deferLayout(); + } + + /** @see WindowSurfacePlacer#continueLayout */ + void continueWindowLayout() { + mWindowManager.mWindowPlacerLocked.continueLayout(mLayoutReasons != 0); + if (DEBUG_ALL && !mWindowManager.mWindowPlacerLocked.isLayoutDeferred()) { + Slog.i(TAG, "continueWindowLayout reason=" + mLayoutReasons); + } + } + + /** + * If a reason is added between {@link #deferWindowLayout} and {@link #continueWindowLayout}, + * it will make sure {@link WindowSurfacePlacer#performSurfacePlacement} is called when the last + * defer count is gone. + */ + void addWindowLayoutReasons(@LayoutReason int reasons) { + mLayoutReasons |= reasons; + } + private void updateEventDispatchingLocked(boolean booted) { mWindowManager.setEventDispatching(booted && !mShuttingDown); } @@ -6667,7 +6707,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } if (!restarting && hasVisibleActivities) { - mWindowManager.deferSurfaceLayout(); + deferWindowLayout(); try { if (!mRootActivityContainer.resumeFocusedStacksTopActivities()) { // If there was nothing to resume, and we are not already restarting @@ -6678,7 +6718,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { !PRESERVE_WINDOWS); } } finally { - mWindowManager.continueSurfaceLayout(); + continueWindowLayout(); } } } diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java index 422b6e58e0ed..d528ef6ec6a5 100644 --- a/services/core/java/com/android/server/wm/KeyguardController.java +++ b/services/core/java/com/android/server/wm/KeyguardController.java @@ -182,7 +182,7 @@ class KeyguardController { return; } Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "keyguardGoingAway"); - mWindowManager.deferSurfaceLayout(); + mService.deferWindowLayout(); try { setKeyguardGoingAway(true); EventLog.writeEvent(EventLogTags.AM_SET_KEYGUARD_SHOWN, @@ -204,7 +204,7 @@ class KeyguardController { mWindowManager.executeAppTransition(); } finally { Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "keyguardGoingAway: surfaceLayout"); - mWindowManager.continueSurfaceLayout(); + mService.continueWindowLayout(); Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); @@ -330,7 +330,7 @@ class KeyguardController { mWindowManager.onKeyguardOccludedChanged(isDisplayOccluded(DEFAULT_DISPLAY)); if (isKeyguardLocked()) { - mWindowManager.deferSurfaceLayout(); + mService.deferWindowLayout(); try { mRootActivityContainer.getDefaultDisplay().mDisplayContent .prepareAppTransition(resolveOccludeTransit(), @@ -340,7 +340,7 @@ class KeyguardController { mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS); mWindowManager.executeAppTransition(); } finally { - mWindowManager.continueSurfaceLayout(); + mService.continueWindowLayout(); } } dismissDockedStackIfNeeded(); diff --git a/services/core/java/com/android/server/wm/LaunchParamsController.java b/services/core/java/com/android/server/wm/LaunchParamsController.java index 59df09be1ff5..6de48d1b2d07 100644 --- a/services/core/java/com/android/server/wm/LaunchParamsController.java +++ b/services/core/java/com/android/server/wm/LaunchParamsController.java @@ -133,7 +133,7 @@ class LaunchParamsController { return false; } - mService.mWindowManager.deferSurfaceLayout(); + mService.deferWindowLayout(); try { if (mTmpParams.hasPreferredDisplay() @@ -161,7 +161,7 @@ class LaunchParamsController { task.setLastNonFullscreenBounds(mTmpParams.mBounds); return false; } finally { - mService.mWindowManager.continueSurfaceLayout(); + mService.continueWindowLayout(); } } diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java index 1a8944ab415b..5cabbd97b1f7 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimation.java +++ b/services/core/java/com/android/server/wm/RecentsAnimation.java @@ -196,7 +196,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks, mCaller.setRunningRecentsAnimation(true); } - mWindowManager.deferSurfaceLayout(); + mService.deferWindowLayout(); try { if (hasExistingActivity) { // Move the recents activity into place for the animation if it is not top most @@ -260,7 +260,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks, Slog.e(TAG, "Failed to start recents activity", e); throw e; } finally { - mWindowManager.continueSurfaceLayout(); + mService.continueWindowLayout(); Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); } } @@ -297,7 +297,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks, mWindowManager.inSurfaceTransaction(() -> { Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "RecentsAnimation#onAnimationFinished_inSurfaceTransaction"); - mWindowManager.deferSurfaceLayout(); + mService.deferWindowLayout(); try { mWindowManager.cleanupRecentsAnimation(reorderMode); @@ -387,7 +387,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks, Slog.e(TAG, "Failed to clean up recents activity", e); throw e; } finally { - mWindowManager.continueSurfaceLayout(); + mService.continueWindowLayout(); Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); } }); diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java index eeea18525751..d9e30a2da9a5 100644 --- a/services/core/java/com/android/server/wm/RootActivityContainer.java +++ b/services/core/java/com/android/server/wm/RootActivityContainer.java @@ -945,7 +945,7 @@ class RootActivityContainer extends ConfigurationContainer void moveActivityToPinnedStack(ActivityRecord r, Rect sourceHintBounds, float aspectRatio, String reason) { - mWindowManager.deferSurfaceLayout(); + mService.deferWindowLayout(); final ActivityDisplay display = r.getActivityStack().getDisplay(); ActivityStack stack = display.getPinnedStack(); @@ -994,7 +994,7 @@ class RootActivityContainer extends ConfigurationContainer // to the pinned stack r.supportsEnterPipOnTaskSwitch = false; } finally { - mWindowManager.continueSurfaceLayout(); + mService.continueWindowLayout(); } // Notify the pinned stack controller to prepare the PiP animation, expect callback @@ -2060,7 +2060,7 @@ class RootActivityContainer extends ConfigurationContainer * @param userId user handle for the locked managed profile. */ void lockAllProfileTasks(@UserIdInt int userId) { - mWindowManager.deferSurfaceLayout(); + mService.deferWindowLayout(); try { for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { final ActivityDisplay display = mActivityDisplays.get(displayNdx); @@ -2081,7 +2081,7 @@ class RootActivityContainer extends ConfigurationContainer } } } finally { - mWindowManager.continueSurfaceLayout(); + mService.continueWindowLayout(); } } diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java index d3f3981625d9..4b3691c88a06 100644 --- a/services/core/java/com/android/server/wm/TaskRecord.java +++ b/services/core/java/com/android/server/wm/TaskRecord.java @@ -545,7 +545,7 @@ class TaskRecord extends ConfigurationContainer { } boolean resize(Rect bounds, int resizeMode, boolean preserveWindow, boolean deferResume) { - mService.mWindowManager.deferSurfaceLayout(); + mService.deferWindowLayout(); try { if (!isResizeable()) { @@ -619,7 +619,7 @@ class TaskRecord extends ConfigurationContainer { Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); return kept; } finally { - mService.mWindowManager.continueSurfaceLayout(); + mService.continueWindowLayout(); } } @@ -725,7 +725,7 @@ class TaskRecord extends ConfigurationContainer { windowManager.setWillReplaceWindow(topActivity.appToken, animate); } - windowManager.deferSurfaceLayout(); + mService.deferWindowLayout(); boolean kept = true; try { final ActivityRecord r = topRunningActivityLocked(); @@ -809,7 +809,7 @@ class TaskRecord extends ConfigurationContainer { !mightReplaceWindow, deferResume); } } finally { - windowManager.continueSurfaceLayout(); + mService.continueWindowLayout(); } if (mightReplaceWindow) { diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 8d3a107c2f25..a7f6688f1ce7 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2775,21 +2775,6 @@ 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}. - */ - void deferSurfaceLayout() { - mWindowPlacerLocked.deferLayout(); - } - - /** Resumes layout passes after deferring them. See {@link #deferSurfaceLayout()} */ - void continueSurfaceLayout() { - mWindowPlacerLocked.continueLayout(); - } - - /** * Notifies activity manager that some Keyguard flags have changed and that it needs to * reevaluate the visibilities of the activities. * @param callback Runnable to be called when activity manager is done reevaluating visibilities diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java index cc7917879634..56f6d4b02e32 100644 --- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java +++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java @@ -25,7 +25,6 @@ import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD import android.os.Debug; import android.os.Trace; import android.util.Slog; -import android.util.SparseIntArray; import java.io.PrintWriter; @@ -50,8 +49,8 @@ class WindowSurfacePlacer { private boolean mTraversalScheduled; private int mDeferDepth = 0; - - private final SparseIntArray mTempTransitionReasons = new SparseIntArray(); + /** The number of layout requests when deferring. */ + private int mDeferredRequests; private final Runnable mPerformSurfacePlacement; @@ -65,19 +64,38 @@ class WindowSurfacePlacer { } /** - * See {@link WindowManagerService#deferSurfaceLayout()} + * 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 #continueLayout}. */ void deferLayout() { mDeferDepth++; } /** - * See {@link WindowManagerService#continueSurfaceLayout()} + * Resumes layout passes after deferring them. If there is a deferred direct invocation of + * {@link #performSurfacePlacement} ({@link #mDeferredRequests} > 0), when the defer is + * done, it will continue to perform layout. + * + * @param hasChanges Something has changed. That means whether to call + * {@link #performSurfacePlacement} when {@link #mDeferDepth} becomes zero. + * @see #deferLayout */ - void continueLayout() { + void continueLayout(boolean hasChanges) { mDeferDepth--; - if (mDeferDepth <= 0) { + if (mDeferDepth > 0) { + return; + } + + if (hasChanges || mDeferredRequests > 0) { + if (DEBUG) { + Slog.i(TAG, "continueLayout hasChanges=" + hasChanges + + " deferredRequests=" + mDeferredRequests + " " + Debug.getCallers(2, 3)); + } performSurfacePlacement(); + mDeferredRequests = 0; + } else if (DEBUG) { + Slog.i(TAG, "Cancel continueLayout " + Debug.getCallers(2, 3)); } } @@ -97,6 +115,7 @@ class WindowSurfacePlacer { final void performSurfacePlacement(boolean force) { if (mDeferDepth > 0 && !force) { + mDeferredRequests++; return; } int loopCount = 6; @@ -195,10 +214,19 @@ class WindowSurfacePlacer { } void requestTraversal() { - if (!mTraversalScheduled) { - mTraversalScheduled = true; - mService.mAnimationHandler.post(mPerformSurfacePlacement); + if (mTraversalScheduled) { + return; + } + + // Set as scheduled even the request will be deferred because mDeferredRequests is also + // increased, then the end of deferring will perform the request. + mTraversalScheduled = true; + if (mDeferDepth > 0) { + mDeferredRequests++; + if (DEBUG) Slog.i(TAG, "Defer requestTraversal " + Debug.getCallers(3)); + return; } + mService.mAnimationHandler.post(mPerformSurfacePlacement); } public void dump(PrintWriter pw, String prefix) { |