Loading services/core/java/com/android/server/wm/Task.java +1 −1 Original line number Diff line number Diff line Loading @@ -6880,7 +6880,7 @@ class Task extends TaskFragment { private void assignLayer(@NonNull SurfaceControl.Transaction t, int layer) { t.setLayer(mContainerSurface, layer); t.setVisibility(mContainerSurface, mOwnerTaskFragment.isVisible()); t.setVisibility(mContainerSurface, mOwnerTaskFragment.isVisible() || mIsBoosted); for (int i = 0; i < mPendingClientTransactions.size(); i++) { t.merge(mPendingClientTransactions.get(i)); } Loading services/core/java/com/android/server/wm/Transition.java +29 −0 Original line number Diff line number Diff line Loading @@ -236,6 +236,8 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { @VisibleForTesting ArrayList<Runnable> mTransactionCompletedListeners = null; private ArrayList<Runnable> mTransitionEndedListeners = null; /** Custom activity-level animation options and callbacks. */ private TransitionInfo.AnimationOptions mOverrideOptions; private IRemoteCallback mClientAnimationStartCallback = null; Loading Loading @@ -1473,6 +1475,18 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { mController.mSnapshotController.onTransitionFinish(mType, mTargets); // Resume snapshot persist thread after snapshot controller analysis this transition. mController.updateAnimatingState(); invokeTransitionEndedListeners(); } private void invokeTransitionEndedListeners() { if (mTransitionEndedListeners == null) { return; } for (int i = 0; i < mTransitionEndedListeners.size(); i++) { mTransitionEndedListeners.get(i).run(); } mTransitionEndedListeners = null; } private void commitConfigAtEndActivities() { Loading Loading @@ -1584,6 +1598,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { // Syncengine abort will call through to onTransactionReady() mSyncEngine.abort(mSyncId); mController.dispatchLegacyAppTransitionCancelled(); invokeTransitionEndedListeners(); } /** Immediately moves this to playing even if it isn't started yet. */ Loading Loading @@ -1901,6 +1916,20 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { mTransactionCompletedListeners.add(listener); } /** * Adds a listener that will be executed after the transition is finished or aborted. */ void addTransitionEndedListener(Runnable listener) { if (mState != STATE_COLLECTING && mState != STATE_STARTED) { throw new IllegalStateException( "Can't register listeners if the transition isn't collecting. state=" + mState); } if (mTransitionEndedListeners == null) { mTransitionEndedListeners = new ArrayList<>(); } mTransitionEndedListeners.add(listener); } /** * Checks if the transition contains order changes. * Loading services/core/java/com/android/server/wm/WindowOrganizerController.java +20 −4 Original line number Diff line number Diff line Loading @@ -1613,6 +1613,10 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub } case OP_TYPE_SET_DECOR_SURFACE_BOOSTED: { if (Flags.activityEmbeddingInteractiveDividerFlag()) { final Task task = taskFragment.getTask(); if (task == null) { break; } final SurfaceControl.Transaction clientTransaction = operation.getSurfaceTransaction(); if (clientTransaction != null) { Loading @@ -1621,11 +1625,23 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub // any invalid operations. clientTransaction.sanitize(caller.mPid, caller.mUid); } taskFragment.getTask().setDecorSurfaceBoosted( if (transition != null) { // The decor surface boost/unboost must happen after the transition is // completed. Otherwise, the decor surface could be moved before Shell // completes the transition, causing flicker. transition.addTransitionEndedListener(() -> task.setDecorSurfaceBoosted( taskFragment, operation.getBooleanValue() /* isBoosted */, clientTransaction)); } else { task.setDecorSurfaceBoosted( taskFragment, operation.getBooleanValue() /* isBoosted */, clientTransaction); } } break; } case OP_TYPE_SET_PINNED: { Loading services/tests/wmtests/src/com/android/server/wm/TransitionTests.java +27 −0 Original line number Diff line number Diff line Loading @@ -1445,6 +1445,33 @@ public class TransitionTests extends WindowTestsBase { assertTrue(activity1.mLaunchTaskBehind); } @Test public void testTransitionEndedListeners() { final TransitionController controller = new TestTransitionController(mAtm); controller.setSyncEngine(mWm.mSyncEngine); final ITransitionPlayer player = new ITransitionPlayer.Default(); controller.registerTransitionPlayer(player, null /* playerProc */); final Runnable transitionEndedListener = mock(Runnable.class); final Transition transition1 = controller.createTransition(TRANSIT_OPEN); transition1.addTransitionEndedListener(transitionEndedListener); // Using abort to force-finish the sync (since we can't wait for drawing in unit test). // We didn't call abort on the transition itself, so it will still run onTransactionReady // normally. mWm.mSyncEngine.abort(transition1.getSyncId()); transition1.finishTransition(); verify(transitionEndedListener).run(); clearInvocations(transitionEndedListener); final Transition transition2 = controller.createTransition(TRANSIT_OPEN); transition2.addTransitionEndedListener(transitionEndedListener); transition2.abort(); verify(transitionEndedListener).run(); } @Test public void testTransientLaunch() { spyOn(mWm.mSnapshotController.mTaskSnapshotController); Loading Loading
services/core/java/com/android/server/wm/Task.java +1 −1 Original line number Diff line number Diff line Loading @@ -6880,7 +6880,7 @@ class Task extends TaskFragment { private void assignLayer(@NonNull SurfaceControl.Transaction t, int layer) { t.setLayer(mContainerSurface, layer); t.setVisibility(mContainerSurface, mOwnerTaskFragment.isVisible()); t.setVisibility(mContainerSurface, mOwnerTaskFragment.isVisible() || mIsBoosted); for (int i = 0; i < mPendingClientTransactions.size(); i++) { t.merge(mPendingClientTransactions.get(i)); } Loading
services/core/java/com/android/server/wm/Transition.java +29 −0 Original line number Diff line number Diff line Loading @@ -236,6 +236,8 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { @VisibleForTesting ArrayList<Runnable> mTransactionCompletedListeners = null; private ArrayList<Runnable> mTransitionEndedListeners = null; /** Custom activity-level animation options and callbacks. */ private TransitionInfo.AnimationOptions mOverrideOptions; private IRemoteCallback mClientAnimationStartCallback = null; Loading Loading @@ -1473,6 +1475,18 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { mController.mSnapshotController.onTransitionFinish(mType, mTargets); // Resume snapshot persist thread after snapshot controller analysis this transition. mController.updateAnimatingState(); invokeTransitionEndedListeners(); } private void invokeTransitionEndedListeners() { if (mTransitionEndedListeners == null) { return; } for (int i = 0; i < mTransitionEndedListeners.size(); i++) { mTransitionEndedListeners.get(i).run(); } mTransitionEndedListeners = null; } private void commitConfigAtEndActivities() { Loading Loading @@ -1584,6 +1598,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { // Syncengine abort will call through to onTransactionReady() mSyncEngine.abort(mSyncId); mController.dispatchLegacyAppTransitionCancelled(); invokeTransitionEndedListeners(); } /** Immediately moves this to playing even if it isn't started yet. */ Loading Loading @@ -1901,6 +1916,20 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { mTransactionCompletedListeners.add(listener); } /** * Adds a listener that will be executed after the transition is finished or aborted. */ void addTransitionEndedListener(Runnable listener) { if (mState != STATE_COLLECTING && mState != STATE_STARTED) { throw new IllegalStateException( "Can't register listeners if the transition isn't collecting. state=" + mState); } if (mTransitionEndedListeners == null) { mTransitionEndedListeners = new ArrayList<>(); } mTransitionEndedListeners.add(listener); } /** * Checks if the transition contains order changes. * Loading
services/core/java/com/android/server/wm/WindowOrganizerController.java +20 −4 Original line number Diff line number Diff line Loading @@ -1613,6 +1613,10 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub } case OP_TYPE_SET_DECOR_SURFACE_BOOSTED: { if (Flags.activityEmbeddingInteractiveDividerFlag()) { final Task task = taskFragment.getTask(); if (task == null) { break; } final SurfaceControl.Transaction clientTransaction = operation.getSurfaceTransaction(); if (clientTransaction != null) { Loading @@ -1621,11 +1625,23 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub // any invalid operations. clientTransaction.sanitize(caller.mPid, caller.mUid); } taskFragment.getTask().setDecorSurfaceBoosted( if (transition != null) { // The decor surface boost/unboost must happen after the transition is // completed. Otherwise, the decor surface could be moved before Shell // completes the transition, causing flicker. transition.addTransitionEndedListener(() -> task.setDecorSurfaceBoosted( taskFragment, operation.getBooleanValue() /* isBoosted */, clientTransaction)); } else { task.setDecorSurfaceBoosted( taskFragment, operation.getBooleanValue() /* isBoosted */, clientTransaction); } } break; } case OP_TYPE_SET_PINNED: { Loading
services/tests/wmtests/src/com/android/server/wm/TransitionTests.java +27 −0 Original line number Diff line number Diff line Loading @@ -1445,6 +1445,33 @@ public class TransitionTests extends WindowTestsBase { assertTrue(activity1.mLaunchTaskBehind); } @Test public void testTransitionEndedListeners() { final TransitionController controller = new TestTransitionController(mAtm); controller.setSyncEngine(mWm.mSyncEngine); final ITransitionPlayer player = new ITransitionPlayer.Default(); controller.registerTransitionPlayer(player, null /* playerProc */); final Runnable transitionEndedListener = mock(Runnable.class); final Transition transition1 = controller.createTransition(TRANSIT_OPEN); transition1.addTransitionEndedListener(transitionEndedListener); // Using abort to force-finish the sync (since we can't wait for drawing in unit test). // We didn't call abort on the transition itself, so it will still run onTransactionReady // normally. mWm.mSyncEngine.abort(transition1.getSyncId()); transition1.finishTransition(); verify(transitionEndedListener).run(); clearInvocations(transitionEndedListener); final Transition transition2 = controller.createTransition(TRANSIT_OPEN); transition2.addTransitionEndedListener(transitionEndedListener); transition2.abort(); verify(transitionEndedListener).run(); } @Test public void testTransientLaunch() { spyOn(mWm.mSnapshotController.mTaskSnapshotController); Loading