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

Commit aad3a8e3 authored by Matt Sziklay's avatar Matt Sziklay Committed by Android (Google) Code Review
Browse files

Merge "Allow split select transition from desktop mode." into udc-qpr-dev

parents 18dd2008 95c85034
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.LauncherState.OVERVIEW_MODAL_TASK;
import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT;
import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent;
import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_DESKTOP_TO_WORKSPACE;
import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE;
import static com.android.launcher3.config.FeatureFlags.RECEIVE_UNFOLD_EVENTS_FROM_SYSUI;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP;
@@ -261,6 +262,7 @@ public class QuickstepLauncher extends Launcher {
        mDesktopVisibilityController = new DesktopVisibilityController(this);
        if (DesktopTaskView.DESKTOP_MODE_SUPPORTED) {
            mDesktopVisibilityController.registerSystemUiListener();
            mSplitSelectStateController.initSplitFromDesktopController(this);
        }
        mHotseatPredictionController = new HotseatPredictionController(this);

+36 −0
Original line number Diff line number Diff line
@@ -84,6 +84,7 @@ import com.android.wm.shell.recents.IRecentTasks;
import com.android.wm.shell.recents.IRecentTasksListener;
import com.android.wm.shell.splitscreen.ISplitScreen;
import com.android.wm.shell.splitscreen.ISplitScreenListener;
import com.android.wm.shell.splitscreen.ISplitSelectListener;
import com.android.wm.shell.startingsurface.IStartingWindow;
import com.android.wm.shell.startingsurface.IStartingWindowListener;
import com.android.wm.shell.transition.IShellTransitions;
@@ -128,6 +129,7 @@ public class SystemUiProxy implements ISystemUiProxy {
    private IPipAnimationListener mPipAnimationListener;
    private IBubblesListener mBubblesListener;
    private ISplitScreenListener mSplitScreenListener;
    private ISplitSelectListener mSplitSelectListener;
    private IStartingWindowListener mStartingWindowListener;
    private ILauncherUnlockAnimationController mLauncherUnlockAnimationController;
    private IRecentTasksListener mRecentTasksListener;
@@ -239,6 +241,7 @@ public class SystemUiProxy implements ISystemUiProxy {
        setPipAnimationListener(mPipAnimationListener);
        setBubblesListener(mBubblesListener);
        registerSplitScreenListener(mSplitScreenListener);
        registerSplitSelectListener(mSplitSelectListener);
        setStartingWindowListener(mStartingWindowListener);
        setLauncherUnlockAnimationController(mLauncherUnlockAnimationController);
        new LinkedHashMap<>(mRemoteTransitions).forEach(this::registerRemoteTransition);
@@ -740,6 +743,28 @@ public class SystemUiProxy implements ISystemUiProxy {
        mSplitScreenListener = null;
    }

    public void registerSplitSelectListener(ISplitSelectListener listener) {
        if (mSplitScreen != null) {
            try {
                mSplitScreen.registerSplitSelectListener(listener);
            } catch (RemoteException e) {
                Log.w(TAG, "Failed call registerSplitSelectListener");
            }
        }
        mSplitSelectListener = listener;
    }

    public void unregisterSplitSelectListener(ISplitSelectListener listener) {
        if (mSplitScreen != null) {
            try {
                mSplitScreen.unregisterSplitSelectListener(listener);
            } catch (RemoteException e) {
                Log.w(TAG, "Failed call unregisterSplitSelectListener");
            }
        }
        mSplitSelectListener = null;
    }

    /** Start multiple tasks in split-screen simultaneously. */
    public void startTasks(int taskId1, Bundle options1, int taskId2, Bundle options2,
            @SplitConfigurationOptions.StagePosition int splitPosition, float splitRatio,
@@ -1281,6 +1306,17 @@ public class SystemUiProxy implements ISystemUiProxy {
        }
    }

    /** Perform cleanup transactions after animation to split select is complete */
    public void onDesktopSplitSelectAnimComplete(ActivityManager.RunningTaskInfo taskInfo) {
        if (mDesktopMode != null) {
            try {
                mDesktopMode.onDesktopSplitSelectAnimComplete(taskInfo);
            } catch (RemoteException e) {
                Log.w(TAG, "Failed call onDesktopSplitSelectAnimComplete", e);
            }
        }
    }

    //
    // Unfold transition
    //
+142 −0
Original line number Diff line number Diff line
@@ -17,10 +17,14 @@
package com.android.quickstep.util;

import static com.android.launcher3.Utilities.postAsyncCallback;
import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_DESKTOP_TO_WORKSPACE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_DESKTOP_MODE_SPLIT_RIGHT_BOTTOM;
import static com.android.launcher3.testing.shared.TestProtocol.LAUNCH_SPLIT_PAIR;
import static com.android.launcher3.testing.shared.TestProtocol.testLogD;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.launcher3.util.SplitConfigurationOptions.DEFAULT_SPLIT_RATIO;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_PENDINGINTENT_PENDINGINTENT;
import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_PENDINGINTENT_TASK;
import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_SHORTCUT_TASK;
@@ -31,6 +35,8 @@ import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_TASK_PENDIN
import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_TASK_SHORTCUT;
import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_TASK_TASK;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.ActivityOptions;
@@ -38,11 +44,16 @@ import android.app.ActivityThread;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ShortcutInfo;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.util.Log;
import android.util.Pair;
@@ -57,7 +68,11 @@ import android.window.TransitionInfo;
import androidx.annotation.Nullable;

import com.android.internal.logging.InstanceId;
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.icons.IconProvider;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.statehandlers.DepthController;
@@ -66,6 +81,11 @@ import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
import com.android.quickstep.OverviewComponentObserver;
import com.android.quickstep.RecentsAnimationCallbacks;
import com.android.quickstep.RecentsAnimationController;
import com.android.quickstep.RecentsAnimationDeviceState;
import com.android.quickstep.RecentsAnimationTargets;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.SplitSelectionListener;
import com.android.quickstep.SystemUiProxy;
@@ -74,8 +94,11 @@ import com.android.quickstep.TaskViewUtils;
import com.android.quickstep.views.FloatingTaskView;
import com.android.quickstep.views.GroupedTaskView;
import com.android.quickstep.views.SplitInstructionsView;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
import com.android.wm.shell.splitscreen.ISplitSelectListener;

import java.io.PrintWriter;
import java.util.ArrayList;
@@ -99,6 +122,7 @@ public class SplitSelectStateController {
    private final StatsLogManager mStatsLogManager;
    private final SystemUiProxy mSystemUiProxy;
    private final StateManager mStateManager;
    private SplitFromDesktopController mSplitFromDesktopController;
    @Nullable
    private DepthController mDepthController;
    private boolean mRecentsAnimationRunning;
@@ -476,6 +500,14 @@ public class SplitSelectStateController {
        }
    }

    public void initSplitFromDesktopController(Launcher launcher) {
        mSplitFromDesktopController = new SplitFromDesktopController(launcher);
    }

    public void enterSplitFromDesktop(ActivityManager.RunningTaskInfo taskInfo) {
        mSplitFromDesktopController.enterSplitSelect(taskInfo);
    }

    private RemoteTransition getShellRemoteTransition(int firstTaskId, int secondTaskId,
            @Nullable Consumer<Boolean> callback, String transitionName) {
        final RemoteSplitLaunchTransitionRunner animationRunner =
@@ -686,4 +718,114 @@ public class SplitSelectStateController {
            mSplitSelectDataHolder.dump(prefix, writer);
        }
    }

    public class SplitFromDesktopController {
        private static final String TAG = "SplitFromDesktopController";

        private final Launcher mLauncher;
        private final OverviewComponentObserver mOverviewComponentObserver;
        private final int mSplitPlaceholderSize;
        private final int mSplitPlaceholderInset;
        private ActivityManager.RunningTaskInfo mTaskInfo;
        private ISplitSelectListener mSplitSelectListener;
        private Drawable mAppIcon;

        public SplitFromDesktopController(Launcher launcher) {
            mLauncher = launcher;
            RecentsAnimationDeviceState deviceState = new RecentsAnimationDeviceState(
                    launcher.getApplicationContext());
            mOverviewComponentObserver =
                    new OverviewComponentObserver(launcher.getApplicationContext(), deviceState);
            mSplitPlaceholderSize = mLauncher.getResources().getDimensionPixelSize(
                    R.dimen.split_placeholder_size);
            mSplitPlaceholderInset = mLauncher.getResources().getDimensionPixelSize(
                    R.dimen.split_placeholder_inset);
            mSplitSelectListener = new ISplitSelectListener.Stub() {
                @Override
                public boolean onRequestSplitSelect(ActivityManager.RunningTaskInfo taskInfo) {
                    if (!ENABLE_SPLIT_FROM_DESKTOP_TO_WORKSPACE.get()) return false;
                    MAIN_EXECUTOR.execute(() -> enterSplitSelect(taskInfo));
                    return true;
                }
            };
            SystemUiProxy.INSTANCE.get(mLauncher).registerSplitSelectListener(mSplitSelectListener);
        }

        /**
         * Enter split select from desktop mode.
         * @param taskInfo the desktop task to move to split stage
         */
        public void enterSplitSelect(ActivityManager.RunningTaskInfo taskInfo) {
            mTaskInfo = taskInfo;
            String packageName = mTaskInfo.realActivity.getPackageName();
            PackageManager pm = mLauncher.getApplicationContext().getPackageManager();
            IconProvider provider = new IconProvider(mLauncher.getApplicationContext());
            try {
                mAppIcon = provider.getIcon(pm.getActivityInfo(mTaskInfo.baseActivity,
                     PackageManager.ComponentInfoFlags.of(0)));
            } catch (PackageManager.NameNotFoundException e) {
                Log.w(TAG, "Package not found: " + packageName, e);
            }
            RecentsAnimationCallbacks callbacks = new RecentsAnimationCallbacks(
                    SystemUiProxy.INSTANCE.get(mLauncher.getApplicationContext()),
                    false /* allowMinimizeSplitScreen */);

            DesktopSplitRecentsAnimationListener listener =
                    new DesktopSplitRecentsAnimationListener();

            MAIN_EXECUTOR.execute(() -> {
                callbacks.addListener(listener);
                UI_HELPER_EXECUTOR.execute(
                        // Transition from app to enter stage split in launcher with
                        // recents animation.
                        () -> ActivityManagerWrapper.getInstance().startRecentsActivity(
                                mOverviewComponentObserver.getOverviewIntent(),
                                SystemClock.uptimeMillis(), callbacks, null, null));
            });
        }

        private class DesktopSplitRecentsAnimationListener implements
                RecentsAnimationCallbacks.RecentsAnimationListener {
            private final Rect mTempRect = new Rect();

            @Override
            public void onRecentsAnimationStart(RecentsAnimationController controller,
                    RecentsAnimationTargets targets) {
                setInitialTaskSelect(mTaskInfo, STAGE_POSITION_BOTTOM_OR_RIGHT,
                        null, LAUNCHER_DESKTOP_MODE_SPLIT_RIGHT_BOTTOM);

                RecentsView recentsView = mLauncher.getOverviewPanel();
                recentsView.getPagedOrientationHandler().getInitialSplitPlaceholderBounds(
                        mSplitPlaceholderSize, mSplitPlaceholderInset,
                        mLauncher.getDeviceProfile(), getActiveSplitStagePosition(), mTempRect);

                PendingAnimation anim = new PendingAnimation(
                        SplitAnimationTimings.TABLET_HOME_TO_SPLIT.getDuration());
                RectF startingTaskRect = new RectF(mTaskInfo.configuration.windowConfiguration
                        .getBounds());
                final FloatingTaskView floatingTaskView = FloatingTaskView.getFloatingTaskView(
                        mLauncher, mLauncher.getDragLayer(),
                        null /* thumbnail */,
                        mAppIcon, new RectF());
                floatingTaskView.setAlpha(1);
                floatingTaskView.addStagingAnimation(anim, startingTaskRect, mTempRect,
                        false /* fadeWithThumbnail */, true /* isStagedTask */);
                setFirstFloatingTaskView(floatingTaskView);

                anim.addListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationStart(Animator animation) {
                        controller.finish(true /* toRecents */, null /* onFinishComplete */,
                                false /* sendUserLeaveHint */);
                    }
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        SystemUiProxy.INSTANCE.get(mLauncher.getApplicationContext())
                                .onDesktopSplitSelectAnimComplete(mTaskInfo);
                    }
                });
                anim.buildAnim().start();
            }
        }
    }
}
+3 −1
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.quickstep.util;

