diff options
| author | 2017-01-26 13:17:27 -0800 | |
|---|---|---|
| committer | 2017-01-27 00:14:06 -0800 | |
| commit | fc8f82bc6b587bddd2aeaddc54c1ea3f598bb9c3 (patch) | |
| tree | 902ff2f3a3bb7dbd382424d5e791ead00e3b56d0 | |
| parent | 298c87820922aec2da5006bb233c87a3fc2bb507 (diff) | |
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
11 files changed, 101 insertions, 15 deletions
diff --git a/api/current.txt b/api/current.txt index 19faf5eee979..31114842036c 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 8e7258334cf5..29179cfc8fcf 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 bd3b1255c16a..334f4e62c97f 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 12e1963a2e3e..6788b67197e3 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 { * </p> * * <p> - * 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. * </p> * * @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. + * + * <p> + * 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. + * </p> + * + * @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 a534ca7c94bb..ebb9cf974516 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 */ @@ -194,6 +194,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. + * <p> + * 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. + * </p> + * + * @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 * devices with smaller physicals screens while preserving density. diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 163e2b64a4cb..6d5678c63b86 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 b0a4746b8ff1..2bd119ec177d 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 671918209b25..4798880a3f15 100644 --- a/services/core/java/com/android/server/display/DisplayDeviceInfo.java +++ b/services/core/java/com/android/server/display/DisplayDeviceInfo.java @@ -93,6 +93,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. */ public static final int TOUCH_NONE = 0; @@ -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 cd0779324194..7d18d36aa4cc 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 287a25aa9b3e..d9422ca2c6c2 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 9d0fde5f2027..6a1ef85101b8 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; |