diff options
| author | 2022-11-02 09:31:31 +0000 | |
|---|---|---|
| committer | 2022-11-02 09:31:31 +0000 | |
| commit | 71bf4aaf9e469f922b365ec05da59e2d2b39119b (patch) | |
| tree | 55359b395aa4c0078977c2870291a389a3e29a7b /libs | |
| parent | 269cef1fd5dbf97a4b1fb6fa831dd4e66f78172a (diff) | |
| parent | c3ebae4ca884a1b56930b322d171d06b675fbe4d (diff) | |
Merge "Fix pip update transaction out of order" into tm-qpr-dev
Diffstat (limited to 'libs')
4 files changed, 65 insertions, 5 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMenuController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMenuController.java index 16f1d1c2944c..f81c9f80830a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMenuController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMenuController.java @@ -23,6 +23,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; +import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager.RunningTaskInfo; import android.app.RemoteAction; @@ -70,6 +71,11 @@ public interface PipMenuController { void setAppActions(List<RemoteAction> appActions, RemoteAction closeAction); /** + * Wait until the next frame to run the given Runnable. + */ + void runWithNextFrame(@NonNull Runnable runnable); + + /** * Resize the PiP menu with the given bounds. The PiP SurfaceControl is given if there is a * need to synchronize the movements on the same frame as PiP. */ diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java index f170e774739f..2d7c5ce6feb5 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java @@ -179,8 +179,10 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, // This is necessary in case there was a resize animation ongoing when exit PIP // started, in which case the first resize will be skipped to let the exit // operation handle the final resize out of PIP mode. See b/185306679. - finishResize(tx, destinationBounds, direction, animationType); - sendOnPipTransitionFinished(direction); + finishResizeDelayedIfNeeded(() -> { + finishResize(tx, destinationBounds, direction, animationType); + sendOnPipTransitionFinished(direction); + }); } } @@ -196,6 +198,34 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, } }; + /** + * Finishes resizing the PiP, delaying the operation if it has to be synced with the PiP menu. + * + * This is done to avoid a race condition between the last transaction applied in + * onAnimationUpdate and the finishResize in onAnimationEnd. finishResize creates a + * WindowContainerTransaction, which is to be applied by WmCore later. It may happen that it + * gets applied before the transaction created by the last onAnimationUpdate. As a result of + * this, the PiP surface may get scaled after the new bounds are applied by WmCore, which + * makes the PiP surface have unexpected bounds. To avoid this, we delay the finishResize + * operation until the next frame. This aligns the last onAnimationUpdate transaction with the + * WCT application. + * + * The race only happens when the PiP surface transaction has to be synced with the PiP menu + * due to the necessity for a delay when syncing the PiP surface, the PiP menu surface and + * the PiP menu contents. + */ + private void finishResizeDelayedIfNeeded(Runnable finishResizeRunnable) { + if (!shouldSyncPipTransactionWithMenu()) { + finishResizeRunnable.run(); + return; + } + mPipMenuController.runWithNextFrame(finishResizeRunnable); + } + + private boolean shouldSyncPipTransactionWithMenu() { + return mPipMenuController.isMenuVisible(); + } + @VisibleForTesting final PipTransitionController.PipTransitionCallback mPipTransitionCallback = new PipTransitionController.PipTransitionCallback() { @@ -221,7 +251,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, @Override public boolean handlePipTransaction(SurfaceControl leash, SurfaceControl.Transaction tx, Rect destinationBounds) { - if (mPipMenuController.isMenuVisible()) { + if (shouldSyncPipTransactionWithMenu()) { mPipMenuController.movePipMenu(leash, tx, destinationBounds); return true; } @@ -1223,7 +1253,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, mSurfaceTransactionHelper .crop(tx, mLeash, toBounds) .round(tx, mLeash, mPipTransitionState.isInPip()); - if (mPipMenuController.isMenuVisible()) { + if (shouldSyncPipTransactionWithMenu()) { mPipMenuController.resizePipMenu(mLeash, tx, toBounds); } else { tx.apply(); @@ -1265,7 +1295,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, mSurfaceTransactionHelper .scale(tx, mLeash, startBounds, toBounds, degrees) .round(tx, mLeash, startBounds, toBounds); - if (mPipMenuController.isMenuVisible()) { + if (shouldSyncPipTransactionWithMenu()) { mPipMenuController.movePipMenu(mLeash, tx, toBounds); } else { tx.apply(); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java index 281ea530e9e1..27902b2231ba 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java @@ -305,6 +305,18 @@ public class PhonePipMenuController implements PipMenuController { showResizeHandle); } + @Override + public void runWithNextFrame(Runnable runnable) { + if (mPipMenuView == null || mPipMenuView.getViewRootImpl() == null) { + runnable.run(); + } + + mPipMenuView.getViewRootImpl().registerRtFrameCallback(frame -> { + mMainHandler.post(runnable); + }); + mPipMenuView.invalidate(); + } + /** * Move the PiP menu, which does a translation and possibly a scale transformation. */ diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java index 4ce45e142c64..7d4b43be4f73 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java @@ -466,6 +466,18 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis } @Override + public void runWithNextFrame(Runnable runnable) { + if (mPipMenuView == null || mPipMenuView.getViewRootImpl() == null) { + runnable.run(); + } + + mPipMenuView.getViewRootImpl().registerRtFrameCallback(frame -> { + mMainHandler.post(runnable); + }); + mPipMenuView.invalidate(); + } + + @Override public void movePipMenu(SurfaceControl pipLeash, SurfaceControl.Transaction transaction, Rect pipDestBounds) { if (DEBUG) { |