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

Commit 4eb58456 authored by Evan Rosky's avatar Evan Rosky
Browse files

Fix some incompatibilities of 3p launcher and recentstransition

Since Launcher talks to both recentstransition and WMCore via
binder, it can result in races. Because 3p launchers are treated
half like apps (to recents), launcher would use normal activity
calls to control the 3p launcher lifecycle. It would sometimes
launch the app AND set focus at similar times. Because setfocus
went through recentstransition, it could race and cause the
focus change to happen after the activity-launch which would
confuse recents. To fix this, add a special focus API for recents
which says "focus top task" since all recents really needs is
to tell WM to move focus to itself (transient launch defers
focus change until the animation requests it). By just focusing
"top" task, it should never result in a re-ordering but still
work for recents use-case.

Additionally, recentstransition was seeing 3p launcher as a
regular (non-home) task. This meant that it would treat a
non-committed gesture as a task-switch and "switch away"
from the 3p launcher. So this CL detects when the gesture
starts on 3p launcher and then uses that information to
categorize uncommit properly.

Bug: 277964651
Test: Use a 3p launcher (like Nova) and use gestures.
Change-Id: I6511db60c5a92d2fa4418b95369e069142b3a00c
parent 9188aa60
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -174,6 +174,9 @@ interface IActivityTaskManager {
    ActivityTaskManager.RootTaskInfo getFocusedRootTaskInfo();
    Rect getTaskBounds(int taskId);

    /** Focuses the top task on a display if it isn't already focused. Used for Recents. */
    void focusTopTask(int displayId);

    void cancelRecentsAnimation(boolean restoreHomeRootTaskPosition);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.UPDATE_LOCK_TASK_PACKAGES)")
    void updateLockTaskPackages(int userId, in String[] packages);
+25 −5
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.util.ArrayMap;
import android.util.Slog;
import android.view.Display;
import android.view.IRecentsAnimationController;
import android.view.IRecentsAnimationRunner;
import android.view.RemoteAnimationTarget;
@@ -219,6 +220,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
        private int mRecentsTaskId = -1;
        private TransitionInfo mInfo = null;
        private boolean mOpeningSeparateHome = false;
        private boolean mPausingSeparateHome = false;
        private ArrayMap<SurfaceControl, SurfaceControl> mLeashMap = null;
        private PictureInPictureSurfaceTransaction mPipTransaction = null;
        private IBinder mTransition = null;
@@ -407,6 +409,10 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
                        // raise closing (pausing) task to "above" layer so it isn't covered
                        t.setLayer(target.leash, info.getChanges().size() * 3 - i);
                        mPausingTasks.add(new TaskState(change, target.leash));
                        if (taskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
                            // This can only happen if we have a separate recents/home (3p launcher)
                            mPausingSeparateHome = true;
                        }
                        if (taskInfo.pictureInPictureParams != null
                                && taskInfo.pictureInPictureParams.isAutoEnterEnabled()) {
                            mPipTask = taskInfo.token;
@@ -657,6 +663,8 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
                            mFinishCB != null, enabled);
                    return;
                }
                final int displayId = mInfo.getRootCount() > 0 ? mInfo.getRoot(0).getDisplayId()
                        : Display.DEFAULT_DISPLAY;
                // transient launches don't receive focus automatically. Since we are taking over
                // the gesture now, take focus explicitly.
                // This also moves recents back to top if the user gestured before a switch
@@ -665,7 +673,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
                    ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                            "[%d] RecentsController.setInputConsumerEnabled: set focus to recents",
                            mInstanceId);
                    ActivityTaskManager.getService().setFocusedTask(mRecentsTaskId);
                    ActivityTaskManager.getService().focusTopTask(displayId);
                } catch (RemoteException e) {
                    Slog.e(TAG, "Failed to set focused task", e);
                }
@@ -700,8 +708,9 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
                return;
            }
            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                "[%d] RecentsController.finishInner: toHome=%b userLeave=%b willFinishToHome=%b",
                    mInstanceId, toHome, sendUserLeaveHint, mWillFinishToHome);
                    "[%d] RecentsController.finishInner: toHome=%b userLeave=%b "
                            + "willFinishToHome=%b state=%d",
                    mInstanceId, toHome, sendUserLeaveHint, mWillFinishToHome, mState);
            final Transitions.TransitionFinishCallback finishCB = mFinishCB;
            mFinishCB = null;

@@ -712,8 +721,19 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
                if (toHome) wct.reorder(mRecentsTask, true /* toTop */);
                else wct.restoreTransientOrder(mRecentsTask);
            }
            if (!toHome && !mWillFinishToHome && mPausingTasks != null && mState == STATE_NORMAL) {
                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, "  returning to app");
            if (!toHome
                    // If a recents gesture starts on the 3p launcher, then the 3p launcher is the
                    // live tile (pausing app). If the gesture is "cancelled" we need to return to
                    // 3p launcher instead of "task-switching" away from it.
                    && (!mWillFinishToHome || mPausingSeparateHome)
                    && mPausingTasks != null && mState == STATE_NORMAL) {
                if (mPausingSeparateHome) {
                    ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                            "  returning to 3p home");
                } else {
                    ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                            "  returning to app");
                }
                // The gesture is returning to the pausing-task(s) rather than continuing with
                // recents, so end the transition by moving the app back to the top (and also
                // re-showing it's task).
+18 −0
Original line number Diff line number Diff line
@@ -1996,6 +1996,24 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
        }
    }

    @Override
    public void focusTopTask(int displayId) {
        enforceTaskPermission("focusTopTask()");
        final long callingId = Binder.clearCallingIdentity();
        try {
            synchronized (mGlobalLock) {
                final DisplayContent dc = mRootWindowContainer.getDisplayContent(displayId);
                if (dc == null) return;
                final Task task = dc.getTask((t) -> t.isLeafTask() && t.isFocusable(),
                        true /*  traverseTopToBottom */);
                if (task == null) return;
                setFocusedTask(task.mTaskId, null /* touchedActivity */);
            }
        } finally {
            Binder.restoreCallingIdentity(callingId);
        }
    }

    void setFocusedTask(int taskId, ActivityRecord touchedActivity) {
        ProtoLog.d(WM_DEBUG_FOCUS, "setFocusedTask: taskId=%d touchedActivity=%s", taskId,
                touchedActivity);