From b28fb721f5be06818bedc8601e02118ddcbd4739 Mon Sep 17 00:00:00 2001 From: Charles Chen Date: Thu, 21 May 2020 17:19:32 +0800 Subject: Trust System UI owned display to receive keys A11y service cannot get focus of bubbles because it's not a System owned display. This patch makes System UI owned display a trusted display. Moreover, this patch refactors the logic to identify a trusted display by introducing FLAG_TRUSTED and removes the trusted display check along with supportsSystemDecorations() because the check has been included in supportsSystemDecorations(). fixes: 155823002 Bug: 152416787 Test: atest DisplayContentTests Test: atest WindowFocusTests Test: atest TaskDisplayAreaTests Test: atest MultiDisplaySystemDecorationTests Test: atest DisplayTest Change-Id: Ie684c6488904e5aa8cae166a455c6d55455e5f55 --- .../android/server/display/DisplayDeviceInfo.java | 8 ++++++++ .../server/display/DisplayManagerService.java | 21 ++++++++++++++++----- .../android/server/display/LocalDisplayAdapter.java | 2 ++ .../com/android/server/display/LogicalDisplay.java | 3 +++ .../server/display/OverlayDisplayAdapter.java | 4 ++++ .../server/display/VirtualDisplayAdapter.java | 6 ++++++ .../android/server/display/WifiDisplayAdapter.java | 2 ++ .../java/com/android/server/wm/DisplayContent.java | 16 ++++++---------- .../java/com/android/server/wm/TaskDisplayArea.java | 5 ++--- .../com/android/server/wm/WindowManagerService.java | 7 ++----- .../java/com/android/server/wm/WindowState.java | 2 +- .../com/android/server/wm/DisplayContentTests.java | 5 ++--- .../com/android/server/wm/TaskDisplayAreaTests.java | 4 ++-- 13 files changed, 56 insertions(+), 29 deletions(-) (limited to 'services') diff --git a/services/core/java/com/android/server/display/DisplayDeviceInfo.java b/services/core/java/com/android/server/display/DisplayDeviceInfo.java index 18adc0ba27ee..d4377e4870a5 100644 --- a/services/core/java/com/android/server/display/DisplayDeviceInfo.java +++ b/services/core/java/com/android/server/display/DisplayDeviceInfo.java @@ -116,11 +116,19 @@ final class DisplayDeviceInfo { /** * Flag: This flag identifies secondary displays that should show system decorations, such as * status bar, navigation bar, home activity or IME. + *

Note that this flag doesn't work without {@link #FLAG_TRUSTED}

