From fc8f82bc6b587bddd2aeaddc54c1ea3f598bb9c3 Mon Sep 17 00:00:00 2001 From: Andrii Kulian Date: Thu, 26 Jan 2017 13:17:27 -0800 Subject: [PATCH] Allow showing content on virtual displays when locked This adds new flag to virtual display that changes its behavior when keyguard is shown, but can be dismissed without entering credentials. This can be applied only to private virtual displays. Bug: 34280365 Test: android.server.cts.ActivityManagerDisplayTests Test: #testVirtualDisplayHidesContentWhenLocked Test: #testShowWhenLockedVirtualDisplay Test: #testShowWhenLockedPublicVirtualDisplay Change-Id: I9c19d36295e62f59bd1db1352af707d54ea51667 --- api/current.txt | 2 ++ api/system-current.txt | 2 ++ api/test-current.txt | 2 ++ .../hardware/display/DisplayManager.java | 30 ++++++++++++++----- core/java/android/view/Display.java | 15 +++++++++- .../com/android/server/am/ActivityStack.java | 24 +++++++++++++++ .../android/server/am/KeyguardController.java | 2 +- .../server/display/DisplayDeviceInfo.java | 8 +++++ .../server/display/DisplayManagerService.java | 25 ++++++++++++---- .../server/display/LogicalDisplay.java | 3 ++ .../server/display/VirtualDisplayAdapter.java | 3 ++ 11 files changed, 101 insertions(+), 15 deletions(-) diff --git a/api/current.txt b/api/current.txt index 19faf5eee979d..31114842036cb 100644 --- a/api/current.txt +++ b/api/current.txt @@ -15246,6 +15246,7 @@ package android.hardware.display { field public static final int VIRTUAL_DISPLAY_FLAG_PRESENTATION = 2; // 0x2 field public static final int VIRTUAL_DISPLAY_FLAG_PUBLIC = 1; // 0x1 field public static final int VIRTUAL_DISPLAY_FLAG_SECURE = 4; // 0x4 + field public static final int VIRTUAL_DISPLAY_FLAG_SHOW_WITH_INSECURE_LOCKSCREEN = 32; // 0x20 } public static abstract interface DisplayManager.DisplayListener { @@ -42575,6 +42576,7 @@ package android.view { field public static final int FLAG_PRIVATE = 4; // 0x4 field public static final int FLAG_ROUND = 16; // 0x10 field public static final int FLAG_SECURE = 2; // 0x2 + field public static final int FLAG_SHOW_WITH_INSECURE_LOCKSCREEN = 32; // 0x20 field public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1; // 0x1 field public static final int INVALID_DISPLAY = -1; // 0xffffffff field public static final int STATE_DOZE = 3; // 0x3 diff --git a/api/system-current.txt b/api/system-current.txt index 8e7258334cf5d..29179cfc8fcf6 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -15823,6 +15823,7 @@ package android.hardware.display { field public static final int VIRTUAL_DISPLAY_FLAG_PRESENTATION = 2; // 0x2 field public static final int VIRTUAL_DISPLAY_FLAG_PUBLIC = 1; // 0x1 field public static final int VIRTUAL_DISPLAY_FLAG_SECURE = 4; // 0x4 + field public static final int VIRTUAL_DISPLAY_FLAG_SHOW_WITH_INSECURE_LOCKSCREEN = 32; // 0x20 } public static abstract interface DisplayManager.DisplayListener { @@ -45976,6 +45977,7 @@ package android.view { field public static final int FLAG_PRIVATE = 4; // 0x4 field public static final int FLAG_ROUND = 16; // 0x10 field public static final int FLAG_SECURE = 2; // 0x2 + field public static final int FLAG_SHOW_WITH_INSECURE_LOCKSCREEN = 32; // 0x20 field public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1; // 0x1 field public static final int INVALID_DISPLAY = -1; // 0xffffffff field public static final int STATE_DOZE = 3; // 0x3 diff --git a/api/test-current.txt b/api/test-current.txt index bd3b1255c16a3..334f4e62c97f3 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -15279,6 +15279,7 @@ package android.hardware.display { field public static final int VIRTUAL_DISPLAY_FLAG_PRESENTATION = 2; // 0x2 field public static final int VIRTUAL_DISPLAY_FLAG_PUBLIC = 1; // 0x1 field public static final int VIRTUAL_DISPLAY_FLAG_SECURE = 4; // 0x4 + field public static final int VIRTUAL_DISPLAY_FLAG_SHOW_WITH_INSECURE_LOCKSCREEN = 32; // 0x20 } public static abstract interface DisplayManager.DisplayListener { @@ -42877,6 +42878,7 @@ package android.view { field public static final int FLAG_PRIVATE = 4; // 0x4 field public static final int FLAG_ROUND = 16; // 0x10 field public static final int FLAG_SECURE = 2; // 0x2 + field public static final int FLAG_SHOW_WITH_INSECURE_LOCKSCREEN = 32; // 0x20 field public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1; // 0x1 field public static final int INVALID_DISPLAY = -1; // 0xffffffff field public static final int STATE_DOZE = 3; // 0x3 diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java index 12e1963a2e3ef..6788b67197e3e 100644 --- a/core/java/android/hardware/display/DisplayManager.java +++ b/core/java/android/hardware/display/DisplayManager.java @@ -108,13 +108,14 @@ public final class DisplayManager { *

* *

- * 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;