Merge "Fix pip update transaction out of order" into tm-qpr-dev

This commit is contained in:
Galia Peycheva
2022-11-29 17:04:55 +00:00
committed by Android (Google) Code Review

View File

@@ -63,6 +63,7 @@ import android.graphics.Rect;
import android.os.RemoteException;
import android.os.SystemClock;
import android.util.Log;
import android.view.Choreographer;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceControl;
@@ -179,8 +180,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 +199,39 @@ 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
* onPipAnimationUpdate and the finishResize in onPipAnimationEnd. The transaction in
* onPipAnimationUpdate is applied directly from WmShell, while onPipAnimationEnd creates a
* WindowContainerTransaction in finishResize, which is to be applied by WmCore later. Normally,
* the WCT should be the last transaction to finish the animation. However, it may happen that
* it gets applied *before* the transaction created by the last onPipAnimationUpdate. This
* happens only 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 animation with the PiP menu surface
* animation and redrawing the PiP menu contents. As a result, the PiP surface gets 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.
*/
private void finishResizeDelayedIfNeeded(Runnable finishResizeRunnable) {
if (!shouldSyncPipTransactionWithMenu()) {
finishResizeRunnable.run();
return;
}
// Delay the finishResize to the next frame
Choreographer.getInstance().postCallback(Choreographer.CALLBACK_COMMIT, () -> {
mMainExecutor.execute(finishResizeRunnable);
}, null);
}
private boolean shouldSyncPipTransactionWithMenu() {
return mPipMenuController.isMenuVisible();
}
@VisibleForTesting
final PipTransitionController.PipTransitionCallback mPipTransitionCallback =
new PipTransitionController.PipTransitionCallback() {
@@ -221,7 +257,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 +1259,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 +1301,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();