Loading core/java/android/window/flags/windowing_frontend.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,16 @@ flag { } } flag { name: "wait_for_present_fence_on_display_switch" namespace: "windowing_frontend" description: "Wait for start transaction's present fence when folding/unfolding" bug: "370719724" metadata { purpose: PURPOSE_BUGFIX } } flag { name: "enforce_edge_to_edge" is_exported: true Loading services/core/java/com/android/server/wm/DeferredDisplayUpdater.java +2 −2 Original line number Diff line number Diff line Loading @@ -294,7 +294,7 @@ class DeferredDisplayUpdater { getCurrentDisplayChange(fromRotation, startBounds); displayChange.setPhysicalDisplayChanged(true); transition.addTransactionCompletedListener(this::continueScreenUnblocking); transition.addTransactionPresentedListener(this::continueScreenUnblocking); mDisplayContent.mTransitionController.requestStartTransition(transition, /* startTask= */ null, /* remoteTransition= */ null, displayChange); Loading Loading @@ -366,7 +366,7 @@ class DeferredDisplayUpdater { /** * Continues the screen unblocking flow, could be called either on a binder thread as * a result of surface transaction completed listener or from {@link WindowManagerService#mH} * a result of surface transaction presented listener or from {@link WindowManagerService#mH} * handler in case of timeout */ private void continueScreenUnblocking() { Loading services/core/java/com/android/server/wm/Transition.java +57 −12 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import static android.app.WindowConfiguration.ROTATION_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.hardware.SyncFence.SIGNAL_TIME_PENDING; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; Loading Loading @@ -95,6 +96,7 @@ import android.content.pm.ActivityInfo; import android.graphics.Point; import android.graphics.Rect; import android.hardware.HardwareBuffer; import android.hardware.SyncFence; import android.os.Binder; import android.os.Bundle; import android.os.Debug; Loading Loading @@ -134,6 +136,7 @@ import com.android.window.flags.Flags; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.ref.WeakReference; import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.Objects; Loading Loading @@ -265,8 +268,10 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { */ private ArrayList<Task> mTransientHideTasks; private static final Duration TRANSACTION_PRESENTED_TIMEOUT = Duration.ofSeconds(1); @VisibleForTesting ArrayList<Runnable> mTransactionCompletedListeners = null; ArrayList<Runnable> mTransactionPresentedListeners = null; private ArrayList<Runnable> mTransitionEndedListeners = null; Loading Loading @@ -1911,13 +1916,17 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { commitVisibleActivities(transaction); commitVisibleWallpapers(transaction); if (mTransactionCompletedListeners != null) { for (int i = 0; i < mTransactionCompletedListeners.size(); i++) { final Runnable listener = mTransactionCompletedListeners.get(i); transaction.addTransactionCompletedListener(Runnable::run, (stats) -> listener.run()); if (mTransactionPresentedListeners != null) { final List<Runnable> transactionPresentedListeners = new ArrayList<>(mTransactionPresentedListeners); addTransactionPresentedCallback(transaction, () -> { for (int i = 0; i < transactionPresentedListeners.size(); i++) { transactionPresentedListeners.get(i).run(); } mTransactionCompletedListeners = null; }); mTransactionPresentedListeners = null; } // Fall-back to the default display if there isn't one participating. Loading Loading @@ -2266,11 +2275,11 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { * Adds a listener that will be executed after the start transaction of this transition * is presented on the screen, the listener will be executed on a binder thread */ void addTransactionCompletedListener(Runnable listener) { if (mTransactionCompletedListeners == null) { mTransactionCompletedListeners = new ArrayList<>(); void addTransactionPresentedListener(Runnable listener) { if (mTransactionPresentedListeners == null) { mTransactionPresentedListeners = new ArrayList<>(); } mTransactionCompletedListeners.add(listener); mTransactionPresentedListeners.add(listener); } /** Loading @@ -2287,6 +2296,42 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { mTransitionEndedListeners.add(listener); } private void addTransactionPresentedCallback(SurfaceControl.Transaction transaction, Runnable onPresented) { transaction.addTransactionCompletedListener(Runnable::run, (stats) -> { if (com.android.window.flags.Flags.waitForPresentFenceOnDisplaySwitch()) { final SyncFence fence = stats.getPresentFence(); waitForPresentFence(fence, onPresented); } else { onPresented.run(); } }); } private void waitForPresentFence(SyncFence fence, Runnable onPresented) { try { if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) { Trace.beginSection("Awaiting for the present fence"); } fence.await(TRANSACTION_PRESENTED_TIMEOUT); } finally { if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) { Trace.endSection(); } onPresented.run(); final long signalTime = fence.getSignalTime(); if (signalTime == SIGNAL_TIME_PENDING) { Slog.e(TAG, "Timeout occurred when waiting for the transaction " + "to be presented"); } fence.close(); } } /** * Checks if the transition contains order changes. * Loading services/tests/wmtests/src/com/android/server/wm/DisplayContentDeferredUpdateTests.java +6 −6 Original line number Diff line number Diff line Loading @@ -231,7 +231,7 @@ public class DisplayContentDeferredUpdateTests extends WindowTestsBase { when(mDisplayContent.mTransitionController.inTransition()).thenReturn(false); final Transition transition = captureRequestedTransition().getValue(); makeTransitionTransactionCompleted(transition); makeTransitionTransactionPresented(transition); // Verify that screen is unblocked as start transaction of the transition // has been completed Loading Loading @@ -308,7 +308,7 @@ public class DisplayContentDeferredUpdateTests extends WindowTestsBase { // Mark start transactions as presented when(mDisplayContent.mTransitionController.inTransition()).thenReturn(false); captureRequestedTransition().getAllValues().forEach( this::makeTransitionTransactionCompleted); this::makeTransitionTransactionPresented); // Verify that the default screen unblocker is sent only after start transaction // of the Shell transition is presented Loading Loading @@ -355,10 +355,10 @@ public class DisplayContentDeferredUpdateTests extends WindowTestsBase { return callbackCaptor; } private void makeTransitionTransactionCompleted(Transition transition) { if (transition.mTransactionCompletedListeners != null) { for (int i = 0; i < transition.mTransactionCompletedListeners.size(); i++) { final Runnable listener = transition.mTransactionCompletedListeners.get(i); private void makeTransitionTransactionPresented(Transition transition) { if (transition.mTransactionPresentedListeners != null) { for (int i = 0; i < transition.mTransactionPresentedListeners.size(); i++) { final Runnable listener = transition.mTransactionPresentedListeners.get(i); listener.run(); } } Loading Loading
core/java/android/window/flags/windowing_frontend.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,16 @@ flag { } } flag { name: "wait_for_present_fence_on_display_switch" namespace: "windowing_frontend" description: "Wait for start transaction's present fence when folding/unfolding" bug: "370719724" metadata { purpose: PURPOSE_BUGFIX } } flag { name: "enforce_edge_to_edge" is_exported: true Loading
services/core/java/com/android/server/wm/DeferredDisplayUpdater.java +2 −2 Original line number Diff line number Diff line Loading @@ -294,7 +294,7 @@ class DeferredDisplayUpdater { getCurrentDisplayChange(fromRotation, startBounds); displayChange.setPhysicalDisplayChanged(true); transition.addTransactionCompletedListener(this::continueScreenUnblocking); transition.addTransactionPresentedListener(this::continueScreenUnblocking); mDisplayContent.mTransitionController.requestStartTransition(transition, /* startTask= */ null, /* remoteTransition= */ null, displayChange); Loading Loading @@ -366,7 +366,7 @@ class DeferredDisplayUpdater { /** * Continues the screen unblocking flow, could be called either on a binder thread as * a result of surface transaction completed listener or from {@link WindowManagerService#mH} * a result of surface transaction presented listener or from {@link WindowManagerService#mH} * handler in case of timeout */ private void continueScreenUnblocking() { Loading
services/core/java/com/android/server/wm/Transition.java +57 −12 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import static android.app.WindowConfiguration.ROTATION_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.hardware.SyncFence.SIGNAL_TIME_PENDING; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; Loading Loading @@ -95,6 +96,7 @@ import android.content.pm.ActivityInfo; import android.graphics.Point; import android.graphics.Rect; import android.hardware.HardwareBuffer; import android.hardware.SyncFence; import android.os.Binder; import android.os.Bundle; import android.os.Debug; Loading Loading @@ -134,6 +136,7 @@ import com.android.window.flags.Flags; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.ref.WeakReference; import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.Objects; Loading Loading @@ -265,8 +268,10 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { */ private ArrayList<Task> mTransientHideTasks; private static final Duration TRANSACTION_PRESENTED_TIMEOUT = Duration.ofSeconds(1); @VisibleForTesting ArrayList<Runnable> mTransactionCompletedListeners = null; ArrayList<Runnable> mTransactionPresentedListeners = null; private ArrayList<Runnable> mTransitionEndedListeners = null; Loading Loading @@ -1911,13 +1916,17 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { commitVisibleActivities(transaction); commitVisibleWallpapers(transaction); if (mTransactionCompletedListeners != null) { for (int i = 0; i < mTransactionCompletedListeners.size(); i++) { final Runnable listener = mTransactionCompletedListeners.get(i); transaction.addTransactionCompletedListener(Runnable::run, (stats) -> listener.run()); if (mTransactionPresentedListeners != null) { final List<Runnable> transactionPresentedListeners = new ArrayList<>(mTransactionPresentedListeners); addTransactionPresentedCallback(transaction, () -> { for (int i = 0; i < transactionPresentedListeners.size(); i++) { transactionPresentedListeners.get(i).run(); } mTransactionCompletedListeners = null; }); mTransactionPresentedListeners = null; } // Fall-back to the default display if there isn't one participating. Loading Loading @@ -2266,11 +2275,11 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { * Adds a listener that will be executed after the start transaction of this transition * is presented on the screen, the listener will be executed on a binder thread */ void addTransactionCompletedListener(Runnable listener) { if (mTransactionCompletedListeners == null) { mTransactionCompletedListeners = new ArrayList<>(); void addTransactionPresentedListener(Runnable listener) { if (mTransactionPresentedListeners == null) { mTransactionPresentedListeners = new ArrayList<>(); } mTransactionCompletedListeners.add(listener); mTransactionPresentedListeners.add(listener); } /** Loading @@ -2287,6 +2296,42 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { mTransitionEndedListeners.add(listener); } private void addTransactionPresentedCallback(SurfaceControl.Transaction transaction, Runnable onPresented) { transaction.addTransactionCompletedListener(Runnable::run, (stats) -> { if (com.android.window.flags.Flags.waitForPresentFenceOnDisplaySwitch()) { final SyncFence fence = stats.getPresentFence(); waitForPresentFence(fence, onPresented); } else { onPresented.run(); } }); } private void waitForPresentFence(SyncFence fence, Runnable onPresented) { try { if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) { Trace.beginSection("Awaiting for the present fence"); } fence.await(TRANSACTION_PRESENTED_TIMEOUT); } finally { if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) { Trace.endSection(); } onPresented.run(); final long signalTime = fence.getSignalTime(); if (signalTime == SIGNAL_TIME_PENDING) { Slog.e(TAG, "Timeout occurred when waiting for the transaction " + "to be presented"); } fence.close(); } } /** * Checks if the transition contains order changes. * Loading
services/tests/wmtests/src/com/android/server/wm/DisplayContentDeferredUpdateTests.java +6 −6 Original line number Diff line number Diff line Loading @@ -231,7 +231,7 @@ public class DisplayContentDeferredUpdateTests extends WindowTestsBase { when(mDisplayContent.mTransitionController.inTransition()).thenReturn(false); final Transition transition = captureRequestedTransition().getValue(); makeTransitionTransactionCompleted(transition); makeTransitionTransactionPresented(transition); // Verify that screen is unblocked as start transaction of the transition // has been completed Loading Loading @@ -308,7 +308,7 @@ public class DisplayContentDeferredUpdateTests extends WindowTestsBase { // Mark start transactions as presented when(mDisplayContent.mTransitionController.inTransition()).thenReturn(false); captureRequestedTransition().getAllValues().forEach( this::makeTransitionTransactionCompleted); this::makeTransitionTransactionPresented); // Verify that the default screen unblocker is sent only after start transaction // of the Shell transition is presented Loading Loading @@ -355,10 +355,10 @@ public class DisplayContentDeferredUpdateTests extends WindowTestsBase { return callbackCaptor; } private void makeTransitionTransactionCompleted(Transition transition) { if (transition.mTransactionCompletedListeners != null) { for (int i = 0; i < transition.mTransactionCompletedListeners.size(); i++) { final Runnable listener = transition.mTransactionCompletedListeners.get(i); private void makeTransitionTransactionPresented(Transition transition) { if (transition.mTransactionPresentedListeners != null) { for (int i = 0; i < transition.mTransactionPresentedListeners.size(); i++) { final Runnable listener = transition.mTransactionPresentedListeners.get(i); listener.run(); } } Loading