diff options
| author | 2022-12-07 03:43:13 +0000 | |
|---|---|---|
| committer | 2022-12-07 03:43:13 +0000 | |
| commit | 0de589346f7cc6ae7d5b3bcd991b05fb4759df4c (patch) | |
| tree | f20c700dc8eef6114612dd8d033fc5acd13adcce | |
| parent | 0b26f2e580a33946d7b2b6d7f734085dd67ebbc2 (diff) | |
| parent | 104a5f5ce447e5b97c6ba178330f5a977a67dd34 (diff) | |
Merge "Implement split resize shell transition" into tm-qpr-dev
5 files changed, 160 insertions, 30 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java index 6e116b958ac9..c836b95ffab8 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java @@ -51,8 +51,6 @@ import com.android.wm.shell.R; import com.android.wm.shell.common.ScreenshotUtils; import com.android.wm.shell.common.SurfaceUtils; -import java.util.function.Consumer; - /** * 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 mBackgroundLeash; private SurfaceControl mGapBackgroundLeash; + private SurfaceControl mScreenshot; private boolean mShown; private boolean mIsResizing; private final Rect mBounds = new Rect(); - private final Rect mResizingBounds = new Rect(); private final Rect mTempRect = new Rect(); private ValueAnimator mFadeAnimator; private int mIconSize; private int mOffsetX; private int mOffsetY; + private int mRunningAnimationCount = 0; public SplitDecorManager(Configuration configuration, IconProvider iconProvider, SurfaceSession surfaceSession) { @@ -173,7 +172,6 @@ public class SplitDecorManager extends WindowlessWindowManager { mIsResizing = true; mBounds.set(newBounds); } - mResizingBounds.set(newBounds); mOffsetX = offsetX; mOffsetY = offsetY; @@ -227,33 +225,41 @@ public class SplitDecorManager extends WindowlessWindowManager { t.setVisibility(mBackgroundLeash, show); t.setVisibility(mIconLeash, show); } else { - startFadeAnimation(show, null /* finishedConsumer */); + startFadeAnimation(show, false, null); } mShown = show; } } /** Stops showing resizing hint. */ - public void onResized(SurfaceControl.Transaction t) { - if (!mShown && mIsResizing) { - mTempRect.set(mResizingBounds); - mTempRect.offsetTo(-mOffsetX, -mOffsetY); - final SurfaceControl screenshot = ScreenshotUtils.takeScreenshot(t, - mHostLeash, mTempRect, Integer.MAX_VALUE - 1); + public void onResized(SurfaceControl.Transaction t, Runnable animFinishedCallback) { + if (mScreenshot != null) { + t.setPosition(mScreenshot, mOffsetX, mOffsetY); final SurfaceControl.Transaction animT = new SurfaceControl.Transaction(); final ValueAnimator va = ValueAnimator.ofFloat(1, 0); va.addUpdateListener(valueAnimator -> { final float progress = (float) valueAnimator.getAnimatedValue(); - animT.setAlpha(screenshot, progress); + animT.setAlpha(mScreenshot, progress); animT.apply(); }); va.addListener(new AnimatorListenerAdapter() { @Override + public void onAnimationStart(Animator animation) { + mRunningAnimationCount++; + } + + @Override public void onAnimationEnd(@androidx.annotation.NonNull Animator animation) { - animT.remove(screenshot); + mRunningAnimationCount--; + animT.remove(mScreenshot); animT.apply(); animT.close(); + mScreenshot = null; + + if (mRunningAnimationCount == 0 && animFinishedCallback != null) { + animFinishedCallback.run(); + } } }); va.start(); @@ -285,10 +291,34 @@ public class SplitDecorManager extends WindowlessWindowManager { mFadeAnimator.cancel(); } if (mShown) { - fadeOutDecor(null /* finishedCallback */); + fadeOutDecor(animFinishedCallback); } else { // Decor surface is hidden so release it directly. 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. */ public void fadeOutDecor(Runnable finishedCallback) { if (mShown) { - startFadeAnimation(false /* show */, transaction -> { - releaseDecor(transaction); - if (finishedCallback != null) finishedCallback.run(); - }); + startFadeAnimation(false /* show */, true, finishedCallback); mShown = false; } else { if (finishedCallback != null) finishedCallback.run(); } } - private void startFadeAnimation(boolean show, - Consumer<SurfaceControl.Transaction> finishedConsumer) { + private void startFadeAnimation(boolean show, boolean releaseSurface, + Runnable finishedCallback) { final SurfaceControl.Transaction animT = new SurfaceControl.Transaction(); mFadeAnimator = ValueAnimator.ofFloat(0f, 1f); mFadeAnimator.setDuration(FADE_DURATION); @@ -324,6 +351,7 @@ public class SplitDecorManager extends WindowlessWindowManager { mFadeAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(@NonNull Animator animation) { + mRunningAnimationCount++; if (show) { animT.show(mBackgroundLeash).show(mIconLeash); } @@ -335,6 +363,7 @@ public class SplitDecorManager extends WindowlessWindowManager { @Override public void onAnimationEnd(@NonNull Animator animation) { + mRunningAnimationCount--; if (!show) { if (mBackgroundLeash != null) { animT.hide(mBackgroundLeash); @@ -343,11 +372,15 @@ public class SplitDecorManager extends WindowlessWindowManager { animT.hide(mIconLeash); } } - if (finishedConsumer != null) { - finishedConsumer.accept(animT); + if (releaseSurface) { + releaseDecor(animT); } animT.apply(); animT.close(); + + if (mRunningAnimationCount == 0 && finishedCallback != null) { + finishedCallback.run(); + } } }); mFadeAnimator.start(); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java index 21a13103616c..1cf3a896b68e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java @@ -47,6 +47,7 @@ import android.window.WindowContainerTransactionCallback; import com.android.internal.protolog.common.ProtoLog; 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.transition.OneShotRemoteHandler; import com.android.wm.shell.transition.Transitions; @@ -64,6 +65,7 @@ class SplitScreenTransitions { DismissTransition mPendingDismiss = null; TransitSession mPendingEnter = null; TransitSession mPendingRecent = null; + TransitSession mPendingResize = null; private IBinder mAnimatingTransition = null; OneShotRemoteHandler mPendingRemoteHandler = null; @@ -177,6 +179,43 @@ class SplitScreenTransitions { 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) { return getPendingTransition(transition) != null; } @@ -193,6 +232,10 @@ class SplitScreenTransitions { return mPendingDismiss != null && mPendingDismiss.mTransition == transition; } + boolean isPendingResize(IBinder transition) { + return mPendingResize != null && mPendingResize.mTransition == transition; + } + @Nullable private TransitSession getPendingTransition(IBinder transition) { if (isPendingEnter(transition)) { @@ -201,11 +244,14 @@ class SplitScreenTransitions { return mPendingRecent; } else if (isPendingDismiss(transition)) { return mPendingDismiss; + } else if (isPendingResize(transition)) { + return mPendingResize; } return null; } + /** Starts a transition to enter split with a remote transition animator. */ IBinder startEnterTransition( @WindowManager.TransitionType int transitType, @@ -258,6 +304,21 @@ class SplitScreenTransitions { 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, @Nullable RemoteTransition remoteTransition, @Nullable TransitionFinishedCallback finishCallback) { @@ -324,6 +385,9 @@ class SplitScreenTransitions { mPendingRecent.onConsumed(aborted); mPendingRecent = null; mPendingRemoteHandler = null; + } else if (isPendingResize(transition)) { + mPendingResize.onConsumed(aborted); + mPendingResize = null; } } @@ -340,6 +404,9 @@ class SplitScreenTransitions { } else if (isPendingDismiss(mAnimatingTransition)) { mPendingDismiss.onFinished(wct, mFinishTransaction); mPendingDismiss = null; + } else if (isPendingResize(mAnimatingTransition)) { + mPendingResize.onFinished(wct, mFinishTransaction); + mPendingResize = null; } mPendingRemoteHandler = null; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java index aa0512b64a16..38fb2df11df9 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java @@ -1667,15 +1667,29 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, public void onLayoutSizeChanged(SplitLayout layout) { // Reset this flag every time onLayoutSizeChanged. 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(); updateWindowBounds(layout, wct); sendOnBoundsChanged(); - mSyncQueue.queue(wct); - mSyncQueue.runInSync(t -> { - updateSurfaceBounds(layout, t, false /* applyResizingOffset */); - mMainStage.onResized(t); - mSideStage.onResized(t); - }); + if (ENABLE_SHELL_TRANSITIONS) { + mSplitTransitions.startResizeTransition(wct, this, null /* callback */); + } else { + mSyncQueue.queue(wct); + mSyncQueue.runInSync(t -> { + updateSurfaceBounds(layout, t, false /* applyResizingOffset */); + mMainStage.onResized(t); + mSideStage.onResized(t); + }); + } mLogger.logResize(mSplitLayout.getDividerPositionAsFraction()); } @@ -2029,6 +2043,12 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } else if (mSplitTransitions.isPendingDismiss(transition)) { shouldAnimate = startPendingDismissAnimation( 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; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java index 358f712f76b5..8a52c8750ba6 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java @@ -292,7 +292,13 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener { void onResized(SurfaceControl.Transaction t) { 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) { // Clear overridden bounds and windowing mode to make sure the child task can inherit // windowing mode and bounds from split root. diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 76a112283220..51eec03855a5 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -2183,7 +2183,7 @@ class Task extends TaskFragment { } private boolean shouldStartChangeTransition(int prevWinMode, @NonNull Rect prevBounds) { - if (!isLeafTask() || !canStartChangeTransition()) { + if (!(isLeafTask() || mCreatedByOrganizer) || !canStartChangeTransition()) { return false; } final int newWinMode = getWindowingMode(); |