Loading core/java/android/window/TransitionInfo.java +7 −1 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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(); Loading Loading @@ -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; Loading libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java +2 −1 Original line number Diff line number Diff line Loading @@ -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 Loading libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java +22 −1 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading @@ -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); Loading @@ -106,6 +116,7 @@ public class KeyguardTransitionHandler implements Transitions.TransitionHandler private void onInit() { mTransitions.addHandler(this); mShellController.addKeyguardChangeListener(this); } /** Loading @@ -120,6 +131,16 @@ public class KeyguardTransitionHandler implements Transitions.TransitionHandler return (info.getFlags() & KEYGUARD_VISIBILITY_TRANSIT_FLAGS) != 0; } @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, Loading libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java +18 −15 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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); Loading Loading @@ -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. Loading Loading @@ -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); } } libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java +139 −40 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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 Loading @@ -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 */ Loading @@ -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; Loading @@ -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 Loading @@ -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) { Loading Loading @@ -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()) { 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); } else if (DesktopModeStatus.isEnabled()) { } 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); } else { throw new IllegalStateException("Accepted a recents transition but don't know how to" + " handle it"); } } private TransitionInfo subCopy(@NonNull TransitionInfo info, Loading Loading @@ -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); Loading Loading @@ -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); if (mixed.mFinishT == null) { mixed.mFinishT = finishTransaction; mixed.mFinishCB = finishCallback; } }; mixed.mInFlightSubAnimations++; // 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); } return true; 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 mixed.startSubAnimation(mRecentsHandler, info, startTransaction, finishTransaction); } private boolean animateRecentsDuringDesktop(@NonNull final MixedTransition mixed, Loading Loading @@ -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); Loading Loading @@ -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()); } } } } Loading
core/java/android/window/TransitionInfo.java +7 −1 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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(); Loading Loading @@ -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; Loading
libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java +2 −1 Original line number Diff line number Diff line Loading @@ -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 Loading
libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java +22 −1 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading @@ -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); Loading @@ -106,6 +116,7 @@ public class KeyguardTransitionHandler implements Transitions.TransitionHandler private void onInit() { mTransitions.addHandler(this); mShellController.addKeyguardChangeListener(this); } /** Loading @@ -120,6 +131,16 @@ public class KeyguardTransitionHandler implements Transitions.TransitionHandler return (info.getFlags() & KEYGUARD_VISIBILITY_TRANSIT_FLAGS) != 0; } @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, Loading
libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java +18 −15 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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); Loading Loading @@ -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. Loading Loading @@ -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); } }
libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java +139 −40 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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 Loading @@ -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 */ Loading @@ -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; Loading @@ -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 Loading @@ -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) { Loading Loading @@ -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()) { 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); } else if (DesktopModeStatus.isEnabled()) { } 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); } else { throw new IllegalStateException("Accepted a recents transition but don't know how to" + " handle it"); } } private TransitionInfo subCopy(@NonNull TransitionInfo info, Loading Loading @@ -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); Loading Loading @@ -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); if (mixed.mFinishT == null) { mixed.mFinishT = finishTransaction; mixed.mFinishCB = finishCallback; } }; mixed.mInFlightSubAnimations++; // 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); } return true; 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 mixed.startSubAnimation(mRecentsHandler, info, startTransaction, finishTransaction); } private boolean animateRecentsDuringDesktop(@NonNull final MixedTransition mixed, Loading Loading @@ -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); Loading Loading @@ -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()); } } } }