Loading services/core/java/com/android/server/wm/Transition.java +21 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -2696,6 +2697,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) { Loading services/core/java/com/android/server/wm/TransitionController.java +0 −9 Original line number Diff line number Diff line Loading @@ -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; Loading services/core/java/com/android/server/wm/WindowOrganizerController.java +11 −2 Original line number Diff line number Diff line Loading @@ -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(); Loading services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +1 −0 Original line number Diff line number Diff line Loading @@ -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()); Loading Loading
services/core/java/com/android/server/wm/Transition.java +21 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -2696,6 +2697,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) { Loading
services/core/java/com/android/server/wm/TransitionController.java +0 −9 Original line number Diff line number Diff line Loading @@ -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; Loading
services/core/java/com/android/server/wm/WindowOrganizerController.java +11 −2 Original line number Diff line number Diff line Loading @@ -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(); Loading
services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +1 −0 Original line number Diff line number Diff line Loading @@ -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()); Loading