diff options
| author | 2023-11-07 15:07:10 +0000 | |
|---|---|---|
| committer | 2023-11-07 15:07:10 +0000 | |
| commit | 8b4373760a0c6c9db63fec7fc825f449f47c7ed9 (patch) | |
| tree | da0ec94d85392894090260decfd654cf698d6690 | |
| parent | 263eeb2ab8b32899c331860955addd65366177b9 (diff) | |
| parent | 736ff82e0de0d57d2b31ada94214a767edb39420 (diff) | |
Merge "Handover Recents to Keyguard on swipe-up finish" into main
5 files changed, 188 insertions, 58 deletions
diff --git a/core/java/android/window/TransitionInfo.java b/core/java/android/window/TransitionInfo.java index 1a2d202be934..5bfa3d759a66 100644 --- a/core/java/android/window/TransitionInfo.java +++ b/core/java/android/window/TransitionInfo.java @@ -55,6 +55,7 @@ import android.view.WindowManager; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * Used to communicate information about what is changing during a transition to a TransitionPlayer. @@ -610,7 +611,7 @@ public final class TransitionInfo implements Parcelable { private final WindowContainerToken mContainer; private WindowContainerToken mParent; private WindowContainerToken mLastParent; - private final SurfaceControl mLeash; + private SurfaceControl mLeash; private @TransitionMode int mMode = TRANSIT_NONE; private @ChangeFlags int mFlags = FLAG_NONE; private final Rect mStartAbsBounds = new Rect(); @@ -697,6 +698,11 @@ public final class TransitionInfo implements Parcelable { mLastParent = lastParent; } + /** Sets the animation leash for controlling this change's container */ + public void setLeash(@NonNull SurfaceControl leash) { + mLeash = Objects.requireNonNull(leash); + } + /** Sets the transition mode for this change */ public void setMode(@TransitionMode int mode) { mMode = mode; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java index 64294c9dbdc6..beae96ec3f3b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java @@ -646,11 +646,12 @@ public abstract class WMShellBaseModule { @Provides static KeyguardTransitionHandler provideKeyguardTransitionHandler( ShellInit shellInit, + ShellController shellController, Transitions transitions, @ShellMainThread Handler mainHandler, @ShellMainThread ShellExecutor mainExecutor) { return new KeyguardTransitionHandler( - shellInit, transitions, mainHandler, mainExecutor); + shellInit, shellController, transitions, mainHandler, mainExecutor); } @WMSingleton diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java index dba7f4bdd78d..0890861596a5 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java @@ -50,6 +50,8 @@ import com.android.internal.protolog.common.ProtoLog; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.annotations.ExternalThread; import com.android.wm.shell.protolog.ShellProtoLogGroup; +import com.android.wm.shell.sysui.KeyguardChangeListener; +import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.transition.Transitions.TransitionFinishCallback; @@ -59,10 +61,12 @@ import com.android.wm.shell.transition.Transitions.TransitionFinishCallback; * * <p>This takes the highest priority. */ -public class KeyguardTransitionHandler implements Transitions.TransitionHandler { +public class KeyguardTransitionHandler + implements Transitions.TransitionHandler, KeyguardChangeListener { private static final String TAG = "KeyguardTransition"; private final Transitions mTransitions; + private final ShellController mShellController; private final Handler mMainHandler; private final ShellExecutor mMainExecutor; @@ -81,6 +85,9 @@ public class KeyguardTransitionHandler implements Transitions.TransitionHandler // transition. private boolean mIsLaunchingActivityOverLockscreen; + // Last value reported by {@link KeyguardChangeListener}. + private boolean mKeyguardShowing = true; + private final class StartedTransition { final TransitionInfo mInfo; final SurfaceControl.Transaction mFinishT; @@ -93,12 +100,15 @@ public class KeyguardTransitionHandler implements Transitions.TransitionHandler mPlayer = player; } } + public KeyguardTransitionHandler( @NonNull ShellInit shellInit, + @NonNull ShellController shellController, @NonNull Transitions transitions, @NonNull Handler mainHandler, @NonNull ShellExecutor mainExecutor) { mTransitions = transitions; + mShellController = shellController; mMainHandler = mainHandler; mMainExecutor = mainExecutor; shellInit.addInitCallback(this::onInit, this); @@ -106,6 +116,7 @@ public class KeyguardTransitionHandler implements Transitions.TransitionHandler private void onInit() { mTransitions.addHandler(this); + mShellController.addKeyguardChangeListener(this); } /** @@ -121,6 +132,16 @@ public class KeyguardTransitionHandler implements Transitions.TransitionHandler } @Override + public void onKeyguardVisibilityChanged( + boolean visible, boolean occluded, boolean animatingDismiss) { + mKeyguardShowing = visible; + } + + public boolean isKeyguardShowing() { + return mKeyguardShowing; + } + + @Override public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java index c20d23e4374e..271a3b26305d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java @@ -64,6 +64,7 @@ import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.util.TransitionUtil; import java.util.ArrayList; +import java.util.function.Consumer; /** * Handles the Recents (overview) animation. Only one of these can run at a time. A recents @@ -130,21 +131,21 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler { wct.sendPendingIntent(intent, fillIn, options); final RecentsController controller = new RecentsController(listener); RecentsMixedHandler mixer = null; - Transitions.TransitionHandler mixedHandler = null; + Consumer<IBinder> setTransitionForMixer = null; for (int i = 0; i < mMixers.size(); ++i) { - mixedHandler = mMixers.get(i).handleRecentsRequest(wct); - if (mixedHandler != null) { + setTransitionForMixer = mMixers.get(i).handleRecentsRequest(wct); + if (setTransitionForMixer != null) { mixer = mMixers.get(i); break; } } final IBinder transition = mTransitions.startTransition(TRANSIT_TO_FRONT, wct, - mixedHandler == null ? this : mixedHandler); + mixer == null ? this : mixer); for (int i = 0; i < mStateListeners.size(); i++) { mStateListeners.get(i).onTransitionStarted(transition); } if (mixer != null) { - mixer.setRecentsTransition(transition); + setTransitionForMixer.accept(transition); } if (transition != null) { controller.setTransition(transition); @@ -589,6 +590,13 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler { cancel("transit_sleep"); return; } + if (mKeyguardLocked) { + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, + "[%d] RecentsController.merge: keyguard is locked", mInstanceId); + // We will not accept new changes if we are swiping over the keyguard. + cancel(true /* toHome */, false /* withScreenshots */, "keyguard_locked"); + return; + } ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, "[%d] RecentsController.merge", mInstanceId); // Keep all tasks in one list because order matters. @@ -1105,22 +1113,17 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler { * An interface for a mixed handler to receive information about recents requests (since these * come into this handler directly vs from WMCore request). */ - public interface RecentsMixedHandler { + public interface RecentsMixedHandler extends Transitions.TransitionHandler { /** * Called when a recents request comes in. The handler can add operations to outWCT. If - * the handler wants to "accept" the transition, it should return itself; otherwise, it - * should return `null`. + * the handler wants to "accept" the transition, it should return a Consumer accepting the + * IBinder for the transition. If not, it should return `null`. * * If a mixed-handler accepts this recents, it will be the de-facto handler for this * transition and is required to call the associated {@link #startAnimation}, * {@link #mergeAnimation}, and {@link #onTransitionConsumed} methods. */ - Transitions.TransitionHandler handleRecentsRequest(WindowContainerTransaction outWCT); - - /** - * Reports the transition token associated with the accepted recents request. If there was - * a problem starting the request, this will be called with `null`. - */ - void setRecentsTransition(@Nullable IBinder transition); + @Nullable + Consumer<IBinder> handleRecentsRequest(WindowContainerTransaction outWCT); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java index 918a5a4bd53e..ce7fef2d1fdf 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java @@ -23,6 +23,7 @@ import static android.view.Display.DEFAULT_DISPLAY; import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_PIP; import static android.view.WindowManager.TRANSIT_TO_BACK; +import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_UNOCCLUDING; import static android.window.TransitionInfo.FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY; import static android.window.TransitionInfo.FLAG_IS_WALLPAPER; @@ -37,11 +38,13 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.PendingIntent; import android.os.IBinder; +import android.util.ArrayMap; import android.util.Pair; import android.view.SurfaceControl; import android.view.WindowManager; import android.window.TransitionInfo; import android.window.TransitionRequestInfo; +import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; import com.android.internal.protolog.common.ProtoLog; @@ -61,7 +64,9 @@ import com.android.wm.shell.unfold.UnfoldTransitionHandler; import com.android.wm.shell.util.TransitionUtil; import java.util.ArrayList; +import java.util.Map; import java.util.Optional; +import java.util.function.Consumer; /** * A handler for dealing with transitions involving multiple other handlers. For example: an @@ -79,7 +84,7 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler, private UnfoldTransitionHandler mUnfoldHandler; private ActivityEmbeddingController mActivityEmbeddingController; - private static class MixedTransition { + private class MixedTransition { static final int TYPE_ENTER_PIP_FROM_SPLIT = 1; /** Both the display and split-state (enter/exit) is changing */ @@ -94,14 +99,17 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler, /** Keyguard exit/occlude/unocclude transition. */ static final int TYPE_KEYGUARD = 5; + /** Recents transition on top of the lock screen. */ + static final int TYPE_RECENTS_DURING_KEYGUARD = 6; + /** Recents Transition while in desktop mode. */ - static final int TYPE_RECENTS_DURING_DESKTOP = 6; + static final int TYPE_RECENTS_DURING_DESKTOP = 7; /** Fold/Unfold transition. */ - static final int TYPE_UNFOLD = 7; + static final int TYPE_UNFOLD = 8; /** Enter pip from one of the Activity Embedding windows. */ - static final int TYPE_ENTER_PIP_FROM_ACTIVITY_EMBEDDING = 8; + static final int TYPE_ENTER_PIP_FROM_ACTIVITY_EMBEDDING = 9; /** The default animation for this mixed transition. */ static final int ANIM_TYPE_DEFAULT = 0; @@ -117,7 +125,10 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler, final IBinder mTransition; Transitions.TransitionHandler mLeftoversHandler = null; + TransitionInfo mInfo = null; WindowContainerTransaction mFinishWCT = null; + SurfaceControl.Transaction mFinishT = null; + Transitions.TransitionFinishCallback mFinishCB = null; /** * Whether the transition has request for remote transition while mLeftoversHandler @@ -138,6 +149,37 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler, mTransition = transition; } + boolean startSubAnimation(Transitions.TransitionHandler handler, TransitionInfo info, + SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT) { + if (mInfo != null) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, + "startSubAnimation #%d.%d", mInfo.getDebugId(), info.getDebugId()); + } + mInFlightSubAnimations++; + if (!handler.startAnimation( + mTransition, info, startT, finishT, wct -> onSubAnimationFinished(info, wct))) { + mInFlightSubAnimations--; + return false; + } + return true; + } + + void onSubAnimationFinished(TransitionInfo info, WindowContainerTransaction wct) { + mInFlightSubAnimations--; + if (mInfo != null) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, + "onSubAnimationFinished #%d.%d remaining=%d", + mInfo.getDebugId(), info.getDebugId(), mInFlightSubAnimations); + } + + joinFinishArgs(wct); + + if (mInFlightSubAnimations == 0) { + mActiveTransitions.remove(MixedTransition.this); + mFinishCB.onTransitionFinished(mFinishWCT); + } + } + void joinFinishArgs(WindowContainerTransaction wct) { if (wct != null) { if (mFinishWCT == null) { @@ -271,39 +313,46 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler, } @Override - public Transitions.TransitionHandler handleRecentsRequest(WindowContainerTransaction outWCT) { + public Consumer<IBinder> handleRecentsRequest(WindowContainerTransaction outWCT) { if (mRecentsHandler != null) { if (mSplitHandler.isSplitScreenVisible()) { - return this; + return this::setRecentsTransitionDuringSplit; + } else if (mKeyguardHandler.isKeyguardShowing()) { + return this::setRecentsTransitionDuringKeyguard; } else if (mDesktopTasksController != null // Check on the default display. Recents/gesture nav is only available there && mDesktopTasksController.getVisibleTaskCount(DEFAULT_DISPLAY) > 0) { - return this; + return this::setRecentsTransitionDuringDesktop; } } return null; } - @Override - public void setRecentsTransition(IBinder transition) { - if (mSplitHandler.isSplitScreenVisible()) { - ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Got a recents request while " - + "Split-Screen is foreground, so treat it as Mixed."); - final MixedTransition mixed = new MixedTransition( - MixedTransition.TYPE_RECENTS_DURING_SPLIT, transition); - mixed.mLeftoversHandler = mRecentsHandler; - mActiveTransitions.add(mixed); - } else if (DesktopModeStatus.isEnabled()) { - ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Got a recents request while " - + "desktop mode is active, so treat it as Mixed."); - final MixedTransition mixed = new MixedTransition( - MixedTransition.TYPE_RECENTS_DURING_DESKTOP, transition); - mixed.mLeftoversHandler = mRecentsHandler; - mActiveTransitions.add(mixed); - } else { - throw new IllegalStateException("Accepted a recents transition but don't know how to" - + " handle it"); - } + private void setRecentsTransitionDuringSplit(IBinder transition) { + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Got a recents request while " + + "Split-Screen is foreground, so treat it as Mixed."); + final MixedTransition mixed = new MixedTransition( + MixedTransition.TYPE_RECENTS_DURING_SPLIT, transition); + mixed.mLeftoversHandler = mRecentsHandler; + mActiveTransitions.add(mixed); + } + + private void setRecentsTransitionDuringKeyguard(IBinder transition) { + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Got a recents request while " + + "keyguard is visible, so treat it as Mixed."); + final MixedTransition mixed = new MixedTransition( + MixedTransition.TYPE_RECENTS_DURING_KEYGUARD, transition); + mixed.mLeftoversHandler = mRecentsHandler; + mActiveTransitions.add(mixed); + } + + private void setRecentsTransitionDuringDesktop(IBinder transition) { + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Got a recents request while " + + "desktop mode is active, so treat it as Mixed."); + final MixedTransition mixed = new MixedTransition( + MixedTransition.TYPE_RECENTS_DURING_DESKTOP, transition); + mixed.mLeftoversHandler = mRecentsHandler; + mActiveTransitions.add(mixed); } private TransitionInfo subCopy(@NonNull TransitionInfo info, @@ -410,6 +459,9 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler, } else if (mixed.mType == MixedTransition.TYPE_KEYGUARD) { return animateKeyguard(mixed, info, startTransaction, finishTransaction, finishCallback); + } else if (mixed.mType == MixedTransition.TYPE_RECENTS_DURING_KEYGUARD) { + return animateRecentsDuringKeyguard(mixed, info, startTransaction, finishTransaction, + finishCallback); } else if (mixed.mType == MixedTransition.TYPE_RECENTS_DURING_DESKTOP) { return animateRecentsDuringDesktop(mixed, info, startTransaction, finishTransaction, finishCallback); @@ -764,24 +816,28 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler, @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull Transitions.TransitionFinishCallback finishCallback) { - final Transitions.TransitionFinishCallback finishCB = (wct) -> { - mixed.mInFlightSubAnimations--; - if (mixed.mInFlightSubAnimations == 0) { - mActiveTransitions.remove(mixed); - finishCallback.onTransitionFinished(wct); - } - }; - mixed.mInFlightSubAnimations++; + if (mixed.mFinishT == null) { + mixed.mFinishT = finishTransaction; + mixed.mFinishCB = finishCallback; + } // Sync pip state. if (mPipHandler != null) { mPipHandler.syncPipSurfaceState(info, startTransaction, finishTransaction); } - if (!mKeyguardHandler.startAnimation( - mixed.mTransition, info, startTransaction, finishTransaction, finishCB)) { - mixed.mInFlightSubAnimations--; - return false; + return mixed.startSubAnimation(mKeyguardHandler, info, startTransaction, finishTransaction); + } + + private boolean animateRecentsDuringKeyguard(@NonNull final MixedTransition mixed, + @NonNull TransitionInfo info, + @NonNull SurfaceControl.Transaction startTransaction, + @NonNull SurfaceControl.Transaction finishTransaction, + @NonNull Transitions.TransitionFinishCallback finishCallback) { + if (mixed.mInfo == null) { + mixed.mInfo = info; + mixed.mFinishT = finishTransaction; + mixed.mFinishCB = finishCallback; } - return true; + return mixed.startSubAnimation(mRecentsHandler, info, startTransaction, finishTransaction); } private boolean animateRecentsDuringDesktop(@NonNull final MixedTransition mixed, @@ -905,6 +961,15 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler, finishCallback); } else if (mixed.mType == MixedTransition.TYPE_KEYGUARD) { mKeyguardHandler.mergeAnimation(transition, info, t, mergeTarget, finishCallback); + } else if (mixed.mType == MixedTransition.TYPE_RECENTS_DURING_KEYGUARD) { + if ((info.getFlags() & TRANSIT_FLAG_KEYGUARD_UNOCCLUDING) != 0) { + handoverTransitionLeashes(mixed, info, t, mixed.mFinishT); + if (animateKeyguard(mixed, info, t, mixed.mFinishT, mixed.mFinishCB)) { + finishCallback.onTransitionFinished(null); + } + } + mixed.mLeftoversHandler.mergeAnimation(transition, info, t, mergeTarget, + finishCallback); } else if (mixed.mType == MixedTransition.TYPE_RECENTS_DURING_DESKTOP) { mixed.mLeftoversHandler.mergeAnimation(transition, info, t, mergeTarget, finishCallback); @@ -947,4 +1012,38 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler, mPlayer.getRemoteTransitionHandler().onTransitionConsumed(transition, aborted, finishT); } } + + /** + * Update an incoming {@link TransitionInfo} with the leashes from an ongoing + * {@link MixedTransition} so that it can take over some parts of the animation without + * reparenting to new transition roots. + */ + private static void handoverTransitionLeashes(@NonNull MixedTransition mixed, + @NonNull TransitionInfo info, + @NonNull SurfaceControl.Transaction startT, + @NonNull SurfaceControl.Transaction finishT) { + + // Show the roots in case they contain new changes not present in the original transition. + for (int j = info.getRootCount() - 1; j >= 0; --j) { + startT.show(info.getRoot(j).getLeash()); + } + + // Find all of the leashes from the original transition. + Map<WindowContainerToken, TransitionInfo.Change> originalChanges = new ArrayMap<>(); + for (TransitionInfo.Change oldChange : mixed.mInfo.getChanges()) { + if (oldChange.getContainer() != null) { + originalChanges.put(oldChange.getContainer(), oldChange); + } + } + + // Merge the animation leashes by re-using the original ones if we see the same container + // in the new transition and the old. + for (TransitionInfo.Change newChange : info.getChanges()) { + if (originalChanges.containsKey(newChange.getContainer())) { + final TransitionInfo.Change oldChange = originalChanges.get(newChange.getContainer()); + startT.reparent(newChange.getLeash(), null); + newChange.setLeash(oldChange.getLeash()); + } + } + } } |