Loading libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +8 −2 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ import com.android.wm.shell.common.SystemWindows; import com.android.wm.shell.common.TabletopModeController; import com.android.wm.shell.common.TaskStackListenerImpl; import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.common.annotations.ShellAnimationThread; import com.android.wm.shell.common.annotations.ShellBackgroundThread; import com.android.wm.shell.common.annotations.ShellMainThread; import com.android.wm.shell.desktopmode.DesktopModeController; Loading Loading @@ -264,8 +265,13 @@ public abstract class WMShellModule { static FreeformTaskTransitionHandler provideFreeformTaskTransitionHandler( ShellInit shellInit, Transitions transitions, WindowDecorViewModel windowDecorViewModel) { return new FreeformTaskTransitionHandler(shellInit, transitions, windowDecorViewModel); Context context, WindowDecorViewModel windowDecorViewModel, DisplayController displayController, @ShellMainThread ShellExecutor mainExecutor, @ShellAnimationThread ShellExecutor animExecutor) { return new FreeformTaskTransitionHandler(shellInit, transitions, context, windowDecorViewModel, displayController, mainExecutor, animExecutor); } @WMSingleton Loading libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java +94 −10 Original line number Diff line number Diff line Loading @@ -19,9 +19,15 @@ package com.android.wm.shell.freeform; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.app.ActivityManager; import android.app.WindowConfiguration; import android.content.Context; import android.graphics.Rect; import android.os.IBinder; import android.util.ArrayMap; import android.view.SurfaceControl; import android.view.WindowManager; import android.window.TransitionInfo; Loading @@ -31,6 +37,8 @@ import android.window.WindowContainerTransaction; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.windowdecor.WindowDecorViewModel; Loading @@ -39,23 +47,37 @@ import java.util.ArrayList; import java.util.List; /** * The {@link Transitions.TransitionHandler} that handles freeform task maximizing and restoring * transitions. * The {@link Transitions.TransitionHandler} that handles freeform task maximizing, closing, and * restoring transitions. */ public class FreeformTaskTransitionHandler implements Transitions.TransitionHandler, FreeformTaskTransitionStarter { private static final int CLOSE_ANIM_DURATION = 400; private final Context mContext; private final Transitions mTransitions; private final WindowDecorViewModel mWindowDecorViewModel; private final DisplayController mDisplayController; private final ShellExecutor mMainExecutor; private final ShellExecutor mAnimExecutor; private final List<IBinder> mPendingTransitionTokens = new ArrayList<>(); private final ArrayMap<IBinder, ArrayList<Animator>> mAnimations = new ArrayMap<>(); public FreeformTaskTransitionHandler( ShellInit shellInit, Transitions transitions, WindowDecorViewModel windowDecorViewModel) { Context context, WindowDecorViewModel windowDecorViewModel, DisplayController displayController, ShellExecutor mainExecutor, ShellExecutor animExecutor) { mTransitions = transitions; mContext = context; mWindowDecorViewModel = windowDecorViewModel; mDisplayController = displayController; mMainExecutor = mainExecutor; mAnimExecutor = animExecutor; if (Transitions.ENABLE_SHELL_TRANSITIONS) { shellInit.addInitCallback(this::onInit, this); } Loading Loading @@ -103,6 +125,14 @@ public class FreeformTaskTransitionHandler @NonNull SurfaceControl.Transaction finishT, @NonNull Transitions.TransitionFinishCallback finishCallback) { boolean transitionHandled = false; final ArrayList<Animator> animations = new ArrayList<>(); final Runnable onAnimFinish = () -> { if (!animations.isEmpty()) return; mMainExecutor.execute(() -> { mAnimations.remove(transition); finishCallback.onTransitionFinished(null /* wct */, null /* wctCB */); }); }; for (TransitionInfo.Change change : info.getChanges()) { if ((change.getFlags() & TransitionInfo.FLAG_IS_WALLPAPER) != 0) { continue; Loading @@ -121,21 +151,45 @@ public class FreeformTaskTransitionHandler case WindowManager.TRANSIT_TO_BACK: transitionHandled |= startMinimizeTransition(transition); break; case WindowManager.TRANSIT_CLOSE: if (change.getTaskInfo().getWindowingMode() == WINDOWING_MODE_FREEFORM) { transitionHandled |= startCloseTransition(transition, change, finishT, animations, onAnimFinish); } break; } } mPendingTransitionTokens.remove(transition); if (!transitionHandled) { return false; } mAnimations.put(transition, animations); // startT must be applied before animations start. startT.apply(); mTransitions.getMainExecutor().execute( () -> finishCallback.onTransitionFinished(null, null)); mAnimExecutor.execute(() -> { for (Animator anim : animations) { anim.start(); } }); // Run this here in case no animators are created. onAnimFinish.run(); mPendingTransitionTokens.remove(transition); return true; } @Override public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget, @NonNull Transitions.TransitionFinishCallback finishCallback) { ArrayList<Animator> animations = mAnimations.get(mergeTarget); if (animations == null) return; mAnimExecutor.execute(() -> { for (Animator anim : animations) { anim.end(); } }); } private boolean startChangeTransition( IBinder transition, int type, Loading Loading @@ -165,6 +219,36 @@ public class FreeformTaskTransitionHandler return mPendingTransitionTokens.contains(transition); } private boolean startCloseTransition(IBinder transition, TransitionInfo.Change change, SurfaceControl.Transaction finishT, ArrayList<Animator> animations, Runnable onAnimFinish) { if (!mPendingTransitionTokens.contains(transition)) return false; int screenHeight = mDisplayController .getDisplayLayout(change.getTaskInfo().displayId).height(); ValueAnimator animator = new ValueAnimator(); animator.setDuration(CLOSE_ANIM_DURATION) .setFloatValues(0f, 1f); SurfaceControl.Transaction t = new SurfaceControl.Transaction(); SurfaceControl sc = change.getLeash(); finishT.hide(sc); Rect startBounds = new Rect(change.getTaskInfo().configuration.windowConfiguration .getBounds()); animator.addUpdateListener(animation -> { t.setPosition(sc, startBounds.left, startBounds.top + (animation.getAnimatedFraction() * screenHeight)); t.apply(); }); animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { animations.remove(animator); onAnimFinish.run(); } }); animations.add(animator); return true; } @Nullable @Override public WindowContainerTransaction handleRequest(@NonNull IBinder transition, Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +8 −2 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ import com.android.wm.shell.common.SystemWindows; import com.android.wm.shell.common.TabletopModeController; import com.android.wm.shell.common.TaskStackListenerImpl; import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.common.annotations.ShellAnimationThread; import com.android.wm.shell.common.annotations.ShellBackgroundThread; import com.android.wm.shell.common.annotations.ShellMainThread; import com.android.wm.shell.desktopmode.DesktopModeController; Loading Loading @@ -264,8 +265,13 @@ public abstract class WMShellModule { static FreeformTaskTransitionHandler provideFreeformTaskTransitionHandler( ShellInit shellInit, Transitions transitions, WindowDecorViewModel windowDecorViewModel) { return new FreeformTaskTransitionHandler(shellInit, transitions, windowDecorViewModel); Context context, WindowDecorViewModel windowDecorViewModel, DisplayController displayController, @ShellMainThread ShellExecutor mainExecutor, @ShellAnimationThread ShellExecutor animExecutor) { return new FreeformTaskTransitionHandler(shellInit, transitions, context, windowDecorViewModel, displayController, mainExecutor, animExecutor); } @WMSingleton Loading
libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java +94 −10 Original line number Diff line number Diff line Loading @@ -19,9 +19,15 @@ package com.android.wm.shell.freeform; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.app.ActivityManager; import android.app.WindowConfiguration; import android.content.Context; import android.graphics.Rect; import android.os.IBinder; import android.util.ArrayMap; import android.view.SurfaceControl; import android.view.WindowManager; import android.window.TransitionInfo; Loading @@ -31,6 +37,8 @@ import android.window.WindowContainerTransaction; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.windowdecor.WindowDecorViewModel; Loading @@ -39,23 +47,37 @@ import java.util.ArrayList; import java.util.List; /** * The {@link Transitions.TransitionHandler} that handles freeform task maximizing and restoring * transitions. * The {@link Transitions.TransitionHandler} that handles freeform task maximizing, closing, and * restoring transitions. */ public class FreeformTaskTransitionHandler implements Transitions.TransitionHandler, FreeformTaskTransitionStarter { private static final int CLOSE_ANIM_DURATION = 400; private final Context mContext; private final Transitions mTransitions; private final WindowDecorViewModel mWindowDecorViewModel; private final DisplayController mDisplayController; private final ShellExecutor mMainExecutor; private final ShellExecutor mAnimExecutor; private final List<IBinder> mPendingTransitionTokens = new ArrayList<>(); private final ArrayMap<IBinder, ArrayList<Animator>> mAnimations = new ArrayMap<>(); public FreeformTaskTransitionHandler( ShellInit shellInit, Transitions transitions, WindowDecorViewModel windowDecorViewModel) { Context context, WindowDecorViewModel windowDecorViewModel, DisplayController displayController, ShellExecutor mainExecutor, ShellExecutor animExecutor) { mTransitions = transitions; mContext = context; mWindowDecorViewModel = windowDecorViewModel; mDisplayController = displayController; mMainExecutor = mainExecutor; mAnimExecutor = animExecutor; if (Transitions.ENABLE_SHELL_TRANSITIONS) { shellInit.addInitCallback(this::onInit, this); } Loading Loading @@ -103,6 +125,14 @@ public class FreeformTaskTransitionHandler @NonNull SurfaceControl.Transaction finishT, @NonNull Transitions.TransitionFinishCallback finishCallback) { boolean transitionHandled = false; final ArrayList<Animator> animations = new ArrayList<>(); final Runnable onAnimFinish = () -> { if (!animations.isEmpty()) return; mMainExecutor.execute(() -> { mAnimations.remove(transition); finishCallback.onTransitionFinished(null /* wct */, null /* wctCB */); }); }; for (TransitionInfo.Change change : info.getChanges()) { if ((change.getFlags() & TransitionInfo.FLAG_IS_WALLPAPER) != 0) { continue; Loading @@ -121,21 +151,45 @@ public class FreeformTaskTransitionHandler case WindowManager.TRANSIT_TO_BACK: transitionHandled |= startMinimizeTransition(transition); break; case WindowManager.TRANSIT_CLOSE: if (change.getTaskInfo().getWindowingMode() == WINDOWING_MODE_FREEFORM) { transitionHandled |= startCloseTransition(transition, change, finishT, animations, onAnimFinish); } break; } } mPendingTransitionTokens.remove(transition); if (!transitionHandled) { return false; } mAnimations.put(transition, animations); // startT must be applied before animations start. startT.apply(); mTransitions.getMainExecutor().execute( () -> finishCallback.onTransitionFinished(null, null)); mAnimExecutor.execute(() -> { for (Animator anim : animations) { anim.start(); } }); // Run this here in case no animators are created. onAnimFinish.run(); mPendingTransitionTokens.remove(transition); return true; } @Override public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget, @NonNull Transitions.TransitionFinishCallback finishCallback) { ArrayList<Animator> animations = mAnimations.get(mergeTarget); if (animations == null) return; mAnimExecutor.execute(() -> { for (Animator anim : animations) { anim.end(); } }); } private boolean startChangeTransition( IBinder transition, int type, Loading Loading @@ -165,6 +219,36 @@ public class FreeformTaskTransitionHandler return mPendingTransitionTokens.contains(transition); } private boolean startCloseTransition(IBinder transition, TransitionInfo.Change change, SurfaceControl.Transaction finishT, ArrayList<Animator> animations, Runnable onAnimFinish) { if (!mPendingTransitionTokens.contains(transition)) return false; int screenHeight = mDisplayController .getDisplayLayout(change.getTaskInfo().displayId).height(); ValueAnimator animator = new ValueAnimator(); animator.setDuration(CLOSE_ANIM_DURATION) .setFloatValues(0f, 1f); SurfaceControl.Transaction t = new SurfaceControl.Transaction(); SurfaceControl sc = change.getLeash(); finishT.hide(sc); Rect startBounds = new Rect(change.getTaskInfo().configuration.windowConfiguration .getBounds()); animator.addUpdateListener(animation -> { t.setPosition(sc, startBounds.left, startBounds.top + (animation.getAnimatedFraction() * screenHeight)); t.apply(); }); animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { animations.remove(animator); onAnimFinish.run(); } }); animations.add(animator); return true; } @Nullable @Override public WindowContainerTransaction handleRequest(@NonNull IBinder transition, Loading