Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 03de64be authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Finish sync for unchanged drawn window

A window may be collected while it is drawn without state changes.
So after surface placement, if the window is not added to be resizing
(updateResizingWindowIfNeeded is not called), the window can be
considered as ready to reduce the time of waiting next redraw or even
transition timeout.

For example (shell transition): Activity X starts Y in the same task
and X finishes when the previous transition animation is running.
X's draw state (drawn) and visibility (visible) are not changed. Then
the closing transition may be timeout.

Though the timeout can also be fixed by calling DC#setLayoutNeeded
(to trigger updateResizingWindowIfNeeded) in SyncGroup#setReady, it
means that the transition needs to wait for the unnecessary redraw.

This can also handle the case of
I49746b56e7dda76c530366663000b0d11ae779f3

Bug: 260059642
Test: atest SyncEngineTests WindowOrganizerTests

Change-Id: I4615eb17553ffb6635a0c39c849b44c80d03f41e
parent 2fafc8df
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -3744,7 +3744,6 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
        if (mSyncState == SYNC_STATE_NONE) return false;
        mSyncState = SYNC_STATE_READY;
        mSyncMethodOverride = BLASTSyncEngine.METHOD_UNDEFINED;
        mWmService.mWindowPlacerLocked.requestTraversal();
        ProtoLog.v(WM_DEBUG_SYNC_ENGINE, "onSyncFinishedDrawing %s", this);
        return true;
    }
@@ -3814,8 +3813,8 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<

    /**
     * Checks if the subtree rooted at this container is finished syncing (everything is ready or
     * not visible). NOTE, this is not const: it will cancel/prepare itself depending on its state
     * in the hierarchy.
     * not visible). NOTE, this is not const: it may cancel/prepare/complete itself depending on
     * its state in the hierarchy.
     *
     * @return {@code true} if this subtree is finished waiting for sync participants.
     */
+0 −6
Original line number Diff line number Diff line
@@ -2587,12 +2587,6 @@ public class WindowManagerService extends IWindowManager.Stub
                        && win.mSyncSeqId > lastSyncSeqId) {
                    maybeSyncSeqId = win.shouldSyncWithBuffers() ? win.mSyncSeqId : -1;
                    win.markRedrawForSyncReported();
                    if (win.mSyncState == WindowContainer.SYNC_STATE_WAITING_FOR_DRAW
                            && winAnimator.mDrawState == WindowStateAnimator.HAS_DRAWN
                            && maybeSyncSeqId < 0) {
                        // Do not wait for a drawn window which won't report draw.
                        win.onSyncFinishedDrawing();
                    }
                } else {
                    maybeSyncSeqId = -1;
                }
+10 −5
Original line number Diff line number Diff line
@@ -6004,12 +6004,16 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP

    @Override
    boolean isSyncFinished() {
        if (mSyncState == SYNC_STATE_WAITING_FOR_DRAW && mViewVisibility != View.VISIBLE
                && !isVisibleRequested()) {
        if (!isVisibleRequested()) {
            // Don't wait for invisible windows. However, we don't alter the state in case the
            // window becomes visible while the sync group is still active.
            return true;
        }
        if (mSyncState == SYNC_STATE_WAITING_FOR_DRAW && mWinAnimator.mDrawState == HAS_DRAWN
                && !mRedrawForSyncReported && !mWmService.mResizingWindows.contains(this)) {
            // Complete the sync state immediately for a drawn window that doesn't need to redraw.
            onSyncFinishedDrawing();
        }
        return super.isSyncFinished();
    }

@@ -6060,6 +6064,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
        final boolean hasSyncHandlers = executeDrawHandlers(postDrawTransaction, syncSeqId);

        boolean skipLayout = false;
        boolean layoutNeeded = false;
        // Control the timing to switch the appearance of window with different rotations.
        final AsyncRotationController asyncRotationController =
                mDisplayContent.getAsyncRotationController();
@@ -6072,7 +6077,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
        } else if (syncActive) {
            // Currently in a Sync that is using BLAST.
            if (!syncStillPending) {
                onSyncFinishedDrawing();
                layoutNeeded = onSyncFinishedDrawing();
            }
            if (postDrawTransaction != null) {
                mSyncTransaction.merge(postDrawTransaction);
@@ -6081,10 +6086,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
            }
        } else if (useBLASTSync()) {
            // Sync that is not using BLAST
            onSyncFinishedDrawing();
            layoutNeeded = onSyncFinishedDrawing();
        }

        final boolean layoutNeeded =
        layoutNeeded |=
                mWinAnimator.finishDrawingLocked(postDrawTransaction, mClientWasDrawingForSync);
        mClientWasDrawingForSync = false;
        // We always want to force a traversal after a finish draw for blast sync.
+2 −3
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import static com.android.server.wm.WindowState.BLAST_TIMEOUT_DURATION;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
@@ -108,9 +109,7 @@ public class SyncEngineTests extends WindowTestsBase {
        bse.onSurfacePlacement();
        verify(listener, times(0)).onTransactionReady(anyInt(), any());

        mockWC.onSyncFinishedDrawing();
        // Make sure the second traversal is requested.
        verify(mWm.mWindowPlacerLocked, times(2)).requestTraversal();
        assertTrue(mockWC.onSyncFinishedDrawing());
        bse.onSurfacePlacement();
        verify(listener, times(1)).onTransactionReady(eq(id), notNull());
    }
+2 −1
Original line number Diff line number Diff line
@@ -1240,7 +1240,8 @@ public class WindowOrganizerTests extends WindowTestsBase {
        assertTrue(w1.useBLASTSync());
        assertTrue(w2.useBLASTSync());

        w1.immediatelyNotifyBlastSync();
        // A drawn window can complete the sync state automatically.
        w1.mWinAnimator.mDrawState = WindowStateAnimator.HAS_DRAWN;
        mWm.mSyncEngine.onSurfacePlacement();
        verify(mockCallback).onTransactionReady(anyInt(), any());
        assertFalse(w1.useBLASTSync());