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

Commit d0b5c8ff authored by lumark's avatar lumark
Browse files

Do not allow input connections from untrusted virtual displays

As Input-routing or Input Method Editor (IME) supported on multi-displays from Q,
user can interact multi-displays with touch and key input.

It could be necessary to consider and prevent a use case that the malicious app
may create in-visible virtual display to steal the window focus or intercept key
or keyboard input through input channel or input connection.

Don't provide display focus to the newly created virtual displays, until the user
interacts with a virtual display, then we give it & receive the display focus.

Bug: 129963294
Test: make sure all MultiDisplay and Window focus related tests pass.
Change-Id: I9bc37695cf6e2e894bf545a69c6cb006666c5539
parent 14a2a901
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -2256,7 +2256,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
            return false;
        }

        if (mRootActivityContainer.getTopResumedActivity() == this) {
        if (mRootActivityContainer.getTopResumedActivity() == this
                && getDisplayContent().mFocusedApp == this) {
            if (DEBUG_FOCUS) {
                Slog.d(TAG_FOCUS, "moveActivityStackToFront: already on top, activity=" + this);
            }
+5 −1
Original line number Diff line number Diff line
@@ -4097,7 +4097,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
                super.positionChildAt(currentPosition, child, false /* includingParents */);
                return;
            }

            // We don't allow untrusted display to top when task stack moves to top,
            // until user tapping this display to change display position as top intentionally.
            if (isUntrustedVirtualDisplay() && !getParent().isOnTop()) {
                includingParents = false;
            }
            final int targetPosition = findPositionForStack(position, child, false /* adding */);
            super.positionChildAt(targetPosition, child, includingParents);

+6 −0
Original line number Diff line number Diff line
@@ -203,6 +203,12 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
        return dc != null ? dc : getDisplayContent(DEFAULT_DISPLAY);
    }

    @Override
    boolean isOnTop() {
        // Considered always on top
        return true;
    }

    @Override
    void onChildPositionChanged(WindowContainer child) {
        mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
+5 −8
Original line number Diff line number Diff line
@@ -7610,12 +7610,15 @@ public class WindowManagerService extends IWindowManager.Stub
            // it as if the host window was tapped.
            touchedWindow = mEmbeddedWindowController.getHostWindow(touchedToken);
        }
        if (touchedWindow == null || !touchedWindow.canReceiveKeys()) {

        if (touchedWindow == null || !touchedWindow.canReceiveKeys(true /* fromUserTouch */)) {
            // If the window that received the input event cannot receive keys, don't move the
            // display it's on to the top since that window won't be able to get focus anyway.
            return;
        }

        handleTaskFocusChange(touchedWindow.getTask());
        handleDisplayFocusChange(touchedWindow);
        handleTaskFocusChange(touchedWindow.getTask());
    }

    private void handleTaskFocusChange(Task task) {
@@ -7643,12 +7646,6 @@ public class WindowManagerService extends IWindowManager.Stub
            return;
        }

        if (!window.canReceiveKeys()) {
            // If the window that received the input event cannot receive keys, don't move the
            // display it's on to the top since that window won't be able to get focus anyway.
            return;
        }

        final WindowContainer parent = displayContent.getParent();
        if (parent != null && parent.getTopChild() != displayContent) {
            parent.positionChildAt(WindowContainer.POSITION_TOP, displayContent,
+12 −1
Original line number Diff line number Diff line
@@ -2617,11 +2617,22 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP

    @Override
    public boolean canReceiveKeys() {
        return isVisibleOrAdding()
        return canReceiveKeys(false /* fromUserTouch */);
    }

    public boolean canReceiveKeys(boolean fromUserTouch) {
        final boolean canReceiveKeys = isVisibleOrAdding()
                && (mViewVisibility == View.VISIBLE) && !mRemoveOnExit
                && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0)
                && (mActivityRecord == null || mActivityRecord.windowsAreFocusable())
                && !cantReceiveTouchInput();
        if (!canReceiveKeys) {
            return false;
        }
        // Do not allow untrusted virtual display to receive keys unless user intentionally
        // touches the display.
        return fromUserTouch || getDisplayContent().isOnTop()
                || !getDisplayContent().isUntrustedVirtualDisplay();
    }

    @Override
Loading