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

Commit 3e62d4f2 authored by Evan Rosky's avatar Evan Rosky
Browse files

Keep existing focus during transient-launch.

If the user hasn't moved enough, the touch event is supposed to
go through the gesture-bar to the app. Once the user has moved
enough, though, the inputs should go to the launcher.

In legacy, touches automatically went to the live-tile because
the launcher was launch-behind (and thus not focused) but an
input consumer had to be added once the gesture started to take
events away from the app.

Shell is the opposite, launcher is on top so it would get focus
automatically; however, we need to add logic for the app to
hold-onto its focus until the gesture starts. This CL adds a rule
where transient-launches do not automatically take focus. If it
wants focus, it can make an explicit focus request.

Bug: 266660298
Test: SettingsActivityUiAutomatorTest#unblockAppDialogTest
      CloseImeWindowToHomeTest
Change-Id: I5ab01dc56dd4ae8bd40d5035ea985f9d562ac866
parent 1e980081
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -1771,6 +1771,12 @@
      "group": "WM_DEBUG_KEEP_SCREEN_ON",
      "at": "com\/android\/server\/wm\/RootWindowContainer.java"
    },
    "-464564167": {
      "message": "Current transition prevents automatic focus change",
      "level": "VERBOSE",
      "group": "WM_DEBUG_FOCUS",
      "at": "com\/android\/server\/wm\/DisplayContent.java"
    },
    "-463348344": {
      "message": "Removing and adding activity %s to root task at top callers=%s",
      "level": "INFO",
@@ -2065,12 +2071,6 @@
      "group": "WM_DEBUG_ANIM",
      "at": "com\/android\/server\/wm\/SurfaceAnimator.java"
    },
    "-206549078": {
      "message": "Not moving display (displayId=%d) to top. Top focused displayId=%d. Reason: config_perDisplayFocusEnabled",
      "level": "INFO",
      "group": "WM_DEBUG_FOCUS_LIGHT",
      "at": "com\/android\/server\/wm\/WindowManagerService.java"
    },
    "-203358733": {
      "message": "commitFinishDrawingLocked: mDrawState=READY_TO_SHOW %s",
      "level": "INFO",
+17 −3
Original line number Diff line number Diff line
@@ -88,6 +88,7 @@ public class RemoteTransitionCompat {
                final ArrayList<WindowContainerToken> pausingTasks = new ArrayList<>();
                WindowContainerToken pipTask = null;
                WindowContainerToken recentsTask = null;
                int recentsTaskId = -1;
                for (int i = apps.length - 1; i >= 0; --i) {
                    final ActivityManager.RunningTaskInfo taskInfo = apps[i].taskInfo;
                    if (apps[i].mode == MODE_CLOSING) {
@@ -106,8 +107,10 @@ public class RemoteTransitionCompat {
                        // This task is for recents, keep it on top.
                        t.setLayer(apps[i].leash, info.getChanges().size() * 3 - i);
                        recentsTask = taskInfo.token;
                        recentsTaskId = taskInfo.taskId;
                    } else if (taskInfo != null && taskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
                        recentsTask = taskInfo.token;
                        recentsTaskId = taskInfo.taskId;
                    }
                }
                // Also make all the wallpapers opaque since we want the visible from the start
@@ -116,7 +119,7 @@ public class RemoteTransitionCompat {
                }
                t.apply();
                mRecentsSession.setup(controller, info, finishedCallback, pausingTasks, pipTask,
                        recentsTask, leashMap, mToken,
                        recentsTask, recentsTaskId, leashMap, mToken,
                        (info.getFlags() & TRANSIT_FLAG_KEYGUARD_LOCKED) != 0);
                recents.onAnimationStart(mRecentsSession, apps, wallpapers, new Rect(0, 0, 0, 0),
                        new Rect());
@@ -154,6 +157,7 @@ public class RemoteTransitionCompat {
        private ArrayList<WindowContainerToken> mPausingTasks = null;
        private WindowContainerToken mPipTask = null;
        private WindowContainerToken mRecentsTask = null;
        private int mRecentsTaskId = 0;
        private TransitionInfo mInfo = null;
        private ArrayList<SurfaceControl> mOpeningLeashes = null;
        private boolean mOpeningHome = false;
@@ -167,8 +171,8 @@ public class RemoteTransitionCompat {
        void setup(RecentsAnimationControllerCompat wrapped, TransitionInfo info,
                IRemoteTransitionFinishedCallback finishCB,
                ArrayList<WindowContainerToken> pausingTasks, WindowContainerToken pipTask,
                WindowContainerToken recentsTask, ArrayMap<SurfaceControl, SurfaceControl> leashMap,
                IBinder transition, boolean keyguardLocked) {
                WindowContainerToken recentsTask, int recentsTaskId, ArrayMap<SurfaceControl,
                SurfaceControl> leashMap, IBinder transition, boolean keyguardLocked) {
            if (mInfo != null) {
                throw new IllegalStateException("Trying to run a new recents animation while"
                        + " recents is already active.");
@@ -179,6 +183,7 @@ public class RemoteTransitionCompat {
            mPausingTasks = pausingTasks;
            mPipTask = pipTask;
            mRecentsTask = recentsTask;
            mRecentsTaskId = recentsTaskId;
            mLeashMap = leashMap;
            mTransition = transition;
            mKeyguardLocked = keyguardLocked;
@@ -296,6 +301,15 @@ public class RemoteTransitionCompat {
        }

        @Override public void setInputConsumerEnabled(boolean enabled) {
            if (enabled) {
                // transient launches don't receive focus automatically. Since we are taking over
                // the gesture now, take focus explicitly.
                try {
                    ActivityTaskManager.getService().setFocusedTask(mRecentsTaskId);
                } catch (RemoteException e) {
                    Log.e(TAG, "Failed to set focused task", e);
                }
            }
            if (mWrapped != null) mWrapped.setInputConsumerEnabled(enabled);
        }

+20 −9
Original line number Diff line number Diff line
@@ -4748,16 +4748,27 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
        updateResumedAppTrace(r);
        mLastResumedActivity = r;

        // Don't take focus when transient launching. We don't want the app to know anything
        // until we've committed to the gesture. The focus will be transferred at the end of
        // the transition (if the transient launch is committed) or early if explicitly requested
        // via `setFocused*`.
        if (!getTransitionController().isTransientCollect(r)) {
            final Task prevFocusTask = r.mDisplayContent.mFocusedApp != null
                    ? r.mDisplayContent.mFocusedApp.getTask() : null;
            final boolean changed = r.mDisplayContent.setFocusedApp(r);
            if (changed) {
                mWindowManager.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
                        true /*updateInputWindows*/);
            }
        if (prevTask == null || task != prevTask) {
            if (prevTask != null) {
                mTaskChangeNotificationController.notifyTaskFocusChanged(prevTask.mTaskId, false);
            if (task != prevFocusTask) {
                if (prevFocusTask != null) {
                    mTaskChangeNotificationController.notifyTaskFocusChanged(
                            prevFocusTask.mTaskId, false);
                }
                mTaskChangeNotificationController.notifyTaskFocusChanged(task.mTaskId, true);
            }
        }
        if (task != prevTask) {
            mTaskSupervisor.mRecentTasks.add(task);
        }

+11 −0
Original line number Diff line number Diff line
@@ -3804,6 +3804,17 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
     */
    boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows,
            int topFocusedDisplayId) {
        // Don't re-assign focus automatically away from a should-keep-focus app window.
        // `findFocusedWindow` will always grab the transient-launch app since it is "on top" which
        // would create a mismatch, so just early-out here.
        if (mCurrentFocus != null && mTransitionController.shouldKeepFocus(mCurrentFocus)
                // This is only keeping focus, so don't early-out if the focused-app has been
                // explicitly changed (eg. via setFocusedTask).
                && mFocusedApp != null && mCurrentFocus.isDescendantOf(mFocusedApp)
                && mCurrentFocus.isVisible() && mCurrentFocus.isFocusable()) {
            ProtoLog.v(WM_DEBUG_FOCUS, "Current transition prevents automatic focus change");
            return false;
        }
        WindowState newFocus = findFocusedWindowIfNeeded(topFocusedDisplayId);
        if (mCurrentFocus == newFocus) {
            return false;
+6 −2
Original line number Diff line number Diff line
@@ -405,8 +405,12 @@ final class InputMonitor {
            // Apply recents input consumer when the focusing window is in recents animation.
            final boolean shouldApplyRecentsInputConsumer = (recentsAnimationController != null
                    && recentsAnimationController.shouldApplyInputConsumer(focus.mActivityRecord))
                    // Shell transitions doesn't use RecentsAnimationController
                    || getWeak(mActiveRecentsActivity) != null && focus.inTransition();
                    // Shell transitions doesn't use RecentsAnimationController but we still
                    // have carryover legacy logic that relies on the consumer.
                    || (getWeak(mActiveRecentsActivity) != null && focus.inTransition()
                            // only take focus from the recents activity to avoid intercepting
                            // events before the gesture officially starts.
                            && focus.isActivityTypeHomeOrRecents());
            if (shouldApplyRecentsInputConsumer) {
                if (mInputFocus != recentsAnimationInputConsumer.mWindowHandle.token) {
                    requestFocus(recentsAnimationInputConsumer.mWindowHandle.token,
Loading