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

Commit 2104fd96 authored by Louis Chang's avatar Louis Chang
Browse files

Allowing tap outside focus changes for pre-Q non-top window

For compatibility reasons, non-top app windows that target earlier
SDK may not have focus if there has another window that is higher
and has focus. In that case, we were unable to switch focus to the
window since it cannot handle tap outside events.

Also remove #ensureActivitiesVisible while handling focus change,
since it is no longer necessary.

Bug: 123761773
Test: atest MultiDisplayPolicyTests
Change-Id: I5afac910ecb4806dc190b37f1dccd4cba4d76f9f
parent 993b3ed5
Loading
Loading
Loading
Loading
+13 −4
Original line number Diff line number Diff line
@@ -2222,11 +2222,15 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        return (info.flags & FLAG_ALWAYS_FOCUSABLE) != 0;
    }

    boolean windowsAreFocusable() {
        return windowsAreFocusable(false /* fromUserTouch */);
    }

    // TODO: Does this really need to be different from isAlwaysFocusable()? For the activity side
    // focusable means resumeable. I guess with that in mind maybe we should rename the other
    // method to isResumeable() or something like that.
    boolean windowsAreFocusable() {
        if (mTargetSdk < Build.VERSION_CODES.Q) {
    boolean windowsAreFocusable(boolean fromUserTouch) {
        if (!fromUserTouch && mTargetSdk < Build.VERSION_CODES.Q) {
            final int pid = getPid();
            final ActivityRecord topFocusedAppOfMyProcess =
                    mWmService.mRoot.mTopFocusedAppByProcess.get(pid);
@@ -2240,7 +2244,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
                && getDisplay() != null;
    }

    /** Move activity with its stack to front and make the stack focused. */
    /**
     * Move activity with its stack to front and make the stack focused.
     * @param reason the reason to move to top
     * @return {@code true} if the stack is focusable and has been moved to top or the activity
     *         is not yet resumed while the stack is already on top, {@code false} otherwise.
     */
    boolean moveFocusableActivityToTop(String reason) {
        if (!isFocusable()) {
            if (DEBUG_FOCUS) {
@@ -2261,7 +2270,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
            if (DEBUG_FOCUS) {
                Slog.d(TAG_FOCUS, "moveActivityStackToFront: already on top, activity=" + this);
            }
            return false;
            return !isState(RESUMED);
        }

        if (DEBUG_FOCUS) {
+5 −25
Original line number Diff line number Diff line
@@ -80,7 +80,6 @@ import static com.android.internal.util.LatencyTracker.ACTION_ROTATE_SCREEN;
import static com.android.server.LockGuard.INDEX_WINDOW;
import static com.android.server.LockGuard.installLock;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_BOOT;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS;
@@ -7640,7 +7639,11 @@ public class WindowManagerService extends IWindowManager.Stub
            return;
        }

        handleDisplayFocusChange(touchedWindow);
        final DisplayContent displayContent = touchedWindow.getDisplayContent();
        if (!displayContent.isOnTop()) {
            displayContent.getParent().positionChildAt(WindowContainer.POSITION_TOP, displayContent,
                    true /* includingParents */);
        }
        handleTaskFocusChange(touchedWindow.getTask());
    }

@@ -7663,29 +7666,6 @@ public class WindowManagerService extends IWindowManager.Stub
        }
    }

    private void handleDisplayFocusChange(WindowState window) {
        final DisplayContent displayContent = window.getDisplayContent();
        if (displayContent == null) {
            return;
        }

        final WindowContainer parent = displayContent.getParent();
        if (parent != null && parent.getTopChild() != displayContent) {
            parent.positionChildAt(WindowContainer.POSITION_TOP, displayContent,
                    true /* includingParents */);
            // For compatibility, only the topmost activity is allowed to be resumed for pre-Q
            // app. Ensure the topmost activities are resumed whenever a display is moved to top.
            // TODO(b/123761773): Investigate whether we can move this into
            // RootActivityContainer#updateTopResumedActivityIfNeeded(). Currently, it is risky
            // to do so because it seems possible to resume activities as part of a larger
            // transaction and it's too early to resume based on current order when performing
            // updateTopResumedActivityIfNeeded().
            // TODO(display-merge): Remove cast
            ((ActivityDisplay) displayContent).ensureActivitiesVisible(null /* starting */,
                    0 /* configChanges */, !PRESERVE_WINDOWS, true /* notifyClients */);
        }
    }

    /**
     * Assigns an InputChannel to a SurfaceControl and configures it to receive
     * touch input according to it's on-screen geometry.
+1 −1
Original line number Diff line number Diff line
@@ -2625,7 +2625,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
        final boolean canReceiveKeys = isVisibleOrAdding()
                && (mViewVisibility == View.VISIBLE) && !mRemoveOnExit
                && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0)
                && (mActivityRecord == null || mActivityRecord.windowsAreFocusable())
                && (mActivityRecord == null || mActivityRecord.windowsAreFocusable(fromUserTouch))
                && !cantReceiveTouchInput();
        if (!canReceiveKeys) {
            return false;