Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 20983818 authored by Luca Zuccarini's avatar Luca Zuccarini
Browse files

[Toast] Introduce SysUI's animation library to the transition manager.

Bug: 250588519
Test: manual, see videos in bug
Change-Id: Iccc440c95ecc14d39e35d911798e239b698b950a
parent 91b9de1f
Loading
Loading
Loading
Loading
+98 −5
Original line number Diff line number Diff line
@@ -89,6 +89,7 @@ import android.provider.Settings;
import android.util.Pair;
import android.util.Size;
import android.view.CrossWindowBlurListeners;
import android.view.IRemoteAnimationFinishedCallback;
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationDefinition;
import android.view.RemoteAnimationTarget;
@@ -114,6 +115,7 @@ import com.android.launcher3.anim.AnimatorListeners;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.icons.FastBitmapDrawable;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.shortcuts.DeepShortcutView;
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.taskbar.LauncherTaskbarUIController;
@@ -143,6 +145,9 @@ import com.android.quickstep.util.SurfaceTransactionApplier;
import com.android.quickstep.util.WorkspaceRevealAnim;
import com.android.quickstep.views.FloatingWidgetView;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.animation.DelegateLaunchAnimatorController;
import com.android.systemui.animation.RemoteAnimationDelegate;
import com.android.systemui.shared.system.BlurUtils;
import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
import com.android.systemui.shared.system.QuickStepContract;
@@ -222,7 +227,6 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
    private RemoteAnimationProvider mRemoteAnimationProvider;
    // Strong refs to runners which are cleared when the launcher activity is destroyed
    private RemoteAnimationFactory mWallpaperOpenRunner;
    private RemoteAnimationFactory mAppLaunchRunner;
    private RemoteAnimationFactory mKeyguardGoingAwayRunner;

    private RemoteAnimationFactory mWallpaperOpenTransitionRunner;
@@ -291,9 +295,18 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
    public ActivityOptionsWrapper getActivityLaunchOptions(View v) {
        boolean fromRecents = isLaunchingFromRecents(v, null /* targets */);
        RunnableList onEndCallback = new RunnableList();
        mAppLaunchRunner = new AppLaunchAnimationRunner(v, onEndCallback);

        RemoteAnimationFactory delegateRunner = new AppLaunchAnimationRunner(v, onEndCallback);
        ItemInfo tag = (ItemInfo) v.getTag();
        if (tag != null && tag.shouldUseBackgroundAnimation()) {
            ContainerAnimationRunner containerAnimationRunner =
                    ContainerAnimationRunner.from(v, mStartingWindowListener);
            if (containerAnimationRunner != null) {
                delegateRunner = containerAnimationRunner;
            }
        }
        RemoteAnimationRunnerCompat runner = new LauncherAnimationRunner(
                mHandler, mAppLaunchRunner, true /* startAtFrontOfQueue */);
                mHandler, delegateRunner, true /* startAtFrontOfQueue */);

        // Note that this duration is a guess as we do not know if the animation will be a
        // recents launch or not for sure until we know the opening app targets.
@@ -1160,7 +1173,6 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
            // Also clear strong references to the runners registered with the remote animation
            // definition so we don't have to wait for the system gc
            mWallpaperOpenRunner = null;
            mAppLaunchRunner = null;
            mKeyguardGoingAwayRunner = null;
        }
    }
@@ -1754,6 +1766,79 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
        }
    }

    /** Remote animation runner to launch an app using System UI's animation library. */
    private static class ContainerAnimationRunner implements RemoteAnimationFactory {

        /** The delegate runner that handles the actual animation. */
        private final RemoteAnimationDelegate<IRemoteAnimationFinishedCallback> mDelegate;

        private ContainerAnimationRunner(
                RemoteAnimationDelegate<IRemoteAnimationFinishedCallback> delegate) {
            mDelegate = delegate;
        }

        @Nullable
        private static ContainerAnimationRunner from(
                View v, StartingWindowListener startingWindowListener) {
            View viewToUse = findViewWithBackground(v);
            if (viewToUse == null) {
                viewToUse = v;
            }

            // TODO(b/265134143): create a CUJ type for interaction jank monitoring.
            ActivityLaunchAnimator.Controller controllerDelegate =
                    ActivityLaunchAnimator.Controller.fromView(viewToUse, null /* cujType */);

            if (controllerDelegate == null) {
                return null;
            }

            // This wrapper allows us to override the default value, telling the controller that the
            // current window is below the animating window.
            ActivityLaunchAnimator.Controller controller =
                    new DelegateLaunchAnimatorController(controllerDelegate) {
                        @Override
                        public boolean isBelowAnimatingWindow() {
                            return true;
                        }
                    };

            ActivityLaunchAnimator.Callback callback = task -> ColorUtils.setAlphaComponent(
                    startingWindowListener.getBackgroundColor(), 255);

            return new ContainerAnimationRunner(
                    new ActivityLaunchAnimator.AnimationDelegate(controller, callback));
        }

        /** Finds the closest parent of [view] (inclusive) with a background drawable. */
        @Nullable
        private static View findViewWithBackground(View view) {
            View current = view;
            while (current.getBackground() == null) {
                if (!(current.getParent() instanceof View)) {
                    return null;
                }

                current = (View) view.getParent();
            }

            return current;
        }

        @Override
        public void onAnimationStart(int transit, RemoteAnimationTarget[] appTargets,
                RemoteAnimationTarget[] wallpaperTargets, RemoteAnimationTarget[] nonAppTargets,
                LauncherAnimationRunner.AnimationResult result) {
            mDelegate.onAnimationStart(
                    transit, appTargets, wallpaperTargets, nonAppTargets, result);
        }

        @Override
        public void onAnimationCancelled(boolean isKeyguardOccluded) {
            mDelegate.onAnimationCancelled(isKeyguardOccluded);
        }
    }

    /**
     * Class that holds all the variables for the app open animation.
     */
