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

Commit 8d9edd29 authored by Nicolo' Mazzucato's avatar Nicolo' Mazzucato
Browse files

Drive Launcher unfold animation from System UI

Before this cl, both Launcher and System UI processes were registering for hinge angle and device state (e.g. folded/unfolded) change events to calculate the current unfold animation progress. In some cases, launcher ui thread was busy, delaying the progress calculation from the hinge angle value (that was received ~at the same time by both processes). This resulted in launcher and sysui unfold animation not being synchronized in some cases.

With this cl, System UI process uses OverviewProxyService to send the unfold events to Launcher. In this way, both process always have the exact same progress (+- 1 frame)

This is currently guarded by a launcher flag, by default with the new behaviour, to allow devs to compare the experience and easily debug potential regressions.

Bug: 268490854
Test: Analysed perfetto trace + RemoteUnfoldTransitionProgressProviderTest + manual
Change-Id: If15fd6fe39abb3d922c5fdb327100206dfa3665d
parent 2e16aa87
Loading
Loading
Loading
Loading
+73 −30
Original line number Original line Diff line number Diff line
@@ -35,6 +35,7 @@ import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustom
import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE;
import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE;
import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE;
import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE;
import static com.android.launcher3.config.FeatureFlags.ENABLE_WIDGET_PICKER_DEPTH;
import static com.android.launcher3.config.FeatureFlags.ENABLE_WIDGET_PICKER_DEPTH;
import static com.android.launcher3.config.FeatureFlags.RECEIVE_UNFOLD_EVENTS_FROM_SYSUI;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP;
import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID;
import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID;
import static com.android.launcher3.popup.QuickstepSystemShortcut.getSplitSelectShortcutByPosition;
import static com.android.launcher3.popup.QuickstepSystemShortcut.getSplitSelectShortcutByPosition;
@@ -166,11 +167,13 @@ import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.unfold.RemoteUnfoldSharedComponent;
import com.android.systemui.unfold.UnfoldSharedComponent;
import com.android.systemui.unfold.UnfoldSharedComponent;
import com.android.systemui.unfold.UnfoldTransitionFactory;
import com.android.systemui.unfold.UnfoldTransitionFactory;
import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
import com.android.systemui.unfold.config.ResourceUnfoldTransitionConfig;
import com.android.systemui.unfold.config.ResourceUnfoldTransitionConfig;
import com.android.systemui.unfold.config.UnfoldTransitionConfig;
import com.android.systemui.unfold.config.UnfoldTransitionConfig;
import com.android.systemui.unfold.progress.RemoteUnfoldTransitionReceiver;
import com.android.systemui.unfold.system.ActivityManagerActivityTypeProvider;
import com.android.systemui.unfold.system.ActivityManagerActivityTypeProvider;
import com.android.systemui.unfold.system.DeviceStateManagerFoldProvider;
import com.android.systemui.unfold.system.DeviceStateManagerFoldProvider;
import com.android.systemui.unfold.updates.RotationChangeProvider;
import com.android.systemui.unfold.updates.RotationChangeProvider;
@@ -204,7 +207,6 @@ public class QuickstepLauncher extends Launcher {
    // Will be updated when dragging from taskbar.
    // Will be updated when dragging from taskbar.
    private @Nullable DragOptions mNextWorkspaceDragOptions = null;
    private @Nullable DragOptions mNextWorkspaceDragOptions = null;
    private @Nullable UnfoldTransitionProgressProvider mUnfoldTransitionProgressProvider;
    private @Nullable UnfoldTransitionProgressProvider mUnfoldTransitionProgressProvider;
    private @Nullable RotationChangeProvider mRotationChangeProvider;
    private @Nullable LauncherUnfoldAnimationController mLauncherUnfoldAnimationController;
    private @Nullable LauncherUnfoldAnimationController mLauncherUnfoldAnimationController;


    private SplitSelectStateController mSplitSelectStateController;
    private SplitSelectStateController mSplitSelectStateController;
@@ -844,13 +846,24 @@ public class QuickstepLauncher extends Launcher {
    private void initUnfoldTransitionProgressProvider() {
    private void initUnfoldTransitionProgressProvider() {
        final UnfoldTransitionConfig config = new ResourceUnfoldTransitionConfig();
        final UnfoldTransitionConfig config = new ResourceUnfoldTransitionConfig();
        if (config.isEnabled()) {
        if (config.isEnabled()) {
            if (RECEIVE_UNFOLD_EVENTS_FROM_SYSUI.get()) {
                initRemotelyCalculatedUnfoldAnimation(config);
            } else {
                initLocallyCalculatedUnfoldAnimation(config);
            }

        }
    }

    /** Registers hinge angle listener and calculates the animation progress in this process. */
    private void initLocallyCalculatedUnfoldAnimation(UnfoldTransitionConfig config) {
        UnfoldSharedComponent unfoldComponent =
        UnfoldSharedComponent unfoldComponent =
                UnfoldTransitionFactory.createUnfoldSharedComponent(
                UnfoldTransitionFactory.createUnfoldSharedComponent(
                        /* context= */ this,
                        /* context= */ this,
                        config,
                        config,
                        ProxyScreenStatusProvider.INSTANCE,
                        ProxyScreenStatusProvider.INSTANCE,
                        new DeviceStateManagerFoldProvider(
                        new DeviceStateManagerFoldProvider(
                                    getSystemService(DeviceStateManager.class), /* context */this),
                                getSystemService(DeviceStateManager.class), /* context= */ this),
                        new ActivityManagerActivityTypeProvider(
                        new ActivityManagerActivityTypeProvider(
                                getSystemService(ActivityManager.class)),
                                getSystemService(ActivityManager.class)),
                        getSystemService(SensorManager.class),
                        getSystemService(SensorManager.class),
@@ -866,15 +879,45 @@ public class QuickstepLauncher extends Launcher {
                        "Trying to create UnfoldTransitionProgressProvider when the "
                        "Trying to create UnfoldTransitionProgressProvider when the "
                                + "transition is disabled"));
                                + "transition is disabled"));


            mRotationChangeProvider = unfoldComponent.getRotationChangeProvider();
        initUnfoldAnimationController(mUnfoldTransitionProgressProvider,
                unfoldComponent.getRotationChangeProvider());
    }

    /** Receives animation progress from sysui process. */
    private void initRemotelyCalculatedUnfoldAnimation(UnfoldTransitionConfig config) {
        RemoteUnfoldSharedComponent unfoldComponent =
                UnfoldTransitionFactory.createRemoteUnfoldSharedComponent(
                        /* context= */ this,
                        config,
                        getMainExecutor(),
                        /* backgroundExecutor= */ UI_HELPER_EXECUTOR,
                        /* tracingTagPrefix= */ "launcher",
                        WindowManagerGlobal.getWindowManagerService()
                );

        final RemoteUnfoldTransitionReceiver remoteUnfoldTransitionProgressProvider =
                unfoldComponent.getRemoteTransitionProgress().orElseThrow(
                        () -> new IllegalStateException(
                                "Trying to create getRemoteTransitionProgress when the transition "
                                        + "is disabled"));
        mUnfoldTransitionProgressProvider = remoteUnfoldTransitionProgressProvider;

        SystemUiProxy.INSTANCE.get(this).setUnfoldAnimationListener(
                remoteUnfoldTransitionProgressProvider);

        initUnfoldAnimationController(mUnfoldTransitionProgressProvider,
                unfoldComponent.getRotationChangeProvider());
    }

    private void initUnfoldAnimationController(UnfoldTransitionProgressProvider progressProvider,
            RotationChangeProvider rotationChangeProvider) {
        mLauncherUnfoldAnimationController = new LauncherUnfoldAnimationController(
        mLauncherUnfoldAnimationController = new LauncherUnfoldAnimationController(
                /* launcher= */ this,
                /* launcher= */ this,
                getWindowManager(),
                getWindowManager(),
                    mUnfoldTransitionProgressProvider,
                progressProvider,
                    mRotationChangeProvider
                rotationChangeProvider
        );
        );
    }
    }
    }


    public void setTaskbarUIController(LauncherTaskbarUIController taskbarUIController) {
    public void setTaskbarUIController(LauncherTaskbarUIController taskbarUIController) {
        mTaskbarUIController = taskbarUIController;
        mTaskbarUIController = taskbarUIController;
+29 −2
Original line number Original line Diff line number Diff line
@@ -57,6 +57,8 @@ import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.system.smartspace.ILauncherUnlockAnimationController;
import com.android.systemui.shared.system.smartspace.ILauncherUnlockAnimationController;
import com.android.systemui.shared.system.smartspace.ISysuiUnlockAnimationController;
import com.android.systemui.shared.system.smartspace.ISysuiUnlockAnimationController;
import com.android.systemui.shared.system.smartspace.SmartspaceState;
import com.android.systemui.shared.system.smartspace.SmartspaceState;
import com.android.systemui.unfold.progress.IUnfoldAnimation;
import com.android.systemui.unfold.progress.IUnfoldTransitionListener;
import com.android.wm.shell.back.IBackAnimation;
import com.android.wm.shell.back.IBackAnimation;
import com.android.wm.shell.desktopmode.IDesktopMode;
import com.android.wm.shell.desktopmode.IDesktopMode;
import com.android.wm.shell.onehanded.IOneHanded;
import com.android.wm.shell.onehanded.IOneHanded;
@@ -96,6 +98,7 @@ public class SystemUiProxy implements ISystemUiProxy {
    private IRecentTasks mRecentTasks;
    private IRecentTasks mRecentTasks;
    private IBackAnimation mBackAnimation;
    private IBackAnimation mBackAnimation;
    private IDesktopMode mDesktopMode;
    private IDesktopMode mDesktopMode;
    private IUnfoldAnimation mUnfoldAnimation;
    private final DeathRecipient mSystemUiProxyDeathRecipient = () -> {
    private final DeathRecipient mSystemUiProxyDeathRecipient = () -> {
        MAIN_EXECUTOR.execute(() -> clearProxy());
        MAIN_EXECUTOR.execute(() -> clearProxy());
    };
    };
@@ -109,6 +112,7 @@ public class SystemUiProxy implements ISystemUiProxy {
    private IStartingWindowListener mStartingWindowListener;
    private IStartingWindowListener mStartingWindowListener;
    private ILauncherUnlockAnimationController mLauncherUnlockAnimationController;
    private ILauncherUnlockAnimationController mLauncherUnlockAnimationController;
    private IRecentTasksListener mRecentTasksListener;
    private IRecentTasksListener mRecentTasksListener;
    private IUnfoldTransitionListener mUnfoldAnimationListener;
    private final LinkedHashMap<RemoteTransition, TransitionFilter> mRemoteTransitions =
    private final LinkedHashMap<RemoteTransition, TransitionFilter> mRemoteTransitions =
            new LinkedHashMap<>();
            new LinkedHashMap<>();
    private IOnBackInvokedCallback mBackToLauncherCallback;
    private IOnBackInvokedCallback mBackToLauncherCallback;
@@ -171,7 +175,8 @@ public class SystemUiProxy implements ISystemUiProxy {
            IOneHanded oneHanded, IShellTransitions shellTransitions,
            IOneHanded oneHanded, IShellTransitions shellTransitions,
            IStartingWindow startingWindow, IRecentTasks recentTasks,
            IStartingWindow startingWindow, IRecentTasks recentTasks,
            ISysuiUnlockAnimationController sysuiUnlockAnimationController,
            ISysuiUnlockAnimationController sysuiUnlockAnimationController,
            IBackAnimation backAnimation, IDesktopMode desktopMode) {
            IBackAnimation backAnimation, IDesktopMode desktopMode,
            IUnfoldAnimation unfoldAnimation) {
        unlinkToDeath();
        unlinkToDeath();
        mSystemUiProxy = proxy;
        mSystemUiProxy = proxy;
        mPip = pip;
        mPip = pip;
@@ -183,6 +188,7 @@ public class SystemUiProxy implements ISystemUiProxy {
        mRecentTasks = recentTasks;
        mRecentTasks = recentTasks;
        mBackAnimation = backAnimation;
        mBackAnimation = backAnimation;
        mDesktopMode = desktopMode;
        mDesktopMode = desktopMode;
        mUnfoldAnimation = unfoldAnimation;
        linkToDeath();
        linkToDeath();
        // re-attach the listeners once missing due to setProxy has not been initialized yet.
        // re-attach the listeners once missing due to setProxy has not been initialized yet.
        if (mPipAnimationListener != null && mPip != null) {
        if (mPipAnimationListener != null && mPip != null) {
@@ -204,10 +210,13 @@ public class SystemUiProxy implements ISystemUiProxy {
        if (mBackAnimation != null && mBackToLauncherCallback != null) {
        if (mBackAnimation != null && mBackToLauncherCallback != null) {
            setBackToLauncherCallback(mBackToLauncherCallback);
            setBackToLauncherCallback(mBackToLauncherCallback);
        }
        }
        if (unfoldAnimation != null && mUnfoldAnimationListener != null) {
            setUnfoldAnimationListener(mUnfoldAnimationListener);
        }
    }
    }


    public void clearProxy() {
    public void clearProxy() {
        setProxy(null, null, null, null, null, null, null, null, null, null);
        setProxy(null, null, null, null, null, null, null, null, null, null, null);
    }
    }


    // TODO(141886704): Find a way to remove this
    // TODO(141886704): Find a way to remove this
@@ -961,4 +970,22 @@ public class SystemUiProxy implements ISystemUiProxy {
        }
        }
        return 0;
        return 0;
    }
    }

    //
    // Unfold transition
    //

    /** Sets the unfold animation lister to sysui. */
    public void setUnfoldAnimationListener(IUnfoldTransitionListener callback) {
        mUnfoldAnimationListener = callback;
        if (mUnfoldAnimation == null) {
            return;
        }
        try {
            Log.d(TAG, "Registering unfold animation receiver");
            mUnfoldAnimation.setListener(callback);
        } catch (RemoteException e) {
            Log.e(TAG, "Failed call setUnfoldAnimationListener", e);
        }
    }
}
}
+6 −1
Original line number Original line Diff line number Diff line
@@ -28,6 +28,7 @@ import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent
import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.MOTION_UP;
import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.MOTION_UP;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_UNFOLD_ANIMATION_FORWARDER;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_UNLOCK_ANIMATION_CONTROLLER;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_UNLOCK_ANIMATION_CONTROLLER;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_FREEFORM_ACTIVE_IN_DESKTOP_MODE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_FREEFORM_ACTIVE_IN_DESKTOP_MODE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
@@ -114,6 +115,7 @@ import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.InputMonitorCompat;
import com.android.systemui.shared.system.InputMonitorCompat;
import com.android.systemui.shared.system.smartspace.ISysuiUnlockAnimationController;
import com.android.systemui.shared.system.smartspace.ISysuiUnlockAnimationController;
import com.android.systemui.shared.tracing.ProtoTraceable;
import com.android.systemui.shared.tracing.ProtoTraceable;
import com.android.systemui.unfold.progress.IUnfoldAnimation;
import com.android.wm.shell.back.IBackAnimation;
import com.android.wm.shell.back.IBackAnimation;
import com.android.wm.shell.desktopmode.IDesktopMode;
import com.android.wm.shell.desktopmode.IDesktopMode;
import com.android.wm.shell.onehanded.IOneHanded;
import com.android.wm.shell.onehanded.IOneHanded;
@@ -174,10 +176,13 @@ public class TouchInteractionService extends Service
                    bundle.getBinder(KEY_EXTRA_SHELL_BACK_ANIMATION));
                    bundle.getBinder(KEY_EXTRA_SHELL_BACK_ANIMATION));
            IDesktopMode desktopMode = IDesktopMode.Stub.asInterface(
            IDesktopMode desktopMode = IDesktopMode.Stub.asInterface(
                    bundle.getBinder(KEY_EXTRA_SHELL_DESKTOP_MODE));
                    bundle.getBinder(KEY_EXTRA_SHELL_DESKTOP_MODE));
            IUnfoldAnimation unfoldTransition = IUnfoldAnimation.Stub.asInterface(
                    bundle.getBinder(KEY_EXTRA_UNFOLD_ANIMATION_FORWARDER));
            MAIN_EXECUTOR.execute(() -> {
            MAIN_EXECUTOR.execute(() -> {
                SystemUiProxy.INSTANCE.get(TouchInteractionService.this).setProxy(proxy, pip,
                SystemUiProxy.INSTANCE.get(TouchInteractionService.this).setProxy(proxy, pip,
                        splitscreen, onehanded, shellTransitions, startingWindow,
                        splitscreen, onehanded, shellTransitions, startingWindow,
                        recentTasks, launcherUnlockAnimationController, backAnimation, desktopMode);
                        recentTasks, launcherUnlockAnimationController, backAnimation, desktopMode,
                        unfoldTransition);
                TouchInteractionService.this.initInputMonitor("TISBinder#onInitialize()");
                TouchInteractionService.this.initInputMonitor("TISBinder#onInitialize()");
                preloadOverview(true /* fromInit */);
                preloadOverview(true /* fromInit */);
            });
            });
+0 −1
Original line number Original line Diff line number Diff line
@@ -56,7 +56,6 @@ public abstract class BaseUnfoldMoveFromCenterAnimator implements TransitionProg
        mAnimationInProgress = true;
        mAnimationInProgress = true;
        mMoveFromCenterAnimation.updateDisplayProperties();
        mMoveFromCenterAnimation.updateDisplayProperties();
        onPrepareViewsForAnimation();
        onPrepareViewsForAnimation();
        onTransitionProgress(0f);
        mRotationChangeProvider.addCallback(mRotationListener);
        mRotationChangeProvider.addCallback(mRotationListener);
    }
    }


+5 −0
Original line number Original line Diff line number Diff line
@@ -394,6 +394,11 @@ public final class FeatureFlags {
            "ENABLE_GRID_ONLY_OVERVIEW", false,
            "ENABLE_GRID_ONLY_OVERVIEW", false,
            "Enable a grid-only overview without a focused task.");
            "Enable a grid-only overview without a focused task.");


    public static final BooleanFlag RECEIVE_UNFOLD_EVENTS_FROM_SYSUI = getDebugFlag(
            "RECEIVE_UNFOLD_EVENTS_FROM_SYSUI", true,
            "Enables receiving unfold animation events from sysui instead of calculating "
                    + "them in launcher process using hinge sensor values.");

    public static void initialize(Context context) {
    public static void initialize(Context context) {
        synchronized (sDebugFlags) {
        synchronized (sDebugFlags) {
            for (DebugFlag flag : sDebugFlags) {
            for (DebugFlag flag : sDebugFlags) {