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

Commit 0ca6ebba authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Apply rotation change on display thread

This aligns the same behavior as legacy that posts
continueDisplayChange to display thread.

Otherwise the display info change (triggered from
DisplayContent#updateDisplayAndOrientation -> setDisplayInfoOverrideFromWindowManager and then dispatch on
display thread) will reach client before window manger requests
resizing with buffer synchronization (shouldSyncWithBuffers).

This can also reduce about 10ms in WM lock because the display
thread is set to top-app sched group that usually runs on the
big core.

Also with this and [1] (transform hint), the workaround to force
full-blast-sync for 180 degree rotation is no longer needed.

[1]: Id4ad45adb9719b078f46040a09f786092c325a8a

Bug: 288105083
Test: Rotate device by 180 degree and observe display cutout
      doesn't show on opposite position.

Change-Id: I7e1de5b5fe12cb30b5f48808ea6b0a2214c0f339
parent f2c66dee
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -77,6 +77,7 @@ import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.IRemoteCallback;
import android.os.Looper;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.Trace;
@@ -2686,6 +2687,26 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
        });
    }

    /**
     * Returns {@code true} if the transition and the corresponding transaction should be applied
     * on display thread. Currently, this only checks for display rotation change because the order
     * of dispatching the new display info will be after requesting the windows to sync drawing.
     * That avoids potential flickering of screen overlays (e.g. cutout, rounded corner). Also,
     * because the display thread has a higher priority, it is faster to perform the configuration
     * changes and window hierarchy traversal.
     */
    boolean shouldApplyOnDisplayThread() {
        for (int i = mParticipants.size() - 1; i >= 0; --i) {
            final DisplayContent dc = mParticipants.valueAt(i).asDisplayContent();
            if (dc == null) continue;
            final ChangeInfo changeInfo = mChanges.get(dc);
            if (changeInfo != null && changeInfo.mRotation != dc.getRotation()) {
                return Looper.myLooper() != mController.mAtm.mWindowManager.mH.getLooper();
            }
        }
        return false;
    }

    /** Applies the new configuration for the changed displays. */
    void applyDisplayChangeIfNeeded() {
        for (int i = mParticipants.size() - 1; i >= 0; --i) {
+0 −9
Original line number Diff line number Diff line
@@ -588,15 +588,6 @@ class TransitionController {
    /** Sets the sync method for the display change. */
    private void setDisplaySyncMethod(@NonNull TransitionRequestInfo.DisplayChange displayChange,
            @NonNull Transition displayTransition, @NonNull DisplayContent displayContent) {
        final int startRotation = displayChange.getStartRotation();
        final int endRotation = displayChange.getEndRotation();
        if (startRotation != endRotation && (startRotation + endRotation) % 2 == 0) {
            // 180 degrees rotation change may not change screen size. So the clients may draw
            // some frames before and after the display projection transaction is applied by the
            // remote player. That may cause some buffers to show in different rotation. So use
            // sync method to pause clients drawing until the projection transaction is applied.
            mSyncEngine.setSyncMethod(displayTransition.getSyncId(), BLASTSyncEngine.METHOD_BLAST);
        }
        final Rect startBounds = displayChange.getStartAbsBounds();
        final Rect endBounds = displayChange.getEndAbsBounds();
        if (startBounds == null || endBounds == null) return;
+11 −2
Original line number Diff line number Diff line
@@ -321,9 +321,18 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
                    applyTransaction(wct, -1 /*syncId*/, null /*transition*/, caller);
                    return transition.getToken();
                }
                transition.start();
                transition.mLogger.mStartWCT = wct;
                if (transition.shouldApplyOnDisplayThread()) {
                    mService.mH.post(() -> {
                        synchronized (mService.mGlobalLock) {
                            transition.start();
                            applyTransaction(wct, -1 /* syncId */, transition, caller);
                        }
                    });
                } else {
                    transition.start();
                    applyTransaction(wct, -1 /* syncId */, transition, caller);
                }
                // Since the transition is already provided, it means WMCore is determining the
                // "readiness lifecycle" outside the provided transaction, so don't set ready here.
                return transition.getToken();
+1 −0
Original line number Diff line number Diff line
@@ -2046,6 +2046,7 @@ public class DisplayContentTests extends WindowTestsBase {

        // Once transition starts, rotation is applied and transition shows DC rotating.
        testPlayer.startTransition();
        waitUntilHandlersIdle();
        assertNotEquals(origRot, dc.getConfiguration().windowConfiguration.getRotation());
        assertNotNull(testPlayer.mLastReady);
        assertTrue(testPlayer.mController.isPlaying());