diff options
| author | 2024-05-06 21:50:10 +0800 | |
|---|---|---|
| committer | 2024-05-07 20:59:16 +0800 | |
| commit | adaa572912e29a8d7cc4c94d7af75a8e8915ce90 (patch) | |
| tree | f0d16864ab148579eed6a6cebe2b5469a0b666ae | |
| parent | a8f99519ab3fec77352f506c62c057e480ae90af (diff) | |
Reduce unnecessary sync redraw without changes
If a window was drawn and its parent container's prepareSync is called,
the window will always redraw even if there is nothing change to it.
For example, when cold launching an activity in a different orientation,
the app window and starting window can be drawn first and then display
updates. The prepareSync from display will request the 2 windows redraw
but the windows already have the latest state.
In general, prepareSync is usually called before knowing whether there
will be a change. Then updateResizingWindowIfNeeded can give a chance
to filter necessary redraw request.
Bug: 231435331
Bug: 297493149
Test: atest WindowStateTests#testRequestResizeForBlastSync
Change-Id: Id9134e7c71d37357d39d864b3d502ba5bdaebdc2
| -rw-r--r-- | services/core/java/com/android/server/wm/WindowState.java | 15 | ||||
| -rw-r--r-- | services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java | 23 |
2 files changed, 29 insertions, 9 deletions
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index c25080f9e756..6e6aba13347e 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -1443,14 +1443,17 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP + " last=" + mWindowFrames.mLastFrame + " frame=" + mWindowFrames.mFrame); } + final boolean contentChanged = didFrameInsetsChange || configChanged + || dragResizingChanged || attachedFrameChanged; + // Cancel unchanged non-sync-buffer redraw request to avoid unnecessary reportResized(). + if (!contentChanged && !mRedrawForSyncReported && mPrepareSyncSeqId <= 0 + && mDrawHandlers.isEmpty()) { + mRedrawForSyncReported = true; + } + // Add a window that is using blastSync to the resizing list if it hasn't been reported // already. This because the window is waiting on a finishDrawing from the client. - if (didFrameInsetsChange - || configChanged - || insetsChanged - || dragResizingChanged - || shouldSendRedrawForSync() - || attachedFrameChanged) { + if (contentChanged || insetsChanged || shouldSendRedrawForSync()) { ProtoLog.v(WM_DEBUG_RESIZE, "Resize reasons for w=%s: %s configChanged=%b didFrameInsetsChange=%b", this, mWindowFrames.getInsetsChangedInfo(), 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 fbbb9a2e55a7..b152c3e5355f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -819,17 +819,20 @@ public class WindowStateTests extends WindowTestsBase { assertFalse(win.getOrientationChanging()); } - @SetupWindows(addWindows = W_ABOVE_ACTIVITY) @Test public void testRequestResizeForBlastSync() { - final WindowState win = mChildAppWindowAbove; - makeWindowVisible(win, win.getParentWindow()); + final WindowState win = createWindow(null, TYPE_APPLICATION, "window"); + makeWindowVisible(win); + makeLastConfigReportedToClient(win, true /* visible */); win.mLayoutSeq = win.getDisplayContent().mLayoutSeq; win.reportResized(); win.updateResizingWindowIfNeeded(); assertThat(mWm.mResizingWindows).doesNotContain(win); // Check that the window is in resizing if using blast sync. + final BLASTSyncEngine.SyncGroup syncGroup = mock(BLASTSyncEngine.SyncGroup.class); + syncGroup.mSyncMethod = BLASTSyncEngine.METHOD_BLAST; + win.mSyncGroup = syncGroup; win.reportResized(); win.prepareSync(); assertEquals(SYNC_STATE_WAITING_FOR_DRAW, win.mSyncState); @@ -842,6 +845,20 @@ public class WindowStateTests extends WindowTestsBase { mWm.mResizingWindows.remove(win); win.updateResizingWindowIfNeeded(); assertThat(mWm.mResizingWindows).doesNotContain(win); + + // Non blast sync doesn't require to force resizing, because it won't use syncSeqId. + // And if the window is already drawn, it can report sync finish immediately so that the + // sync group won't be blocked. + win.finishSync(mTransaction, syncGroup, false /* cancel */); + syncGroup.mSyncMethod = BLASTSyncEngine.METHOD_NONE; + win.mSyncGroup = syncGroup; + win.mWinAnimator.mDrawState = WindowStateAnimator.HAS_DRAWN; + win.prepareSync(); + assertEquals(SYNC_STATE_WAITING_FOR_DRAW, win.mSyncState); + win.updateResizingWindowIfNeeded(); + assertThat(mWm.mResizingWindows).doesNotContain(win); + assertTrue(win.isSyncFinished(syncGroup)); + assertEquals(WindowContainer.SYNC_STATE_READY, win.mSyncState); } @Test |