@@ -1822,8 +1907,9 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
        }
    }

    private static class StartingWindowListener extends IStartingWindowListener.Stub {
    private class StartingWindowListener extends IStartingWindowListener.Stub {
        private QuickstepTransitionManager mTransitionManager;
        private int mBackgroundColor;

        public void setTransitionManager(QuickstepTransitionManager transitionManager) {
            mTransitionManager = transitionManager;
@@ -1832,6 +1918,13 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
        @Override
        public void onTaskLaunching(int taskId, int supportedType, int color) {
            mTransitionManager.mTaskStartParams.put(taskId, Pair.create(supportedType, color));
            mBackgroundColor = color;
        }

        public int getBackgroundColor() {
            return mBackgroundColor == Color.TRANSPARENT
                    ? mLauncher.getScrimView().getBackgroundColor()
                    : mBackgroundColor;
        }
    }

+14 −0
Original line number Diff line number Diff line
@@ -29,6 +29,20 @@ import com.android.launcher3.model.data.ItemInfo;
 */
public class LauncherSettings {

    /**
     * Types of animations.
     */
    public static final class Animation {
        /**
         * The default animation for a given view/item info type.
         */
        public static final int DEFAULT = 0;
        /**
         * An animation using the view's background.
         */
        public static final int VIEW_BACKGROUND = 1;
    }

    /**
     * Favorites.
     */
+1 −1
Original line number Diff line number Diff line
@@ -272,7 +272,7 @@ public final class FeatureFlags {

    public static final BooleanFlag ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION = new DeviceFlag(
            "ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION", false,
            "Enable option to launch search results using the new standardized transitions");
            "Enable option to launch search results using the new view container transitions");

    public static final BooleanFlag TWO_PREDICTED_ROWS_ALL_APPS_SEARCH = new DeviceFlag(
            "TWO_PREDICTED_ROWS_ALL_APPS_SEARCH", false,
+18 −0
Original line number Diff line number Diff line
@@ -47,8 +47,10 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherSettings.Animation;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.Workspace;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.logger.LauncherAtom.AllAppsContainer;
import com.android.launcher3.logger.LauncherAtom.ContainerInfo;
@@ -93,6 +95,12 @@ public class ItemInfo {
     */
    public int itemType;

    /**
     * One of {@link Animation#DEFAULT},
     * {@link Animation#VIEW_BACKGROUND}.
     */
    public int animationType = Animation.DEFAULT;

    /**
     * The id of the container that holds this item. For the desktop, this will be
     * {@link Favorites#CONTAINER_DESKTOP}. For the all applications folder it
@@ -185,6 +193,7 @@ public class ItemInfo {
        rank = info.rank;
        screenId = info.screenId;
        itemType = info.itemType;
        animationType = info.animationType;
        container = info.container;
        user = info.user;
        contentDescription = info.contentDescription;
@@ -297,6 +306,15 @@ public class ItemInfo {
        return container == CONTAINER_HOTSEAT_PREDICTION || container == CONTAINER_PREDICTION;
    }

    /**
     * Returns whether this item should use the background animation.
     */
    public boolean shouldUseBackgroundAnimation() {
        return animationType == LauncherSettings.Animation.VIEW_BACKGROUND
                && FeatureFlags.ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES.get()
                && FeatureFlags.ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION.get();
    }

    /**
     * Creates {@link LauncherAtom.ItemInfo} with important fields and parent container info.
     */
+2 −1
Original line number Diff line number Diff line
@@ -343,7 +343,8 @@ public class ItemClickHandler {
                return;
            }
        }
        if (v != null && launcher.supportsAdaptiveIconAnimation(v)) {
        if (v != null && launcher.supportsAdaptiveIconAnimation(v)
                && !item.shouldUseBackgroundAnimation()) {
            // Preload the icon to reduce latency b/w swapping the floating view with the original.
            FloatingIconView.fetchIcon(launcher, v, item, true /* isOpening */);
        }
Loading