diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 448188583b1ab..4c81f9cd38081 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -344,6 +344,16 @@ public final class DisplayManager {
*/
public static final int VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP = 1 << 11;
+ /**
+ * Virtual display flags: Indicates that the virtual display should always be unlocked and not
+ * have keyguard displayed on it. Only valid for virtual displays that aren't in the default
+ * display group.
+ *
+ * @see #createVirtualDisplay
+ * @see #VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP
+ * @hide
+ */
+ public static final int VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED = 1 << 12;
/** @hide */
@IntDef(prefix = {"MATCH_CONTENT_FRAMERATE_"}, value = {
@@ -1363,5 +1373,13 @@ public final class DisplayManager {
* @hide
*/
String KEY_HIGH_REFRESH_RATE_BLACKLIST = "high_refresh_rate_blacklist";
+
+ /**
+ * Whether to allow the creation of always unlocked virtual displays by apps having the
+ * required permissions.
+ * @hide
+ */
+ String KEY_ALLOW_ALWAYS_UNLOCKED_VIRTUAL_DISPLAYS =
+ "allow_always_unlocked_virtual_displays";
}
}
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 8259a9d981255..3cc51c7e8b51d 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -298,6 +298,15 @@ public final class Display {
*/
public static final int FLAG_OWN_DISPLAY_GROUP = 1 << 8;
+ /**
+ * Flag: Indicates that the display should always be unlocked. Only valid on virtual displays
+ * that aren't in the default display group.
+ *
+ * @hide
+ * @see #getFlags()
+ */
+ public static final int FLAG_ALWAYS_UNLOCKED = 1 << 9;
+
/**
* 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/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index 6572510465513..b8614ccde6fd1 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -863,6 +863,9 @@ public final class DisplayInfo implements Parcelable {
if ((flags & Display.FLAG_OWN_DISPLAY_GROUP) != 0) {
result.append(", FLAG_OWN_DISPLAY_GROUP");
}
+ if ((flags & Display.FLAG_ALWAYS_UNLOCKED) != 0) {
+ result.append(", FLAG_ALWAYS_UNLOCKED");
+ }
return result.toString();
}
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index a49e3b502c965..aada7eb2df8f4 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -5882,6 +5882,10 @@
+
+
+
diff --git a/services/core/java/com/android/server/display/DisplayDeviceInfo.java b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
index 40cee66a67914..fd4cd8e6ec88e 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceInfo.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
@@ -141,6 +141,15 @@ final class DisplayDeviceInfo {
*/
public static final int FLAG_OWN_DISPLAY_GROUP = 1 << 14;
+ /**
+ * Flag: Indicates that the display should always be unlocked. Only valid on virtual displays
+ * that aren't in the default display group.
+ * @see #FLAG_OWN_DISPLAY_GROUP
+ * @hide
+ */
+ public static final int FLAG_ALWAYS_UNLOCKED = 1 << 15;
+
+
/**
* 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 a36a1a9183fb3..77ab81301059e 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -16,11 +16,13 @@
package com.android.server.display;
+import static android.Manifest.permission.ADD_ALWAYS_UNLOCKED_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;
import static android.hardware.display.DisplayManager.EventsMask;
+import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
@@ -94,6 +96,8 @@ import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
+import android.provider.DeviceConfig;
+import android.provider.DeviceConfigInterface;
import android.provider.Settings;
import android.sysprop.DisplayProperties;
import android.text.TextUtils;
@@ -393,6 +397,7 @@ public final class DisplayManagerService extends SystemService {
private final SparseArray mDisplayAccessUIDs = new SparseArray<>();
private final Injector mInjector;
+ private final DeviceConfigInterface mDeviceConfig;
// The minimum brightness curve, which guarantess that any brightness curve that dips below it
// is rejected by the system.
@@ -443,6 +448,7 @@ public final class DisplayManagerService extends SystemService {
DisplayManagerService(Context context, Injector injector) {
super(context);
mInjector = injector;
+ mDeviceConfig = mInjector.getDeviceConfig();
mContext = context;
mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper());
mUiHandler = UiThread.getHandler();
@@ -1254,6 +1260,31 @@ public final class DisplayManagerService extends SystemService {
}
}
+ if ((flags & VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED) != 0) {
+ if (callingUid != Process.SYSTEM_UID
+ && !checkCallingPermission(ADD_ALWAYS_UNLOCKED_DISPLAY,
+ "createVirtualDisplay()")) {
+ throw new SecurityException(
+ "Requires ADD_ALWAYS_UNLOCKED_DISPLAY permission to "
+ + "create an always unlocked virtual display.");
+ }
+ boolean allowedByDeviceConfig = false;
+ final long token = Binder.clearCallingIdentity();
+ try {
+ allowedByDeviceConfig = mDeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
+ DisplayManager.DeviceConfig.KEY_ALLOW_ALWAYS_UNLOCKED_VIRTUAL_DISPLAYS,
+ false);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ if (!allowedByDeviceConfig) {
+ Slog.w(TAG, "Ignoring flag VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED "
+ + "because it is not allowed by DeviceConfig");
+ flags &= ~VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED;
+ }
+ }
+
if ((flags & VIRTUAL_DISPLAY_FLAG_TRUSTED) == 0) {
flags &= ~VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
}
@@ -2366,6 +2397,11 @@ public final class DisplayManagerService extends SystemService {
return DisplayProperties
.debug_allow_non_native_refresh_rate_override().orElse(false);
}
+
+ @NonNull
+ public DeviceConfigInterface getDeviceConfig() {
+ return DeviceConfigInterface.REAL;
+ }
}
@VisibleForTesting
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index 48eea8938bb8e..4d1367a3d0834 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -378,6 +378,9 @@ final class LogicalDisplay {
if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP) != 0) {
mBaseDisplayInfo.flags |= Display.FLAG_OWN_DISPLAY_GROUP;
}
+ if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_ALWAYS_UNLOCKED) != 0) {
+ mBaseDisplayInfo.flags |= Display.FLAG_ALWAYS_UNLOCKED;
+ }
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/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index a59219265e2cd..797c3fb443383 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -16,6 +16,7 @@
package com.android.server.display;
+import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL;
@@ -28,6 +29,7 @@ import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SHOUL
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_ALWAYS_UNLOCKED;
import static com.android.server.display.DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP;
import static com.android.server.display.DisplayDeviceInfo.FLAG_TRUSTED;
@@ -453,6 +455,10 @@ public class VirtualDisplayAdapter extends DisplayAdapter {
if ((mFlags & VIRTUAL_DISPLAY_FLAG_TRUSTED) != 0) {
mInfo.flags |= FLAG_TRUSTED;
}
+ if ((mFlags & VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED) != 0
+ && (mInfo.flags & DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP) != 0) {
+ mInfo.flags |= FLAG_ALWAYS_UNLOCKED;
+ }
mInfo.type = Display.TYPE_VIRTUAL;
mInfo.touch = ((mFlags & VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH) == 0) ?
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 68eff9a5450e8..9d8f1fc5f1bf4 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -5927,6 +5927,13 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
.getKeyguardController().isKeyguardGoingAway(mDisplayId);
}
+ /**
+ * @return whether keyguard should always be unlocked for this display
+ */
+ boolean isKeyguardAlwaysUnlocked() {
+ return (mDisplayInfo.flags & Display.FLAG_ALWAYS_UNLOCKED) != 0;
+ }
+
/**
* @return whether AOD is showing on this display
*/
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index a843909dd26ca..cabe414395269 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -157,6 +157,11 @@ class KeyguardController {
* Update the Keyguard showing state.
*/
void setKeyguardShown(int displayId, boolean keyguardShowing, boolean aodShowing) {
+ if (mRootWindowContainer.getDisplayContent(displayId).isKeyguardAlwaysUnlocked()) {
+ Slog.i(TAG, "setKeyguardShown ignoring always unlocked display " + displayId);
+ return;
+ }
+
final KeyguardDisplayState state = getDisplayState(displayId);
final boolean aodChanged = aodShowing != state.mAodShowing;
// If keyguard is going away, but SystemUI aborted the transition, need to reset state.
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
index fcfe27397df6c..68e90fbadd0c3 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -16,20 +16,27 @@
package com.android.server.display;
+import static android.Manifest.permission.ADD_ALWAYS_UNLOCKED_DISPLAY;
+import static android.Manifest.permission.ADD_TRUSTED_DISPLAY;
+
import static com.android.server.display.VirtualDisplayAdapter.UNIQUE_ID_PREFIX;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.PropertyInvalidatedCache;
import android.compat.testing.PlatformCompatChangeRule;
import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.pm.PackageManager;
import android.graphics.Insets;
import android.graphics.Rect;
import android.hardware.display.BrightnessConfiguration;
@@ -48,6 +55,8 @@ import android.os.IBinder;
import android.os.MessageQueue;
import android.os.Process;
import android.platform.test.annotations.Presubmit;
+import android.provider.DeviceConfig;
+import android.provider.DeviceConfigInterface;
import android.view.Display;
import android.view.DisplayCutout;
import android.view.DisplayEventReceiver;
@@ -55,7 +64,9 @@ import android.view.DisplayInfo;
import android.view.Surface;
import android.view.SurfaceControl;
+import androidx.annotation.NonNull;
import androidx.test.InstrumentationRegistry;
+import androidx.test.core.app.ApplicationProvider;
import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -65,6 +76,7 @@ import com.android.server.SystemService;
import com.android.server.display.DisplayManagerService.SyncRoot;
import com.android.server.lights.LightsManager;
import com.android.server.sensors.SensorManagerInternal;
+import com.android.server.testutils.FakeDeviceConfigInterface;
import com.android.server.wm.WindowManagerInternal;
import com.google.common.collect.ImmutableMap;
@@ -105,6 +117,7 @@ public class DisplayManagerServiceTest {
public TestRule compatChangeRule = new PlatformCompatChangeRule();
private Context mContext;
+ private FakeDeviceConfigInterface mDeviceConfig;
private final DisplayManagerService.Injector mShortMockedInjector =
new DisplayManagerService.Injector() {
@@ -127,6 +140,12 @@ public class DisplayManagerServiceTest {
return new VirtualDisplayAdapter(syncRoot, context, handler, displayAdapterListener,
(String name, boolean secure) -> mMockDisplayToken);
}
+
+ @NonNull
+ @Override
+ public DeviceConfigInterface getDeviceConfig() {
+ return mDeviceConfig;
+ }
}
private final DisplayManagerService.Injector mBasicInjector = new BasicInjector();
@@ -169,7 +188,8 @@ public class DisplayManagerServiceTest {
LocalServices.removeServiceForTest(SensorManagerInternal.class);
LocalServices.addService(SensorManagerInternal.class, mMockSensorManagerInternal);
- mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ mContext = spy(new ContextWrapper(ApplicationProvider.getApplicationContext()));
+ mDeviceConfig = new FakeDeviceConfigInterface();
// Disable binder caches in this process.
PropertyInvalidatedCache.disableForTestMode();
@@ -618,6 +638,25 @@ public class DisplayManagerServiceTest {
assertEquals(displayManager.getVirtualDisplaySurfaceInternal(mMockAppToken), surface);
}
+ /**
+ * Tests that specifying the VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED flag is processed correctly
+ * when it is allowed by DeviceConfig.
+ */
+ @Test
+ public void testCreateVirtualDisplay_alwaysUnlockedAllowed() {
+ testCreateVirtualDisplay_alwaysUnlocked(/*deviceConfigAllows*/ true, /*flagExpected*/ true);
+ }
+
+ /**
+ * Tests that specifying the VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED flag when DeviceConfig does
+ * not allow it results in the flag being stripped from the final flags.
+ */
+ @Test
+ public void testCreateVirtualDisplay_alwaysUnlockedDisallowed() {
+ testCreateVirtualDisplay_alwaysUnlocked(
+ /*deviceConfigAllows*/ false, /*flagExpected*/ false);
+ }
+
/**
* Tests that there is a display change notification if the frame rate override
* list is updated.
@@ -1042,6 +1081,45 @@ public class DisplayManagerServiceTest {
assertEquals(expectedRefreshRate, displayInfo.getRefreshRate(), 0.01f);
}
+ private void testCreateVirtualDisplay_alwaysUnlocked(boolean deviceConfigAllows,
+ boolean flagExpected) {
+ mDeviceConfig.setProperty(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
+ DisplayManager.DeviceConfig.KEY_ALLOW_ALWAYS_UNLOCKED_VIRTUAL_DISPLAYS,
+ deviceConfigAllows ? "true" : "false", /*makeDefault*/ false);
+
+ DisplayManagerService displayManager =
+ new DisplayManagerService(mContext, mBasicInjector);
+ registerDefaultDisplays(displayManager);
+ String uniqueId = "uniqueId --- ALWAYS_UNLOCKED";
+ int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP
+ | DisplayManager.VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED;
+
+ DisplayManagerService.BinderService bs = displayManager.new BinderService();
+ when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
+
+ when(mContext.checkCallingPermission(ADD_ALWAYS_UNLOCKED_DISPLAY)).thenReturn(
+ PackageManager.PERMISSION_GRANTED);
+ when(mContext.checkCallingPermission(ADD_TRUSTED_DISPLAY)).thenReturn(
+ PackageManager.PERMISSION_GRANTED);
+
+ final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
+ VIRTUAL_DISPLAY_NAME, 600, 800, 320);
+ builder.setFlags(flags);
+ builder.setUniqueId(uniqueId);
+
+ int displayId = bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */,
+ null /* projection */, PACKAGE_NAME);
+ displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
+ displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
+ DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayId);
+ assertNotNull(ddi);
+ if (flagExpected) {
+ assertNotEquals(ddi.flags & DisplayDeviceInfo.FLAG_ALWAYS_UNLOCKED, 0);
+ } else {
+ assertEquals(ddi.flags & DisplayDeviceInfo.FLAG_ALWAYS_UNLOCKED, 0);
+ }
+ }
+
private int getDisplayIdForDisplayDevice(
DisplayManagerService displayManager,
DisplayManagerService.BinderService displayManagerBinderService,
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
index afc2b8748abb6..e0072b441577a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -35,6 +35,7 @@ import static com.android.server.wm.ActivityRecord.State.STOPPING;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -63,6 +64,8 @@ import android.os.LocaleList;
import android.os.PowerManager;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
+import android.view.Display;
+import android.view.DisplayInfo;
import android.view.IDisplayWindowListener;
import androidx.test.filters.MediumTest;
@@ -220,6 +223,66 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase {
assertEquals(1, removed.size());
}
+ @Test
+ public void testSetLockScreenShownWithVirtualDisplay() {
+ DisplayInfo displayInfo = new DisplayInfo();
+ displayInfo.copyFrom(mDisplayInfo);
+ displayInfo.type = Display.TYPE_VIRTUAL;
+ DisplayContent virtualDisplay = createNewDisplay(displayInfo);
+
+ // Make sure we're starting out with 2 unlocked displays
+ assertEquals(2, mRootWindowContainer.getChildCount());
+ mRootWindowContainer.forAllDisplays(displayContent -> {
+ assertFalse(displayContent.isKeyguardLocked());
+ assertFalse(displayContent.isAodShowing());
+ });
+
+ // Check that setLockScreenShown locks both displays
+ mAtm.setLockScreenShown(true, true);
+ mRootWindowContainer.forAllDisplays(displayContent -> {
+ assertTrue(displayContent.isKeyguardLocked());
+ assertTrue(displayContent.isAodShowing());
+ });
+
+ // Check setLockScreenShown unlocking both displays
+ mAtm.setLockScreenShown(false, false);
+ mRootWindowContainer.forAllDisplays(displayContent -> {
+ assertFalse(displayContent.isKeyguardLocked());
+ assertFalse(displayContent.isAodShowing());
+ });
+ }
+
+ @Test
+ public void testSetLockScreenShownWithAlwaysUnlockedVirtualDisplay() {
+ assertEquals(Display.DEFAULT_DISPLAY, mRootWindowContainer.getChildAt(0).getDisplayId());
+
+ DisplayInfo displayInfo = new DisplayInfo();
+ displayInfo.copyFrom(mDisplayInfo);
+ displayInfo.type = Display.TYPE_VIRTUAL;
+ displayInfo.displayGroupId = Display.DEFAULT_DISPLAY_GROUP + 1;
+ displayInfo.flags = Display.FLAG_OWN_DISPLAY_GROUP | Display.FLAG_ALWAYS_UNLOCKED;
+ DisplayContent newDisplay = createNewDisplay(displayInfo);
+
+ // Make sure we're starting out with 2 unlocked displays
+ assertEquals(2, mRootWindowContainer.getChildCount());
+ mRootWindowContainer.forAllDisplays(displayContent -> {
+ assertFalse(displayContent.isKeyguardLocked());
+ assertFalse(displayContent.isAodShowing());
+ });
+
+ // setLockScreenShown should only lock the default display, not the virtual one
+ mAtm.setLockScreenShown(true, true);
+
+ assertTrue(mDefaultDisplay.isKeyguardLocked());
+ assertTrue(mDefaultDisplay.isAodShowing());
+
+ DisplayContent virtualDisplay = mRootWindowContainer.getDisplayContent(
+ newDisplay.getDisplayId());
+ assertNotEquals(Display.DEFAULT_DISPLAY, virtualDisplay.getDisplayId());
+ assertFalse(virtualDisplay.isKeyguardLocked());
+ assertFalse(virtualDisplay.isAodShowing());
+ }
+
/*
a test to verify b/144045134 - ignore PIP mode request for destroyed activity.
mocks r.getParent() to return null to cause NPE inside enterPipRunnable#run() in
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index db60b98a7785e..9a33e23fcb30b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -266,6 +266,7 @@ public class SystemServicesTestRule implements TestRule {
doNothing().when(amInternal).updateOomLevelsForDisplay(anyInt());
doNothing().when(amInternal).broadcastGlobalConfigurationChanged(anyInt(), anyBoolean());
doNothing().when(amInternal).cleanUpServices(anyInt(), any(), any());
+ doNothing().when(amInternal).reportCurKeyguardUsageEvent(anyBoolean());
doReturn(UserHandle.USER_SYSTEM).when(amInternal).getCurrentUserId();
doReturn(TEST_USER_PROFILE_IDS).when(amInternal).getCurrentProfileIds();
doReturn(true).when(amInternal).isUserRunning(anyInt(), anyInt());