* @hide */ // TODO (b/114338689): Remove the flag and use IWindowManager#setShouldShowSystemDecors public static final int FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS = 1 << 12; + /** + * Flag: The display is trusted to show system decorations and receive inputs without users' + * touch. + * @see #FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS + */ + public static final int FLAG_TRUSTED = 1 << 13; + /** * Touch attachment: Display does not receive touch. */ diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index dee6cd02917f..1058000e0b68 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -16,6 +16,7 @@ package com.android.server.display; +import static android.Manifest.permission.ADD_TRUSTED_DISPLAY; import static android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT; import static android.Manifest.permission.CAPTURE_VIDEO_OUTPUT; import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW; @@ -25,6 +26,7 @@ import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_C import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC; import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE; import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS; +import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED; import static android.hardware.display.DisplayViewport.VIEWPORT_EXTERNAL; import static android.hardware.display.DisplayViewport.VIEWPORT_INTERNAL; import static android.hardware.display.DisplayViewport.VIEWPORT_VIRTUAL; @@ -2189,16 +2191,25 @@ public final class DisplayManagerService extends SystemService { } } + if (callingUid == Process.SYSTEM_UID + || checkCallingPermission(ADD_TRUSTED_DISPLAY, "createVirtualDisplay()")) { + flags |= VIRTUAL_DISPLAY_FLAG_TRUSTED; + } else { + flags &= ~VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS; + } + // Sometimes users can have sensitive information in system decoration windows. An app // could create a virtual display with system decorations support and read the user info // from the surface. // We should only allow adding flag VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS - // to virtual displays that are owned by the system. - if (callingUid != Process.SYSTEM_UID - && (flags & VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS) != 0) { - if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "createVirtualDisplay()")) { + // to trusted virtual displays. + final int trustedDisplayWithSysDecorFlag = + (VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS + | VIRTUAL_DISPLAY_FLAG_TRUSTED); + if ((flags & trustedDisplayWithSysDecorFlag) + == VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS + && !checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "createVirtualDisplay()")) { throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission"); - } } final long token = Binder.clearCallingIdentity(); diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java index 2a65b33461cf..2c08420af42d 100644 --- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java +++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java @@ -577,6 +577,8 @@ final class LocalDisplayAdapter extends DisplayAdapter { mInfo.name = getContext().getResources().getString( com.android.internal.R.string.display_manager_hdmi_display_name); } + // The display is trusted since it is created by system. + mInfo.flags |= DisplayDeviceInfo.FLAG_TRUSTED; } return mInfo; } diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java index 0261f388f7cb..8556f084a072 100644 --- a/services/core/java/com/android/server/display/LogicalDisplay.java +++ b/services/core/java/com/android/server/display/LogicalDisplay.java @@ -269,6 +269,9 @@ final class LogicalDisplay { if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS) != 0) { mBaseDisplayInfo.flags |= Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS; } + if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_TRUSTED) != 0) { + mBaseDisplayInfo.flags |= Display.FLAG_TRUSTED; + } Rect maskingInsets = getMaskingInsets(deviceInfo); int maskedWidth = deviceInfo.width - maskingInsets.left - maskingInsets.right; int maskedHeight = deviceInfo.height - maskingInsets.top - maskingInsets.bottom; diff --git a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java index 8fb384070e25..69943e3904ed 100644 --- a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java +++ b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java @@ -16,6 +16,8 @@ package com.android.server.display; +import static com.android.server.display.DisplayDeviceInfo.FLAG_TRUSTED; + import android.annotation.Nullable; import android.content.Context; import android.database.ContentObserver; @@ -356,6 +358,8 @@ final class OverlayDisplayAdapter extends DisplayAdapter { mInfo.type = Display.TYPE_OVERLAY; mInfo.touch = DisplayDeviceInfo.TOUCH_VIRTUAL; mInfo.state = mState; + // The display is trusted since it is created by system. + mInfo.flags |= FLAG_TRUSTED; } return mInfo; } diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java index ccd88483593a..210d2979c807 100644 --- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java +++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java @@ -25,6 +25,9 @@ import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_ROTAT import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE; import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS; import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH; +import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED; + +import static com.android.server.display.DisplayDeviceInfo.FLAG_TRUSTED; import android.content.Context; import android.hardware.display.IVirtualDisplayCallback; @@ -412,6 +415,9 @@ public class VirtualDisplayAdapter extends DisplayAdapter { if ((mFlags & VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS) != 0) { mInfo.flags |= DisplayDeviceInfo.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS; } + if ((mFlags & VIRTUAL_DISPLAY_FLAG_TRUSTED) != 0) { + mInfo.flags |= FLAG_TRUSTED; + } mInfo.type = Display.TYPE_VIRTUAL; mInfo.touch = ((mFlags & VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH) == 0) ? diff --git a/services/core/java/com/android/server/display/WifiDisplayAdapter.java b/services/core/java/com/android/server/display/WifiDisplayAdapter.java index 5584dcf69f50..57323170b327 100644 --- a/services/core/java/com/android/server/display/WifiDisplayAdapter.java +++ b/services/core/java/com/android/server/display/WifiDisplayAdapter.java @@ -651,6 +651,8 @@ final class WifiDisplayAdapter extends DisplayAdapter { mInfo.address = mAddress; mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL; mInfo.setAssumedDensityForExternalDisplay(mWidth, mHeight); + // The display is trusted since it is created by system. + mInfo.flags |= DisplayDeviceInfo.FLAG_TRUSTED; } return mInfo; } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 4e19a5224bb4..923128e7c228 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -2175,6 +2175,10 @@ class DisplayContent extends WindowContainer { } // 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 (mDisplayContent.isUntrustedVirtualDisplay() && !getParent().isOnTop()) { + if (!mDisplayContent.isTrusted() && !getParent().isOnTop()) { includingParents = false; } final int targetPosition = findPositionForStack(position, child, false /* adding */); @@ -1497,8 +1497,7 @@ final class TaskDisplayArea extends DisplayArea { @Nullable ActivityStack getOrCreateRootHomeTask(boolean onTop) { ActivityStack homeTask = getRootHomeTask(); - if (homeTask == null && mDisplayContent.supportsSystemDecorations() - && !mDisplayContent.isUntrustedVirtualDisplay()) { + if (homeTask == null && mDisplayContent.supportsSystemDecorations()) { homeTask = createStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME, onTop); } return homeTask; diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 0590288a7f8b..10d07573f8c6 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -7150,9 +7150,6 @@ public class WindowManagerService extends IWindowManager.Stub + "not exist: %d", displayId); return false; } - if (displayContent.isUntrustedVirtualDisplay()) { - return false; - } return displayContent.supportsSystemDecorations(); } } @@ -7171,7 +7168,7 @@ public class WindowManagerService extends IWindowManager.Stub + "does not exist: %d", displayId); return; } - if (displayContent.isUntrustedVirtualDisplay()) { + if (!displayContent.isTrusted()) { throw new SecurityException("Attempted to set system decors flag to an " + "untrusted virtual display: " + displayId); } @@ -7219,7 +7216,7 @@ public class WindowManagerService extends IWindowManager.Stub + "exist: %d", displayId); return; } - if (displayContent.isUntrustedVirtualDisplay()) { + if (!displayContent.isTrusted()) { throw new SecurityException("Attempted to set IME flag to an untrusted " + "virtual display: " + displayId); } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 32717d0e1e65..7512383b161a 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -2793,7 +2793,7 @@ class WindowState extends WindowContainer implements WindowManagerP // Do not allow untrusted virtual display to receive keys unless user intentionally // touches the display. return fromUserTouch || getDisplayContent().isOnTop() - || !getDisplayContent().isUntrustedVirtualDisplay(); + || getDisplayContent().isTrusted(); } @Override diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index 4ad7dff87072..50125c1d290b 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -1280,7 +1280,6 @@ public class DisplayContentTests extends WindowTestsBase { public void testGetOrCreateRootHomeTask_supportedSecondaryDisplay() { DisplayContent display = createNewDisplay(); doReturn(true).when(display).supportsSystemDecorations(); - doReturn(false).when(display).isUntrustedVirtualDisplay(); // Remove the current home stack if it exists so a new one can be created below. TaskDisplayArea taskDisplayArea = display.getDefaultTaskDisplayArea(); @@ -1304,10 +1303,10 @@ public class DisplayContentTests extends WindowTestsBase { } @Test - public void testGetOrCreateRootHomeTask_untrustedVirtualDisplay() { + public void testGetOrCreateRootHomeTask_untrustedDisplay() { DisplayContent display = createNewDisplay(); TaskDisplayArea taskDisplayArea = display.getDefaultTaskDisplayArea(); - doReturn(true).when(display).isUntrustedVirtualDisplay(); + doReturn(false).when(display).isTrusted(); assertNull(taskDisplayArea.getRootHomeTask()); assertNull(taskDisplayArea.getOrCreateRootHomeTask()); diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java index 512042cdf7b9..786f8d8af024 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java @@ -150,9 +150,9 @@ public class TaskDisplayAreaTests extends WindowTestsBase { @Test public void testDisplayPositionWithPinnedStack() { - // Make sure the display is system owned display which capable to move the stack to top. + // Make sure the display is trusted display which capable to move the stack to top. spyOn(mDisplayContent); - doReturn(false).when(mDisplayContent).isUntrustedVirtualDisplay(); + doReturn(true).when(mDisplayContent).isTrusted(); // The display contains pinned stack that was added in {@link #setUp}. final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent); -- cgit v1.2.3-59-g8ed1b