Merge "Implement split resize shell transition" into tm-qpr-dev am: 0de589346f

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20111337

Change-Id: Id456af47541181fb36cc59bf23b3997da914dc39
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Tony Huang
2022-12-07 04:08:48 +00:00
committed by Automerger Merge Worker
5 changed files with 160 additions and 30 deletions

View File

@@ -51,8 +51,6 @@ import com.android.wm.shell.R;
import com.android.wm.shell.common.ScreenshotUtils; import com.android.wm.shell.common.ScreenshotUtils;
import com.android.wm.shell.common.SurfaceUtils; import com.android.wm.shell.common.SurfaceUtils;
import java.util.function.Consumer;
/** /**
* Handles split decor like showing resizing hint for a specific split. * Handles split decor like showing resizing hint for a specific split.
*/ */
@@ -72,17 +70,18 @@ public class SplitDecorManager extends WindowlessWindowManager {
private SurfaceControl mIconLeash; private SurfaceControl mIconLeash;
private SurfaceControl mBackgroundLeash; private SurfaceControl mBackgroundLeash;
private SurfaceControl mGapBackgroundLeash; private SurfaceControl mGapBackgroundLeash;
private SurfaceControl mScreenshot;
private boolean mShown; private boolean mShown;
private boolean mIsResizing; private boolean mIsResizing;
private final Rect mBounds = new Rect(); private final Rect mBounds = new Rect();
private final Rect mResizingBounds = new Rect();
private final Rect mTempRect = new Rect(); private final Rect mTempRect = new Rect();
private ValueAnimator mFadeAnimator; private ValueAnimator mFadeAnimator;
private int mIconSize; private int mIconSize;
private int mOffsetX; private int mOffsetX;
private int mOffsetY; private int mOffsetY;
private int mRunningAnimationCount = 0;
public SplitDecorManager(Configuration configuration, IconProvider iconProvider, public SplitDecorManager(Configuration configuration, IconProvider iconProvider,
SurfaceSession surfaceSession) { SurfaceSession surfaceSession) {
@@ -173,7 +172,6 @@ public class SplitDecorManager extends WindowlessWindowManager {
mIsResizing = true; mIsResizing = true;
mBounds.set(newBounds); mBounds.set(newBounds);
} }
mResizingBounds.set(newBounds);
mOffsetX = offsetX; mOffsetX = offsetX;
mOffsetY = offsetY; mOffsetY = offsetY;
@@ -227,33 +225,41 @@ public class SplitDecorManager extends WindowlessWindowManager {
t.setVisibility(mBackgroundLeash, show); t.setVisibility(mBackgroundLeash, show);
t.setVisibility(mIconLeash, show); t.setVisibility(mIconLeash, show);
} else { } else {
startFadeAnimation(show, null /* finishedConsumer */); startFadeAnimation(show, false, null);
} }
mShown = show; mShown = show;
} }
} }
/** Stops showing resizing hint. */ /** Stops showing resizing hint. */
public void onResized(SurfaceControl.Transaction t) { public void onResized(SurfaceControl.Transaction t, Runnable animFinishedCallback) {
if (!mShown && mIsResizing) { if (mScreenshot != null) {
mTempRect.set(mResizingBounds); t.setPosition(mScreenshot, mOffsetX, mOffsetY);
mTempRect.offsetTo(-mOffsetX, -mOffsetY);
final SurfaceControl screenshot = ScreenshotUtils.takeScreenshot(t,
mHostLeash, mTempRect, Integer.MAX_VALUE - 1);
final SurfaceControl.Transaction animT = new SurfaceControl.Transaction(); final SurfaceControl.Transaction animT = new SurfaceControl.Transaction();
final ValueAnimator va = ValueAnimator.ofFloat(1, 0); final ValueAnimator va = ValueAnimator.ofFloat(1, 0);
va.addUpdateListener(valueAnimator -> { va.addUpdateListener(valueAnimator -> {
final float progress = (float) valueAnimator.getAnimatedValue(); final float progress = (float) valueAnimator.getAnimatedValue();
animT.setAlpha(screenshot, progress); animT.setAlpha(mScreenshot, progress);
animT.apply(); animT.apply();
}); });
va.addListener(new AnimatorListenerAdapter() { va.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
mRunningAnimationCount++;
}
@Override @Override
public void onAnimationEnd(@androidx.annotation.NonNull Animator animation) { public void onAnimationEnd(@androidx.annotation.NonNull Animator animation) {
animT.remove(screenshot); mRunningAnimationCount--;
animT.remove(mScreenshot);
animT.apply(); animT.apply();
animT.close(); animT.close();
mScreenshot = null;
if (mRunningAnimationCount == 0 && animFinishedCallback != null) {
animFinishedCallback.run();
}
} }
}); });
va.start(); va.start();
@@ -285,10 +291,34 @@ public class SplitDecorManager extends WindowlessWindowManager {
mFadeAnimator.cancel(); mFadeAnimator.cancel();
} }
if (mShown) { if (mShown) {
fadeOutDecor(null /* finishedCallback */); fadeOutDecor(animFinishedCallback);
} else { } else {
// Decor surface is hidden so release it directly. // Decor surface is hidden so release it directly.
releaseDecor(t); releaseDecor(t);
if (mRunningAnimationCount == 0 && animFinishedCallback != null) {
animFinishedCallback.run();
}
}
}
/** Screenshot host leash and attach on it if meet some conditions */
public void screenshotIfNeeded(SurfaceControl.Transaction t) {
if (!mShown && mIsResizing) {
mTempRect.set(mBounds);
mTempRect.offsetTo(0, 0);
mScreenshot = ScreenshotUtils.takeScreenshot(t, mHostLeash, mTempRect,
Integer.MAX_VALUE - 1);
}
}
/** Set screenshot and attach on host leash it if meet some conditions */
public void setScreenshotIfNeeded(SurfaceControl screenshot, SurfaceControl.Transaction t) {
if (screenshot == null || !screenshot.isValid()) return;
if (!mShown && mIsResizing) {
mScreenshot = screenshot;
t.reparent(screenshot, mHostLeash);
t.setLayer(screenshot, Integer.MAX_VALUE - 1);
} }
} }
@@ -296,18 +326,15 @@ public class SplitDecorManager extends WindowlessWindowManager {
* directly. */ * directly. */
public void fadeOutDecor(Runnable finishedCallback) { public void fadeOutDecor(Runnable finishedCallback) {
if (mShown) { if (mShown) {
startFadeAnimation(false /* show */, transaction -> { startFadeAnimation(false /* show */, true, finishedCallback);
releaseDecor(transaction);
if (finishedCallback != null) finishedCallback.run();
});
mShown = false; mShown = false;
} else { } else {
if (finishedCallback != null) finishedCallback.run(); if (finishedCallback != null) finishedCallback.run();
} }
} }
private void startFadeAnimation(boolean show, private void startFadeAnimation(boolean show, boolean releaseSurface,
Consumer<SurfaceControl.Transaction> finishedConsumer) { Runnable finishedCallback) {
final SurfaceControl.Transaction animT = new SurfaceControl.Transaction(); final SurfaceControl.Transaction animT = new SurfaceControl.Transaction();
mFadeAnimator = ValueAnimator.ofFloat(0f, 1f); mFadeAnimator = ValueAnimator.ofFloat(0f, 1f);
mFadeAnimator.setDuration(FADE_DURATION); mFadeAnimator.setDuration(FADE_DURATION);
@@ -324,6 +351,7 @@ public class SplitDecorManager extends WindowlessWindowManager {
mFadeAnimator.addListener(new AnimatorListenerAdapter() { mFadeAnimator.addListener(new AnimatorListenerAdapter() {
@Override @Override
public void onAnimationStart(@NonNull Animator animation) { public void onAnimationStart(@NonNull Animator animation) {
mRunningAnimationCount++;
if (show) { if (show) {
animT.show(mBackgroundLeash).show(mIconLeash); animT.show(mBackgroundLeash).show(mIconLeash);
} }
@@ -335,6 +363,7 @@ public class SplitDecorManager extends WindowlessWindowManager {
@Override @Override
public void onAnimationEnd(@NonNull Animator animation) { public void onAnimationEnd(@NonNull Animator animation) {
mRunningAnimationCount--;
if (!show) { if (!show) {
if (mBackgroundLeash != null) { if (mBackgroundLeash != null) {
animT.hide(mBackgroundLeash); animT.hide(mBackgroundLeash);
@@ -343,11 +372,15 @@ public class SplitDecorManager extends WindowlessWindowManager {
animT.hide(mIconLeash); animT.hide(mIconLeash);
} }
} }
if (finishedConsumer != null) { if (releaseSurface) {
finishedConsumer.accept(animT); releaseDecor(animT);
} }
animT.apply(); animT.apply();
animT.close(); animT.close();
if (mRunningAnimationCount == 0 && finishedCallback != null) {
finishedCallback.run();
}
} }
}); });
mFadeAnimator.start(); mFadeAnimator.start();

View File

@@ -47,6 +47,7 @@ import android.window.WindowContainerTransactionCallback;
import com.android.internal.protolog.common.ProtoLog; import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.common.split.SplitDecorManager;
import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.transition.OneShotRemoteHandler; import com.android.wm.shell.transition.OneShotRemoteHandler;
import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.transition.Transitions;
@@ -64,6 +65,7 @@ class SplitScreenTransitions {
DismissTransition mPendingDismiss = null; DismissTransition mPendingDismiss = null;
TransitSession mPendingEnter = null; TransitSession mPendingEnter = null;
TransitSession mPendingRecent = null; TransitSession mPendingRecent = null;
TransitSession mPendingResize = null;
private IBinder mAnimatingTransition = null; private IBinder mAnimatingTransition = null;
OneShotRemoteHandler mPendingRemoteHandler = null; OneShotRemoteHandler mPendingRemoteHandler = null;
@@ -177,6 +179,43 @@ class SplitScreenTransitions {
onFinish(null /* wct */, null /* wctCB */); onFinish(null /* wct */, null /* wctCB */);
} }
void applyResizeTransition(@NonNull IBinder transition, @NonNull TransitionInfo info,
@NonNull SurfaceControl.Transaction startTransaction,
@NonNull SurfaceControl.Transaction finishTransaction,
@NonNull Transitions.TransitionFinishCallback finishCallback,
@NonNull WindowContainerToken mainRoot, @NonNull WindowContainerToken sideRoot,
@NonNull SplitDecorManager mainDecor, @NonNull SplitDecorManager sideDecor) {
mFinishCallback = finishCallback;
mAnimatingTransition = transition;
mFinishTransaction = finishTransaction;
for (int i = info.getChanges().size() - 1; i >= 0; --i) {
final TransitionInfo.Change change = info.getChanges().get(i);
if (mainRoot.equals(change.getContainer()) || sideRoot.equals(change.getContainer())) {
final SurfaceControl leash = change.getLeash();
startTransaction.setPosition(leash, change.getEndAbsBounds().left,
change.getEndAbsBounds().top);
startTransaction.setWindowCrop(leash, change.getEndAbsBounds().width(),
change.getEndAbsBounds().height());
SplitDecorManager decor = mainRoot.equals(change.getContainer())
? mainDecor : sideDecor;
ValueAnimator va = new ValueAnimator();
mAnimations.add(va);
decor.setScreenshotIfNeeded(change.getSnapshot(), startTransaction);
decor.onResized(startTransaction, () -> {
mTransitions.getMainExecutor().execute(() -> {
mAnimations.remove(va);
onFinish(null /* wct */, null /* wctCB */);
});
});
}
}
startTransaction.apply();
onFinish(null /* wct */, null /* wctCB */);
}
boolean isPendingTransition(IBinder transition) { boolean isPendingTransition(IBinder transition) {
return getPendingTransition(transition) != null; return getPendingTransition(transition) != null;
} }
@@ -193,6 +232,10 @@ class SplitScreenTransitions {
return mPendingDismiss != null && mPendingDismiss.mTransition == transition; return mPendingDismiss != null && mPendingDismiss.mTransition == transition;
} }
boolean isPendingResize(IBinder transition) {
return mPendingResize != null && mPendingResize.mTransition == transition;
}
@Nullable @Nullable
private TransitSession getPendingTransition(IBinder transition) { private TransitSession getPendingTransition(IBinder transition) {
if (isPendingEnter(transition)) { if (isPendingEnter(transition)) {
@@ -201,11 +244,14 @@ class SplitScreenTransitions {
return mPendingRecent; return mPendingRecent;
} else if (isPendingDismiss(transition)) { } else if (isPendingDismiss(transition)) {
return mPendingDismiss; return mPendingDismiss;
} else if (isPendingResize(transition)) {
return mPendingResize;
} }
return null; return null;
} }
/** Starts a transition to enter split with a remote transition animator. */ /** Starts a transition to enter split with a remote transition animator. */
IBinder startEnterTransition( IBinder startEnterTransition(
@WindowManager.TransitionType int transitType, @WindowManager.TransitionType int transitType,
@@ -258,6 +304,21 @@ class SplitScreenTransitions {
exitReasonToString(reason), stageTypeToString(dismissTop)); exitReasonToString(reason), stageTypeToString(dismissTop));
} }
IBinder startResizeTransition(WindowContainerTransaction wct,
Transitions.TransitionHandler handler,
@Nullable TransitionFinishedCallback finishCallback) {
IBinder transition = mTransitions.startTransition(TRANSIT_CHANGE, wct, handler);
setResizeTransition(transition, finishCallback);
return transition;
}
void setResizeTransition(@NonNull IBinder transition,
@Nullable TransitionFinishedCallback finishCallback) {
mPendingResize = new TransitSession(transition, null /* consumedCb */, finishCallback);
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " splitTransition "
+ " deduced Resize split screen");
}
void setRecentTransition(@NonNull IBinder transition, void setRecentTransition(@NonNull IBinder transition,
@Nullable RemoteTransition remoteTransition, @Nullable RemoteTransition remoteTransition,
@Nullable TransitionFinishedCallback finishCallback) { @Nullable TransitionFinishedCallback finishCallback) {
@@ -324,6 +385,9 @@ class SplitScreenTransitions {
mPendingRecent.onConsumed(aborted); mPendingRecent.onConsumed(aborted);
mPendingRecent = null; mPendingRecent = null;
mPendingRemoteHandler = null; mPendingRemoteHandler = null;
} else if (isPendingResize(transition)) {
mPendingResize.onConsumed(aborted);
mPendingResize = null;
} }
} }
@@ -340,6 +404,9 @@ class SplitScreenTransitions {
} else if (isPendingDismiss(mAnimatingTransition)) { } else if (isPendingDismiss(mAnimatingTransition)) {
mPendingDismiss.onFinished(wct, mFinishTransaction); mPendingDismiss.onFinished(wct, mFinishTransaction);
mPendingDismiss = null; mPendingDismiss = null;
} else if (isPendingResize(mAnimatingTransition)) {
mPendingResize.onFinished(wct, mFinishTransaction);
mPendingResize = null;
} }
mPendingRemoteHandler = null; mPendingRemoteHandler = null;

View File

@@ -1667,15 +1667,29 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
public void onLayoutSizeChanged(SplitLayout layout) { public void onLayoutSizeChanged(SplitLayout layout) {
// Reset this flag every time onLayoutSizeChanged. // Reset this flag every time onLayoutSizeChanged.
mShowDecorImmediately = false; mShowDecorImmediately = false;
if (!ENABLE_SHELL_TRANSITIONS) {
// Only need screenshot for legacy case because shell transition should screenshot
// itself during transition.
final SurfaceControl.Transaction startT = mTransactionPool.acquire();
mMainStage.screenshotIfNeeded(startT);
mSideStage.screenshotIfNeeded(startT);
mTransactionPool.release(startT);
}
final WindowContainerTransaction wct = new WindowContainerTransaction(); final WindowContainerTransaction wct = new WindowContainerTransaction();
updateWindowBounds(layout, wct); updateWindowBounds(layout, wct);
sendOnBoundsChanged(); sendOnBoundsChanged();
if (ENABLE_SHELL_TRANSITIONS) {
mSplitTransitions.startResizeTransition(wct, this, null /* callback */);
} else {
mSyncQueue.queue(wct); mSyncQueue.queue(wct);
mSyncQueue.runInSync(t -> { mSyncQueue.runInSync(t -> {
updateSurfaceBounds(layout, t, false /* applyResizingOffset */); updateSurfaceBounds(layout, t, false /* applyResizingOffset */);
mMainStage.onResized(t); mMainStage.onResized(t);
mSideStage.onResized(t); mSideStage.onResized(t);
}); });
}
mLogger.logResize(mSplitLayout.getDividerPositionAsFraction()); mLogger.logResize(mSplitLayout.getDividerPositionAsFraction());
} }
@@ -2029,6 +2043,12 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
} else if (mSplitTransitions.isPendingDismiss(transition)) { } else if (mSplitTransitions.isPendingDismiss(transition)) {
shouldAnimate = startPendingDismissAnimation( shouldAnimate = startPendingDismissAnimation(
mSplitTransitions.mPendingDismiss, info, startTransaction, finishTransaction); mSplitTransitions.mPendingDismiss, info, startTransaction, finishTransaction);
} else if (mSplitTransitions.isPendingResize(transition)) {
mSplitTransitions.applyResizeTransition(transition, info, startTransaction,
finishTransaction, finishCallback, mMainStage.mRootTaskInfo.token,
mSideStage.mRootTaskInfo.token, mMainStage.getSplitDecorManager(),
mSideStage.getSplitDecorManager());
return true;
} }
if (!shouldAnimate) return false; if (!shouldAnimate) return false;

View File

@@ -292,7 +292,13 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
void onResized(SurfaceControl.Transaction t) { void onResized(SurfaceControl.Transaction t) {
if (mSplitDecorManager != null) { if (mSplitDecorManager != null) {
mSplitDecorManager.onResized(t); mSplitDecorManager.onResized(t, null);
}
}
void screenshotIfNeeded(SurfaceControl.Transaction t) {
if (mSplitDecorManager != null) {
mSplitDecorManager.screenshotIfNeeded(t);
} }
} }
@@ -304,6 +310,10 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
} }
} }
SplitDecorManager getSplitDecorManager() {
return mSplitDecorManager;
}
void addTask(ActivityManager.RunningTaskInfo task, WindowContainerTransaction wct) { void addTask(ActivityManager.RunningTaskInfo task, WindowContainerTransaction wct) {
// Clear overridden bounds and windowing mode to make sure the child task can inherit // Clear overridden bounds and windowing mode to make sure the child task can inherit
// windowing mode and bounds from split root. // windowing mode and bounds from split root.

View File

@@ -2183,7 +2183,7 @@ class Task extends TaskFragment {
} }
private boolean shouldStartChangeTransition(int prevWinMode, @NonNull Rect prevBounds) { private boolean shouldStartChangeTransition(int prevWinMode, @NonNull Rect prevBounds) {
if (!isLeafTask() || !canStartChangeTransition()) { if (!(isLeafTask() || mCreatedByOrganizer) || !canStartChangeTransition()) {
return false; return false;
} }
final int newWinMode = getWindowingMode(); final int newWinMode = getWindowingMode();