Loading core/java/android/companion/virtual/IVirtualDevice.aidl +6 −0 Original line number Diff line number Diff line Loading @@ -90,6 +90,12 @@ interface IVirtualDevice { */ boolean hasCustomAudioInputSupport(); /** * Returns whether this device is allowed to create mirror displays. */ boolean canCreateMirrorDisplays(); /* /* * Turns off all trusted non-mirror displays of the virtual device. */ Loading services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java +9 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ import android.app.PendingIntent; import android.app.admin.DevicePolicyManager; import android.app.compat.CompatChanges; import android.companion.AssociationInfo; import android.companion.AssociationRequest; import android.companion.virtual.ActivityPolicyExemption; import android.companion.virtual.IVirtualDevice; import android.companion.virtual.IVirtualDeviceActivityListener; Loading Loading @@ -155,6 +156,9 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub private static final String PERSISTENT_ID_PREFIX_CDM_ASSOCIATION = "companion:"; private static final List<String> DEVICE_PROFILES_ALLOWING_MIRROR_DISPLAYS = List.of( AssociationRequest.DEVICE_PROFILE_APP_STREAMING); /** * Timeout until {@link #launchPendingIntent} stops waiting for an activity to be launched. */ Loading Loading @@ -1348,6 +1352,11 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub return hasCustomAudioInputSupportInternal(); } @Override public boolean canCreateMirrorDisplays() { return DEVICE_PROFILES_ALLOWING_MIRROR_DISPLAYS.contains(getDeviceProfile()); } private boolean hasCustomAudioInputSupportInternal() { if (!Flags.vdmPublicApis()) { return false; Loading services/core/java/com/android/server/display/DisplayManagerService.java +6 −1 Original line number Diff line number Diff line Loading @@ -1681,7 +1681,12 @@ public final class DisplayManagerService extends SystemService { if (android.companion.virtualdevice.flags.Flags.enableLimitedVdmRole()) { return checkCallingPermission(ADD_MIRROR_DISPLAY, "canCreateMirrorDisplays"); } return virtualDevice != null; try { return virtualDevice.canCreateMirrorDisplays(); } catch (RemoteException e) { Slog.e(TAG, "Unable to query virtual device for permissions", e); return false; } } private boolean canProjectVideo(IMediaProjection projection) { Loading services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java +33 −16 Original line number Diff line number Diff line Loading @@ -123,7 +123,6 @@ import android.os.RemoteException; import android.os.SystemProperties; import android.os.UserManager; import android.os.test.FakePermissionEnforcer; import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; Loading Loading @@ -1387,21 +1386,23 @@ public class DisplayManagerServiceTest { } /** * Tests that it's not allowed to create an auto-mirror virtual display without * CAPTURE_VIDEO_OUTPUT permission or a virtual device that can mirror displays * Tests that it is not allowed to create an auto-mirror virtual display for a virtual device * without ADD_MIRROR_DISPLAY permission / without the mirror display capability. */ @EnableFlags(android.companion.virtualdevice.flags.Flags.FLAG_ENABLE_LIMITED_VDM_ROLE) @Test public void createAutoMirrorDisplay_withoutPermissionOrAllowedVirtualDevice_throwsException() throws Exception { public void createAutoMirrorDisplay_withoutPermission_throwsException() throws Exception { DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector); DisplayManagerInternal localService = displayManager.new LocalService(); registerDefaultDisplays(displayManager); when(mMockAppToken.asBinder()).thenReturn(mMockAppToken); IVirtualDevice virtualDevice = mock(IVirtualDevice.class); when(virtualDevice.getDeviceId()).thenReturn(1); if (android.companion.virtualdevice.flags.Flags.enableLimitedVdmRole()) { when(mContext.checkCallingPermission(ADD_MIRROR_DISPLAY)) .thenReturn(PackageManager.PERMISSION_DENIED); } else { when(virtualDevice.canCreateMirrorDisplays()).thenReturn(false); } when(mIVirtualDeviceManager.isValidVirtualDeviceId(1)).thenReturn(true); when(mContext.checkCallingPermission(CAPTURE_VIDEO_OUTPUT)).thenReturn( PackageManager.PERMISSION_DENIED); Loading Loading @@ -1432,8 +1433,12 @@ public class DisplayManagerServiceTest { when(mMockAppToken.asBinder()).thenReturn(mMockAppToken); IVirtualDevice virtualDevice = mock(IVirtualDevice.class); when(virtualDevice.getDeviceId()).thenReturn(1); if (android.companion.virtualdevice.flags.Flags.enableLimitedVdmRole()) { when(mContext.checkCallingPermission(ADD_MIRROR_DISPLAY)) .thenReturn(PackageManager.PERMISSION_GRANTED); } else { when(virtualDevice.canCreateMirrorDisplays()).thenReturn(true); } when(mIVirtualDeviceManager.isValidVirtualDeviceId(1)).thenReturn(true); // Create an auto-mirror virtual display using a virtual device. Loading Loading @@ -1466,8 +1471,12 @@ public class DisplayManagerServiceTest { when(mMockAppToken.asBinder()).thenReturn(mMockAppToken); IVirtualDevice virtualDevice = mock(IVirtualDevice.class); when(virtualDevice.getDeviceId()).thenReturn(1); if (android.companion.virtualdevice.flags.Flags.enableLimitedVdmRole()) { when(mContext.checkCallingPermission(ADD_MIRROR_DISPLAY)) .thenReturn(PackageManager.PERMISSION_GRANTED); } else { when(virtualDevice.canCreateMirrorDisplays()).thenReturn(true); } when(mIVirtualDeviceManager.isValidVirtualDeviceId(1)).thenReturn(true); // Create an auto-mirror virtual display using a virtual device. Loading Loading @@ -1534,8 +1543,12 @@ public class DisplayManagerServiceTest { when(mMockAppToken.asBinder()).thenReturn(mMockAppToken); IVirtualDevice virtualDevice = mock(IVirtualDevice.class); when(virtualDevice.getDeviceId()).thenReturn(1); if (android.companion.virtualdevice.flags.Flags.enableLimitedVdmRole()) { when(mContext.checkCallingPermission(ADD_MIRROR_DISPLAY)) .thenReturn(PackageManager.PERMISSION_GRANTED); } else { when(virtualDevice.canCreateMirrorDisplays()).thenReturn(true); } when(mIVirtualDeviceManager.isValidVirtualDeviceId(1)).thenReturn(true); when(mContext.checkCallingPermission(ADD_ALWAYS_UNLOCKED_DISPLAY)) .thenReturn(PackageManager.PERMISSION_GRANTED); Loading Loading @@ -1571,8 +1584,12 @@ public class DisplayManagerServiceTest { when(mMockAppToken.asBinder()).thenReturn(mMockAppToken); IVirtualDevice virtualDevice = mock(IVirtualDevice.class); when(virtualDevice.getDeviceId()).thenReturn(1); if (android.companion.virtualdevice.flags.Flags.enableLimitedVdmRole()) { when(mContext.checkCallingPermission(ADD_MIRROR_DISPLAY)) .thenReturn(PackageManager.PERMISSION_GRANTED); } else { when(virtualDevice.canCreateMirrorDisplays()).thenReturn(true); } when(mIVirtualDeviceManager.isValidVirtualDeviceId(1)).thenReturn(true); // Create an auto-mirror virtual display using a virtual device. Loading Loading
core/java/android/companion/virtual/IVirtualDevice.aidl +6 −0 Original line number Diff line number Diff line Loading @@ -90,6 +90,12 @@ interface IVirtualDevice { */ boolean hasCustomAudioInputSupport(); /** * Returns whether this device is allowed to create mirror displays. */ boolean canCreateMirrorDisplays(); /* /* * Turns off all trusted non-mirror displays of the virtual device. */ Loading
services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java +9 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ import android.app.PendingIntent; import android.app.admin.DevicePolicyManager; import android.app.compat.CompatChanges; import android.companion.AssociationInfo; import android.companion.AssociationRequest; import android.companion.virtual.ActivityPolicyExemption; import android.companion.virtual.IVirtualDevice; import android.companion.virtual.IVirtualDeviceActivityListener; Loading Loading @@ -155,6 +156,9 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub private static final String PERSISTENT_ID_PREFIX_CDM_ASSOCIATION = "companion:"; private static final List<String> DEVICE_PROFILES_ALLOWING_MIRROR_DISPLAYS = List.of( AssociationRequest.DEVICE_PROFILE_APP_STREAMING); /** * Timeout until {@link #launchPendingIntent} stops waiting for an activity to be launched. */ Loading Loading @@ -1348,6 +1352,11 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub return hasCustomAudioInputSupportInternal(); } @Override public boolean canCreateMirrorDisplays() { return DEVICE_PROFILES_ALLOWING_MIRROR_DISPLAYS.contains(getDeviceProfile()); } private boolean hasCustomAudioInputSupportInternal() { if (!Flags.vdmPublicApis()) { return false; Loading
services/core/java/com/android/server/display/DisplayManagerService.java +6 −1 Original line number Diff line number Diff line Loading @@ -1681,7 +1681,12 @@ public final class DisplayManagerService extends SystemService { if (android.companion.virtualdevice.flags.Flags.enableLimitedVdmRole()) { return checkCallingPermission(ADD_MIRROR_DISPLAY, "canCreateMirrorDisplays"); } return virtualDevice != null; try { return virtualDevice.canCreateMirrorDisplays(); } catch (RemoteException e) { Slog.e(TAG, "Unable to query virtual device for permissions", e); return false; } } private boolean canProjectVideo(IMediaProjection projection) { Loading
services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java +33 −16 Original line number Diff line number Diff line Loading @@ -123,7 +123,6 @@ import android.os.RemoteException; import android.os.SystemProperties; import android.os.UserManager; import android.os.test.FakePermissionEnforcer; import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; Loading Loading @@ -1387,21 +1386,23 @@ public class DisplayManagerServiceTest { } /** * Tests that it's not allowed to create an auto-mirror virtual display without * CAPTURE_VIDEO_OUTPUT permission or a virtual device that can mirror displays * Tests that it is not allowed to create an auto-mirror virtual display for a virtual device * without ADD_MIRROR_DISPLAY permission / without the mirror display capability. */ @EnableFlags(android.companion.virtualdevice.flags.Flags.FLAG_ENABLE_LIMITED_VDM_ROLE) @Test public void createAutoMirrorDisplay_withoutPermissionOrAllowedVirtualDevice_throwsException() throws Exception { public void createAutoMirrorDisplay_withoutPermission_throwsException() throws Exception { DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector); DisplayManagerInternal localService = displayManager.new LocalService(); registerDefaultDisplays(displayManager); when(mMockAppToken.asBinder()).thenReturn(mMockAppToken); IVirtualDevice virtualDevice = mock(IVirtualDevice.class); when(virtualDevice.getDeviceId()).thenReturn(1); if (android.companion.virtualdevice.flags.Flags.enableLimitedVdmRole()) { when(mContext.checkCallingPermission(ADD_MIRROR_DISPLAY)) .thenReturn(PackageManager.PERMISSION_DENIED); } else { when(virtualDevice.canCreateMirrorDisplays()).thenReturn(false); } when(mIVirtualDeviceManager.isValidVirtualDeviceId(1)).thenReturn(true); when(mContext.checkCallingPermission(CAPTURE_VIDEO_OUTPUT)).thenReturn( PackageManager.PERMISSION_DENIED); Loading Loading @@ -1432,8 +1433,12 @@ public class DisplayManagerServiceTest { when(mMockAppToken.asBinder()).thenReturn(mMockAppToken); IVirtualDevice virtualDevice = mock(IVirtualDevice.class); when(virtualDevice.getDeviceId()).thenReturn(1); if (android.companion.virtualdevice.flags.Flags.enableLimitedVdmRole()) { when(mContext.checkCallingPermission(ADD_MIRROR_DISPLAY)) .thenReturn(PackageManager.PERMISSION_GRANTED); } else { when(virtualDevice.canCreateMirrorDisplays()).thenReturn(true); } when(mIVirtualDeviceManager.isValidVirtualDeviceId(1)).thenReturn(true); // Create an auto-mirror virtual display using a virtual device. Loading Loading @@ -1466,8 +1471,12 @@ public class DisplayManagerServiceTest { when(mMockAppToken.asBinder()).thenReturn(mMockAppToken); IVirtualDevice virtualDevice = mock(IVirtualDevice.class); when(virtualDevice.getDeviceId()).thenReturn(1); if (android.companion.virtualdevice.flags.Flags.enableLimitedVdmRole()) { when(mContext.checkCallingPermission(ADD_MIRROR_DISPLAY)) .thenReturn(PackageManager.PERMISSION_GRANTED); } else { when(virtualDevice.canCreateMirrorDisplays()).thenReturn(true); } when(mIVirtualDeviceManager.isValidVirtualDeviceId(1)).thenReturn(true); // Create an auto-mirror virtual display using a virtual device. Loading Loading @@ -1534,8 +1543,12 @@ public class DisplayManagerServiceTest { when(mMockAppToken.asBinder()).thenReturn(mMockAppToken); IVirtualDevice virtualDevice = mock(IVirtualDevice.class); when(virtualDevice.getDeviceId()).thenReturn(1); if (android.companion.virtualdevice.flags.Flags.enableLimitedVdmRole()) { when(mContext.checkCallingPermission(ADD_MIRROR_DISPLAY)) .thenReturn(PackageManager.PERMISSION_GRANTED); } else { when(virtualDevice.canCreateMirrorDisplays()).thenReturn(true); } when(mIVirtualDeviceManager.isValidVirtualDeviceId(1)).thenReturn(true); when(mContext.checkCallingPermission(ADD_ALWAYS_UNLOCKED_DISPLAY)) .thenReturn(PackageManager.PERMISSION_GRANTED); Loading Loading @@ -1571,8 +1584,12 @@ public class DisplayManagerServiceTest { when(mMockAppToken.asBinder()).thenReturn(mMockAppToken); IVirtualDevice virtualDevice = mock(IVirtualDevice.class); when(virtualDevice.getDeviceId()).thenReturn(1); if (android.companion.virtualdevice.flags.Flags.enableLimitedVdmRole()) { when(mContext.checkCallingPermission(ADD_MIRROR_DISPLAY)) .thenReturn(PackageManager.PERMISSION_GRANTED); } else { when(virtualDevice.canCreateMirrorDisplays()).thenReturn(true); } when(mIVirtualDeviceManager.isValidVirtualDeviceId(1)).thenReturn(true); // Create an auto-mirror virtual display using a virtual device. Loading