import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_DESKTOP_TO_WORKSPACE;
import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_FULLSCREEN_WITH_KEYBOARD_SHORTCUTS;
import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE;

@@ -178,7 +179,8 @@ public class SplitToWorkspaceController {

    private boolean shouldIgnoreSecondSplitLaunch() {
        return (!ENABLE_SPLIT_FROM_FULLSCREEN_WITH_KEYBOARD_SHORTCUTS.get()
                && !ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get())
                && !ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()
                && !ENABLE_SPLIT_FROM_DESKTOP_TO_WORKSPACE.get())
                || !mController.isSplitSelectActive();
    }
}
+4 −0
Original line number Diff line number Diff line
@@ -370,6 +370,10 @@ public final class FeatureFlags {
            270393453, "ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE", TEAMFOOD,
            "Enable initiating split screen from workspace to workspace.");

    public static final BooleanFlag ENABLE_SPLIT_FROM_DESKTOP_TO_WORKSPACE = getDebugFlag(
            279586624, "ENABLE_SPLIT_FROM_DESKTOP_TO_WORKSPACE", DISABLED,
            "Enable initiating split screen from desktop mode to workspace.");

    public static final BooleanFlag ENABLE_TRACKPAD_GESTURE = getDebugFlag(271010401,
            "ENABLE_TRACKPAD_GESTURE", ENABLED, "Enables trackpad gesture.");

Loading