From 31a3779b15c47aea060c7bf37bb09d05437538af Mon Sep 17 00:00:00 2001 From: Riddle Hsu Date: Wed, 15 Feb 2023 16:33:12 +0800 Subject: [PATCH] Check config change for reporting resize and requesting redraw Since multi-window mode is supported, the orientation change is not the only source that requires redraw. It is confusing to use "set orientation change" to handle other cases that also need to redraw. So simplify the condition to check if there is a config change of the window. While drag-resizing is similar, the end of drag-resizing should also trigger a config change. Also - Reset mLastConfigReportedToClient only if the config is changed. This can avoid unnecessary redraw request if a window is reparented to another container with the same configuration. - Set mWaitingForConfig for 180 rotation because since WindowConfiguration was introduced, there will be always a configuration change for rotation change. - Add trace for global config change. Bug: 159103089 Test: WindowStateTests Change-Id: I50d4c5b741be960bd2850e4bcd0ab62ad32c19dc --- data/etc/services.core.protolog.json | 18 ++--- .../server/wm/ActivityTaskManagerService.java | 4 ++ .../android/server/wm/DisplayRotation.java | 6 +- .../com/android/server/wm/WindowFrames.java | 3 +- .../com/android/server/wm/WindowState.java | 72 +++++-------------- .../server/wm/DisplayContentTests.java | 3 +- .../android/server/wm/WindowStateTests.java | 13 +--- 7 files changed, 35 insertions(+), 84 deletions(-) diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index 0d74e125e68aa..3d81d37aff20f 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -919,12 +919,6 @@ "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "-1270148832": { - "message": "Resize start waiting for draw, mDrawState=DRAW_PENDING in %s, surfaceController %s", - "level": "VERBOSE", - "group": "WM_DEBUG_RESIZE", - "at": "com\/android\/server\/wm\/WindowState.java" - }, "-1263316010": { "message": "Computed rotation=%s (%d) for display id=%d based on lastOrientation=%s (%d) and oldRotation=%s (%d)", "level": "VERBOSE", @@ -2305,12 +2299,6 @@ "group": "WM_DEBUG_RECENTS_ANIMATIONS", "at": "com\/android\/server\/wm\/RecentsAnimationController.java" }, - "25888308": { - "message": "Resize reasons for w=%s: %s configChanged=%b dragResizingChanged=%b", - "level": "VERBOSE", - "group": "WM_DEBUG_RESIZE", - "at": "com\/android\/server\/wm\/WindowState.java" - }, "34682671": { "message": "Not moving display (displayId=%d) to top. Top focused displayId=%d. Reason: FLAG_STEAL_TOP_FOCUS_DISABLED", "level": "INFO", @@ -3097,6 +3085,12 @@ "group": "WM_DEBUG_RESIZE", "at": "com\/android\/server\/wm\/WindowState.java" }, + "686185515": { + "message": "Resize reasons for w=%s: %s configChanged=%b didFrameInsetsChange=%b", + "level": "VERBOSE", + "group": "WM_DEBUG_RESIZE", + "at": "com\/android\/server\/wm\/WindowState.java" + }, "691515534": { "message": " Commit wallpaper becoming invisible: %s", "level": "VERBOSE", diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index e8a0386a5c626..5c20cedbee7cd 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -4397,6 +4397,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { return 0; } + Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateGlobalConfiguration"); ProtoLog.i(WM_DEBUG_CONFIGURATION, "Updating global configuration " + "to: %s", values); writeConfigurationChanged(changes); @@ -4482,9 +4483,12 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { mAmInternal, changes, initLocale); mH.sendMessage(msg); + Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "RootConfigChange"); // Update stored global config and notify everyone about the change. mRootWindowContainer.onConfigurationChanged(mTempConfig); + Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); + Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); return changes; } diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java index c0817250bd146..24a1749c65c82 100644 --- a/services/core/java/com/android/server/wm/DisplayRotation.java +++ b/services/core/java/com/android/server/wm/DisplayRotation.java @@ -19,7 +19,6 @@ package com.android.server.wm; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; -import static android.util.RotationUtils.deltaRotation; import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE; import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT; import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE; @@ -575,13 +574,10 @@ public class DisplayRotation { "Display id=%d rotation changed to %d from %d, lastOrientation=%d", displayId, rotation, oldRotation, lastOrientation); - if (deltaRotation(oldRotation, rotation) != Surface.ROTATION_180) { - mDisplayContent.mWaitingForConfig = true; - } - mRotation = rotation; mDisplayContent.setLayoutNeeded(); + mDisplayContent.mWaitingForConfig = true; if (mDisplayContent.mTransitionController.isShellTransitionsEnabled()) { final boolean wasCollecting = mDisplayContent.mTransitionController.isCollecting(); diff --git a/services/core/java/com/android/server/wm/WindowFrames.java b/services/core/java/com/android/server/wm/WindowFrames.java index 1cb63032b07d9..fbd226e46edf7 100644 --- a/services/core/java/com/android/server/wm/WindowFrames.java +++ b/services/core/java/com/android/server/wm/WindowFrames.java @@ -192,6 +192,7 @@ public class WindowFrames { } String getInsetsChangedInfo() { - return "forceReportingResized=" + mLastForceReportingResized; + return "forceReportingResized=" + mLastForceReportingResized + + " insetsChanged=" + mInsetsChanged; } } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 69e84c76ac3b6..b8d4de5313f39 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -22,6 +22,7 @@ import static android.app.AppOpsManager.MODE_DEFAULT; import static android.app.AppOpsManager.OP_NONE; import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; +import static android.content.pm.ActivityInfo.CONFIG_WINDOW_CONFIGURATION; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.graphics.GraphicsProtos.dumpPointProto; import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS; @@ -1475,15 +1476,11 @@ class WindowState extends WindowContainer implements WindowManagerP Slog.v(TAG_WM, "Win " + this + " config changed: " + getConfiguration()); } - final boolean dragResizingChanged = isDragResizeChanged() - && !isDragResizingChangeReported(); - final boolean attachedFrameChanged = LOCAL_LAYOUT && mLayoutAttached && getParentWindow().frameChanged(); if (DEBUG) { Slog.v(TAG_WM, "Resizing " + this + ": configChanged=" + configChanged - + " dragResizingChanged=" + dragResizingChanged + " last=" + mWindowFrames.mLastFrame + " frame=" + mWindowFrames.mFrame); } @@ -1492,13 +1489,12 @@ class WindowState extends WindowContainer implements WindowManagerP if (didFrameInsetsChange || configChanged || insetsChanged - || dragResizingChanged || shouldSendRedrawForSync() || attachedFrameChanged) { ProtoLog.v(WM_DEBUG_RESIZE, - "Resize reasons for w=%s: %s configChanged=%b dragResizingChanged=%b", + "Resize reasons for w=%s: %s configChanged=%b didFrameInsetsChange=%b", this, mWindowFrames.getInsetsChangedInfo(), - configChanged, dragResizingChanged); + configChanged, didFrameInsetsChange); if (insetsChanged) { mWindowFrames.setInsetsChanged(false); @@ -1518,18 +1514,9 @@ class WindowState extends WindowContainer implements WindowManagerP onResizeHandled(); mWmService.makeWindowFreezingScreenIfNeededLocked(this); - // If the orientation is changing, or we're starting or ending a drag resizing action, - // or we're resizing an embedded Activity, then we need to hold off on unfreezing the - // display until this window has been redrawn; to do that, we need to go through the - // process of getting informed by the application when it has finished drawing. - if (getOrientationChanging() || dragResizingChanged - || isEmbeddedActivityResizeChanged()) { - if (dragResizingChanged) { - ProtoLog.v(WM_DEBUG_RESIZE, - "Resize start waiting for draw, " - + "mDrawState=DRAW_PENDING in %s, surfaceController %s", - this, winAnimator.mSurfaceController); - } + // Reset the drawn state if the window need to redraw for the change, so the transition + // can wait until it has finished drawing to start. + if ((configChanged || getOrientationChanging()) && isVisibleRequested()) { winAnimator.mDrawState = DRAW_PENDING; if (mActivityRecord != null) { mActivityRecord.clearAllDrawn(); @@ -1560,6 +1547,10 @@ class WindowState extends WindowContainer implements WindowManagerP } boolean getOrientationChanging() { + if (mTransitionController.isShellTransitionsEnabled()) { + // Shell transition doesn't use the methods for display frozen state. + return false; + } // In addition to the local state flag, we must also consider the difference in the last // reported configuration vs. the current state. If the client code has not been informed of // the change, logic dependent on having finished processing the orientation, such as @@ -2361,21 +2352,21 @@ class WindowState extends WindowContainer implements WindowManagerP @Override public void onConfigurationChanged(Configuration newParentConfig) { - if (getDisplayContent().getImeInputTarget() != this && !isImeLayeringTarget()) { - super.onConfigurationChanged(newParentConfig); - return; - } - mTempConfiguration.setTo(getConfiguration()); super.onConfigurationChanged(newParentConfig); - final boolean windowConfigChanged = mTempConfiguration.windowConfiguration - .diff(newParentConfig.windowConfiguration, false) != 0; + final int diff = getConfiguration().diff(mTempConfiguration); + if (diff != 0) { + mLastConfigReportedToClient = false; + } + if (getDisplayContent().getImeInputTarget() != this && !isImeLayeringTarget()) { + return; + } // When the window configuration changed, we need to update the IME control target in // case the app may lose the IME inets control when exiting from split-screen mode, or the // IME parent may failed to attach to the app during rotating the screen. // See DisplayContent#shouldImeAttachedToApp, DisplayContent#isImeControlledByApp - if (windowConfigChanged) { + if ((diff & CONFIG_WINDOW_CONFIGURATION) != 0) { // If the window was the IME layering target, updates the IME surface parent in case // the IME surface may be wrongly positioned when the window configuration affects the // IME surface association. (e.g. Attach IME surface on the display instead of the @@ -2384,12 +2375,6 @@ class WindowState extends WindowContainer implements WindowManagerP } } - @Override - void onMergedOverrideConfigurationChanged() { - super.onMergedOverrideConfigurationChanged(); - mLastConfigReportedToClient = false; - } - void onWindowReplacementTimeout() { if (mWillReplaceWindow) { // Since the window already timed out, remove it immediately now. @@ -4142,20 +4127,6 @@ class WindowState extends WindowContainer implements WindowManagerP return mActivityRecord == null || mActivityRecord.isFullyTransparentBarAllowed(frame); } - /** - * Whether this window belongs to a resizing embedded activity. - */ - private boolean isEmbeddedActivityResizeChanged() { - if (mActivityRecord == null || !isVisibleRequested()) { - // No need to update if the window is in the background. - return false; - } - - final TaskFragment embeddedTaskFragment = mActivityRecord.getOrganizedTaskFragment(); - return embeddedTaskFragment != null - && mDisplayContent.mChangingContainers.contains(embeddedTaskFragment); - } - boolean isDragResizeChanged() { return mDragResizing != computeDragResizing(); } @@ -4168,13 +4139,6 @@ class WindowState extends WindowContainer implements WindowManagerP super.setWaitingForDrawnIfResizingChanged(); } - /** - * @return Whether we reported a drag resize change to the application or not already. - */ - private boolean isDragResizingChangeReported() { - return mDragResizingChangeReported; - } - /** * Resets the state whether we reported a drag resize change to the app. */ diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index bfd99fd38a4b0..aaeae239024d4 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -1942,12 +1942,11 @@ public class DisplayContentTests extends WindowTestsBase { final DisplayContent dc = mDisplayContent; final DisplayRotation dr = dc.getDisplayRotation(); spyOn(dr); - // Rotate 180 degree so the display doesn't have configuration change. This condition is - // used for the later verification of stop-freezing (without setting mWaitingForConfig). doReturn((dr.getRotation() + 2) % 4).when(dr).rotationForOrientation(anyInt(), anyInt()); final boolean[] continued = new boolean[1]; doAnswer(invocation -> { continued[0] = true; + mDisplayContent.mWaitingForConfig = false; mAtm.addWindowLayoutReasons(ActivityTaskManagerService.LAYOUT_REASON_CONFIG_CHANGED); return true; }).when(dc).updateDisplayOverrideConfigurationLocked(); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java index b2d8fedb97a69..3aee2cd5fac1f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -730,9 +730,8 @@ public class WindowStateTests extends WindowTestsBase { invisibleApp.requestDrawIfNeeded(outWaitingForDrawn); assertTrue(outWaitingForDrawn.isEmpty()); - // Drawn state should not be changed for insets change when screen is off. - spyOn(mWm.mPolicy); - doReturn(false).when(mWm.mPolicy).isScreenOn(); + // Drawn state should not be changed for insets change if the window is not visible. + startingApp.mActivityRecord.setVisibleRequested(false); makeWindowVisibleAndDrawn(startingApp); startingApp.getConfiguration().orientation = 0; // Reset to be the same as last reported. startingApp.getWindowFrames().setInsetsChanged(true); @@ -742,9 +741,7 @@ public class WindowStateTests extends WindowTestsBase { assertFalse(startingApp.getOrientationChanging()); // Even if the display is frozen, invisible requested window should not be affected. - startingApp.mActivityRecord.setVisibleRequested(false); mWm.startFreezingDisplay(0, 0, mDisplayContent); - doReturn(true).when(mWm.mPolicy).isScreenOn(); startingApp.getWindowFrames().setInsetsChanged(true); startingApp.updateResizingWindowIfNeeded(); assertTrue(startingApp.isDrawn()); @@ -830,11 +827,7 @@ public class WindowStateTests extends WindowTestsBase { win.reportResized(); embeddedTf.setBounds(500, 0, 1000, 2000); - // Clear all drawn when the embedded TaskFragment is in mDisplayContent.mChangingContainers. - win.updateResizingWindowIfNeeded(); - verify(embeddedActivity, never()).clearAllDrawn(); - - mDisplayContent.mChangingContainers.add(embeddedTf); + // Clear all drawn when the window config of embedded TaskFragment is changed. win.updateResizingWindowIfNeeded(); verify(embeddedActivity).clearAllDrawn(); }