From fc8f82bc6b587bddd2aeaddc54c1ea3f598bb9c3 Mon Sep 17 00:00:00 2001
From: Andrii Kulian
- * A private virtual display belongs to the application that created it. - * Only the a owner of a private virtual display is allowed to place windows upon it. - * The private virtual display also does not participate in display mirroring: it will - * neither receive mirrored content from another display nor allow its own content to - * be mirrored elsewhere. More precisely, the only processes that are allowed to - * enumerate or interact with the private display are those that have the same UID as the - * application that originally created the private virtual display. + * A private virtual display belongs to the application that created it. Only the a owner of a + * private virtual display and the apps that are already on that display are allowed to place + * windows upon it. The private virtual display also does not participate in display mirroring: + * it will neither receive mirrored content from another display nor allow its own content to be + * mirrored elsewhere. More precisely, the only processes that are allowed to enumerate or + * interact with the private display are those that have the same UID as the application that + * originally created the private virtual display or as the activities that are already on that + * display. *
* * @see #createVirtualDisplay @@ -234,6 +235,21 @@ public final class DisplayManager { */ public static final int VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR = 1 << 4; + /** + * Virtual display flag: Allows content to be displayed on private virtual displays when + * keyguard is shown but is insecure. + * + *+ * This flag can only be applied to private displays as defined by the + * {@link Display#FLAG_PRIVATE} display flag. It is mutually exclusive with + * {@link #VIRTUAL_DISPLAY_FLAG_PUBLIC}. If both flags are specified then this flag's behavior + * will not be applied. + *
+ * + * @see #createVirtualDisplay + */ + public static final int VIRTUAL_DISPLAY_FLAG_SHOW_WITH_INSECURE_LOCKSCREEN = 1 << 5; + /** @hide */ public DisplayManager(Context context) { mContext = context; diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java index a534ca7c94bb3..ebb9cf974516e 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -163,7 +163,7 @@ public final class Display { /** * Display flag: Indicates that the display is private. Only the application that - * owns the display can create windows on it. + * owns the display and apps that are already on the display can create windows on it. * * @see #getFlags */ @@ -193,6 +193,19 @@ public final class Display { */ public static final int FLAG_ROUND = 1 << 4; + /** + * Display flag: Indicates that the display can show its content when non-secure keyguard is + * shown. + *+ * This flag identifies secondary displays that won't show keyguard if it can be dismissed + * without entering credentials. Display content will be shown even if other displays are + * locked. + *
+ * + * @see #getFlags + */ + public static final int FLAG_SHOW_WITH_INSECURE_LOCKSCREEN = 1 << 5; + /** * Display flag: Indicates that the contents of the display should not be scaled * to fit the physical screen dimensions. Used for development only to emulate diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 163e2b64a4cbb..6d5678c63b868 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -26,6 +26,8 @@ import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT; import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING; import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS; import static android.view.Display.DEFAULT_DISPLAY; +import static android.view.Display.FLAG_SHOW_WITH_INSECURE_LOCKSCREEN; + import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ADD_REMOVE; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_APP; @@ -1884,6 +1886,12 @@ final class ActivityStack extends ConfigurationContainer implements StackWindowL if (isTop) { mTopActivityOccludesKeyguard |= showWhenLocked; } + + final boolean canShowWithKeyguard = isOnShowWhenLockedInsecureDisplay() + && mStackSupervisor.mKeyguardController.canDismissKeyguard(); + if (canShowWithKeyguard) { + return true; + } } if (keyguardShowing) { @@ -1899,6 +1907,22 @@ final class ActivityStack extends ConfigurationContainer implements StackWindowL } } + /** + * Check if the display to which this stack is attached has + * {@link Display#FLAG_SHOW_WITH_INSECURE_LOCKSCREEN} applied. + */ + private boolean isOnShowWhenLockedInsecureDisplay() { + final ActivityStackSupervisor.ActivityDisplay activityDisplay + = mActivityContainer.mActivityDisplay; + if (activityDisplay == null) { + throw new IllegalStateException("Stack is not attached to any display, stackId=" + + mStackId); + } + + final int flags = activityDisplay.mDisplay.getFlags(); + return (flags & FLAG_SHOW_WITH_INSECURE_LOCKSCREEN) != 0; + } + private void checkTranslucentActivityWaiting(ActivityRecord top) { if (mTranslucentActivityWaiting != top) { mUndrawnActivitiesBelowTopTranslucent.clear(); diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java index b0a4746b8ff1d..2bd119ec177da 100644 --- a/services/core/java/com/android/server/am/KeyguardController.java +++ b/services/core/java/com/android/server/am/KeyguardController.java @@ -280,7 +280,7 @@ class KeyguardController { /** * @return true if Keyguard can be currently dismissed without entering credentials. */ - private boolean canDismissKeyguard() { + boolean canDismissKeyguard() { return mWindowManager.isKeyguardTrusted() || !mWindowManager.isKeyguardSecure(); } diff --git a/services/core/java/com/android/server/display/DisplayDeviceInfo.java b/services/core/java/com/android/server/display/DisplayDeviceInfo.java index 671918209b25c..4798880a3f15f 100644 --- a/services/core/java/com/android/server/display/DisplayDeviceInfo.java +++ b/services/core/java/com/android/server/display/DisplayDeviceInfo.java @@ -92,6 +92,11 @@ final class DisplayDeviceInfo { */ public static final int FLAG_ROUND = 1 << 8; + /** + * Flag: This display can show its content when non-secure keyguard is shown. + */ + public static final int FLAG_SHOW_WITH_INSECURE_LOCKSCREEN = 1 << 9; + /** * Touch attachment: Display does not receive touch. */ @@ -420,6 +425,9 @@ final class DisplayDeviceInfo { if ((flags & FLAG_ROUND) != 0) { msg.append(", FLAG_ROUND"); } + if ((flags & FLAG_SHOW_WITH_INSECURE_LOCKSCREEN) != 0) { + msg.append(", FLAG_SHOW_WITH_INSECURE_LOCKSCREEN"); + } return msg.toString(); } } diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index cd07793241942..7d18d36aa4cce 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -16,6 +16,13 @@ package com.android.server.display; +import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR; +import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY; +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_SHOW_WITH_INSECURE_LOCKSCREEN; + import com.android.internal.util.IndentingPrintWriter; import android.Manifest; @@ -1446,11 +1453,17 @@ public final class DisplayManagerService extends SystemService { throw new IllegalArgumentException("Surface can't be single-buffered"); } - if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) { - flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR; + if ((flags & VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) { + flags |= VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR; + + // Public displays can't be allowed to show content when locked. + if ((flags & VIRTUAL_DISPLAY_FLAG_SHOW_WITH_INSECURE_LOCKSCREEN) != 0) { + throw new IllegalArgumentException( + "Public display must not be marked as SHOW_WHEN_LOCKED_INSECURE"); + } } - if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY) != 0) { - flags &= ~DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR; + if ((flags & VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY) != 0) { + flags &= ~VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR; } if (projection != null) { @@ -1465,7 +1478,7 @@ public final class DisplayManagerService extends SystemService { } if (callingUid != Process.SYSTEM_UID && - (flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) { + (flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) { if (!canProjectVideo(projection)) { throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or " + "CAPTURE_SECURE_VIDEO_OUTPUT permission, or an appropriate " @@ -1473,7 +1486,7 @@ public final class DisplayManagerService extends SystemService { + "display."); } } - if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE) != 0) { + if ((flags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0) { if (!canProjectSecureVideo(projection)) { throw new SecurityException("Requires CAPTURE_SECURE_VIDEO_OUTPUT " + "or an appropriate MediaProjection token to create a " diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java index 287a25aa9b3e3..d9422ca2c6c24 100644 --- a/services/core/java/com/android/server/display/LogicalDisplay.java +++ b/services/core/java/com/android/server/display/LogicalDisplay.java @@ -223,6 +223,9 @@ final class LogicalDisplay { if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_ROUND) != 0) { mBaseDisplayInfo.flags |= Display.FLAG_ROUND; } + if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_SHOW_WITH_INSECURE_LOCKSCREEN) != 0) { + mBaseDisplayInfo.flags |= Display.FLAG_SHOW_WITH_INSECURE_LOCKSCREEN; + } mBaseDisplayInfo.type = deviceInfo.type; mBaseDisplayInfo.address = deviceInfo.address; mBaseDisplayInfo.name = deviceInfo.name; diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java index 9d0fde5f2027f..6a1ef85101b88 100644 --- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java +++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java @@ -333,6 +333,9 @@ final class VirtualDisplayAdapter extends DisplayAdapter { } } } + if ((mFlags & DisplayManager.VIRTUAL_DISPLAY_FLAG_SHOW_WITH_INSECURE_LOCKSCREEN) != 0) { + mInfo.flags |= DisplayDeviceInfo.FLAG_SHOW_WITH_INSECURE_LOCKSCREEN; + } mInfo.type = Display.TYPE_VIRTUAL; mInfo.touch = DisplayDeviceInfo.TOUCH_NONE; mInfo.state = mSurface != null ? Display.STATE_ON : Display.STATE_OFF;