Merge "Use SurfaceSyncGroup to sync the pip move animation" into udc-dev

This commit is contained in:
Galia Peycheva
2023-03-02 13:33:52 +00:00
committed by Android (Google) Code Review

View File

@@ -25,16 +25,14 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.graphics.Insets; import android.graphics.Insets;
import android.graphics.Matrix;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Handler; import android.os.Handler;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.SurfaceControl; import android.view.SurfaceControl;
import android.view.SyncRtSurfaceTransactionApplier;
import android.view.View; import android.view.View;
import android.view.ViewRootImpl; import android.view.ViewRootImpl;
import android.view.WindowManagerGlobal; import android.view.WindowManagerGlobal;
import android.window.SurfaceSyncGroup;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@@ -71,12 +69,6 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis
// exiting the move menu instead of showing the regular button menu. // exiting the move menu instead of showing the regular button menu.
private boolean mCloseAfterExitMoveMenu; private boolean mCloseAfterExitMoveMenu;
private SyncRtSurfaceTransactionApplier mApplier;
private SyncRtSurfaceTransactionApplier mBackgroundApplier;
RectF mTmpSourceRectF = new RectF();
RectF mTmpDestinationRectF = new RectF();
Matrix mMoveTransform = new Matrix();
public TvPipMenuController(Context context, TvPipBoundsState tvPipBoundsState, public TvPipMenuController(Context context, TvPipBoundsState tvPipBoundsState,
SystemWindows systemWindows, Handler mainHandler) { SystemWindows systemWindows, Handler mainHandler) {
mContext = context; mContext = context;
@@ -324,44 +316,36 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis
*/ */
@Override @Override
public void resizePipMenu(@Nullable SurfaceControl pipLeash, public void resizePipMenu(@Nullable SurfaceControl pipLeash,
@Nullable SurfaceControl.Transaction t, @Nullable SurfaceControl.Transaction pipTx,
Rect destinationBounds) { Rect pipBounds) {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: resizePipMenu: %s", TAG, destinationBounds.toShortString()); "%s: resizePipMenu: %s", TAG, pipBounds.toShortString());
if (destinationBounds.isEmpty()) { if (pipBounds.isEmpty()) {
return; return;
} }
if (!maybeCreateSyncApplier()) { if (!isMenuReadyToMove()) {
return; return;
} }
final Rect menuBounds = calculateMenuSurfaceBounds(destinationBounds);
final SurfaceControl frontSurface = getSurfaceControl(mPipMenuView); final SurfaceControl frontSurface = getSurfaceControl(mPipMenuView);
final SyncRtSurfaceTransactionApplier.SurfaceParams frontParams =
new SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(frontSurface)
.withWindowCrop(menuBounds)
.build();
final SurfaceControl backSurface = getSurfaceControl(mPipBackgroundView); final SurfaceControl backSurface = getSurfaceControl(mPipBackgroundView);
final SyncRtSurfaceTransactionApplier.SurfaceParams backParams = final Rect menuBounds = calculateMenuSurfaceBounds(pipBounds);
new SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(backSurface) if (pipTx == null) {
.withWindowCrop(menuBounds) pipTx = new SurfaceControl.Transaction();
.build();
// TODO(b/226580399): switch to using SurfaceSyncer (see b/200284684) to synchronize the
// animations of the pip surface with the content of the front and back menu surfaces
mBackgroundApplier.scheduleApply(backParams);
if (pipLeash != null && t != null) {
final SyncRtSurfaceTransactionApplier.SurfaceParams
pipParams = new SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(pipLeash)
.withMergeTransaction(t)
.build();
mApplier.scheduleApply(frontParams, pipParams);
} else {
mApplier.scheduleApply(frontParams);
} }
pipTx.setWindowCrop(frontSurface, menuBounds.width(), menuBounds.height());
pipTx.setWindowCrop(backSurface, menuBounds.width(), menuBounds.height());
// Synchronize drawing the content in the front and back surfaces together with the pip
// transaction and the window crop for the front and back surfaces
final SurfaceSyncGroup syncGroup = new SurfaceSyncGroup("TvPip");
syncGroup.add(mPipMenuView.getRootSurfaceControl(), null);
syncGroup.add(mPipBackgroundView.getRootSurfaceControl(), null);
updateMenuBounds(pipBounds);
syncGroup.addTransaction(pipTx);
syncGroup.markSyncReady();
} }
private SurfaceControl getSurfaceControl(View v) { private SurfaceControl getSurfaceControl(View v) {
@@ -369,102 +353,66 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis
} }
@Override @Override
public void movePipMenu(SurfaceControl pipLeash, SurfaceControl.Transaction transaction, public void movePipMenu(SurfaceControl pipLeash, SurfaceControl.Transaction pipTx,
Rect pipDestBounds) { Rect pipBounds) {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: movePipMenu: %s", TAG, pipDestBounds.toShortString()); "%s: movePipMenu: %s", TAG, pipBounds.toShortString());
if (pipDestBounds.isEmpty()) { if (pipBounds.isEmpty()) {
if (transaction == null) { if (pipTx == null) {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: no transaction given", TAG); "%s: no transaction given", TAG);
} }
return; return;
} }
if (!maybeCreateSyncApplier()) { if (!isMenuReadyToMove()) {
return; return;
} }
final Rect menuDestBounds = calculateMenuSurfaceBounds(pipDestBounds);
final Rect tmpSourceBounds = new Rect();
// If there is no pip leash supplied, that means the PiP leash is already finalized
// resizing and the PiP menu is also resized. We then want to do a scale from the current
// new menu bounds.
if (pipLeash != null && transaction != null) {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: tmpSourceBounds based on mPipMenuView.getBoundsOnScreen()", TAG);
mPipMenuView.getBoundsOnScreen(tmpSourceBounds);
} else {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: tmpSourceBounds based on menu width and height", TAG);
tmpSourceBounds.set(0, 0, menuDestBounds.width(), menuDestBounds.height());
}
mTmpSourceRectF.set(tmpSourceBounds);
mTmpDestinationRectF.set(menuDestBounds);
mMoveTransform.setTranslate(mTmpDestinationRectF.left, mTmpDestinationRectF.top);
final SurfaceControl frontSurface = getSurfaceControl(mPipMenuView); final SurfaceControl frontSurface = getSurfaceControl(mPipMenuView);
final SyncRtSurfaceTransactionApplier.SurfaceParams frontParams =
new SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(frontSurface)
.withMatrix(mMoveTransform)
.build();
final SurfaceControl backSurface = getSurfaceControl(mPipBackgroundView); final SurfaceControl backSurface = getSurfaceControl(mPipBackgroundView);
final SyncRtSurfaceTransactionApplier.SurfaceParams backParams = final Rect menuDestBounds = calculateMenuSurfaceBounds(pipBounds);
new SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(backSurface) if (pipTx == null) {
.withMatrix(mMoveTransform) pipTx = new SurfaceControl.Transaction();
.build();
// TODO(b/226580399): switch to using SurfaceSyncer (see b/200284684) to synchronize the
// animations of the pip surface with the content of the front and back menu surfaces
mBackgroundApplier.scheduleApply(backParams);
if (pipLeash != null && transaction != null) {
final SyncRtSurfaceTransactionApplier.SurfaceParams pipParams =
new SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(pipLeash)
.withMergeTransaction(transaction)
.build();
mApplier.scheduleApply(frontParams, pipParams);
} else {
mApplier.scheduleApply(frontParams);
} }
pipTx.setPosition(frontSurface, menuDestBounds.left, menuDestBounds.top);
pipTx.setPosition(backSurface, menuDestBounds.left, menuDestBounds.top);
updateMenuBounds(pipDestBounds); // Synchronize drawing the content in the front and back surfaces together with the pip
// transaction and the position change for the front and back surfaces
final SurfaceSyncGroup syncGroup = new SurfaceSyncGroup("TvPip");
syncGroup.add(mPipMenuView.getRootSurfaceControl(), null);
syncGroup.add(mPipBackgroundView.getRootSurfaceControl(), null);
updateMenuBounds(pipBounds);
syncGroup.addTransaction(pipTx);
syncGroup.markSyncReady();
} }
private boolean maybeCreateSyncApplier() { private boolean isMenuReadyToMove() {
if (mPipMenuView == null || mPipMenuView.getViewRootImpl() == null) { final boolean ready = mPipMenuView != null && mPipMenuView.getViewRootImpl() != null
&& mPipBackgroundView != null && mPipBackgroundView.getViewRootImpl() != null;
if (!ready) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, ProtoLog.v(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: Not going to move PiP, either menu or its parent is not created.", TAG); "%s: Not going to move PiP, either menu or its parent is not created.", TAG);
return false;
} }
return ready;
if (mApplier == null) {
mApplier = new SyncRtSurfaceTransactionApplier(mPipMenuView);
}
if (mBackgroundApplier == null) {
mBackgroundApplier = new SyncRtSurfaceTransactionApplier(mPipBackgroundView);
}
return true;
} }
private void detachPipMenu() { private void detachPipMenu() {
if (mPipMenuView != null) { if (mPipMenuView != null) {
mApplier = null;
mSystemWindows.removeView(mPipMenuView); mSystemWindows.removeView(mPipMenuView);
mPipMenuView = null; mPipMenuView = null;
} }
if (mPipBackgroundView != null) { if (mPipBackgroundView != null) {
mBackgroundApplier = null;
mSystemWindows.removeView(mPipBackgroundView); mSystemWindows.removeView(mPipBackgroundView);
mPipBackgroundView = null; mPipBackgroundView = null;
} }
} }
@Override @Override
public void updateMenuBounds(Rect destinationBounds) { public void updateMenuBounds(Rect pipBounds) {
final Rect menuBounds = calculateMenuSurfaceBounds(destinationBounds); final Rect menuBounds = calculateMenuSurfaceBounds(pipBounds);
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: updateMenuBounds: %s", TAG, menuBounds.toShortString()); "%s: updateMenuBounds: %s", TAG, menuBounds.toShortString());
mSystemWindows.updateViewLayout(mPipBackgroundView, mSystemWindows.updateViewLayout(mPipBackgroundView,
@@ -473,9 +421,8 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis
mSystemWindows.updateViewLayout(mPipMenuView, mSystemWindows.updateViewLayout(mPipMenuView,
getPipMenuLayoutParams(mContext, MENU_WINDOW_TITLE, menuBounds.width(), getPipMenuLayoutParams(mContext, MENU_WINDOW_TITLE, menuBounds.width(),
menuBounds.height())); menuBounds.height()));
if (mPipMenuView != null) { if (mPipMenuView != null) {
mPipMenuView.updateBounds(destinationBounds); mPipMenuView.updateBounds(pipBounds);
} }
} }