Merge "Allow VDM virtual displays to get FLAG_OWN_DISPLAY_GROUP"

This commit is contained in:
Maurice Lam
2022-01-26 05:06:24 +00:00
committed by Android (Google) Code Review
3 changed files with 105 additions and 4 deletions

View File

@@ -194,9 +194,7 @@ public final class VirtualDeviceManager {
/**
* Creates a virtual display for this virtual device. All displays created on the same
* device belongs to the same display group. Requires the ADD_TRUSTED_DISPLAY permission
* to create a virtual display which is not in the default DisplayGroup, and to create
* trusted displays.
* device belongs to the same display group.
*
* @param width The width of the virtual display in pixels, must be greater than 0.
* @param height The height of the virtual display in pixels, must be greater than 0.

View File

@@ -1318,7 +1318,9 @@ public final class DisplayManagerService extends SystemService {
if (callingUid != Process.SYSTEM_UID
&& (flags & VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP) != 0) {
if (!checkCallingPermission(ADD_TRUSTED_DISPLAY, "createVirtualDisplay()")) {
// The virtualDevice instance has been validated above using isValidVirtualDevice
if (virtualDevice == null
&& !checkCallingPermission(ADD_TRUSTED_DISPLAY, "createVirtualDisplay()")) {
throw new SecurityException("Requires ADD_TRUSTED_DISPLAY permission to "
+ "create a virtual display which is not in the default DisplayGroup.");
}

View File

@@ -33,6 +33,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.PropertyInvalidatedCache;
import android.companion.virtual.IVirtualDevice;
import android.compat.testing.PlatformCompatChangeRule;
import android.content.Context;
import android.content.ContextWrapper;
@@ -73,6 +74,7 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.companion.virtual.VirtualDeviceManagerInternal;
import com.android.server.display.DisplayManagerService.SyncRoot;
import com.android.server.lights.LightsManager;
import com.android.server.sensors.SensorManagerInternal;
@@ -167,6 +169,7 @@ public class DisplayManagerServiceTest {
};
@Mock InputManagerInternal mMockInputManagerInternal;
@Mock VirtualDeviceManagerInternal mMockVirtualDeviceManagerInternal;
@Mock IVirtualDisplayCallback.Stub mMockAppToken;
@Mock IVirtualDisplayCallback.Stub mMockAppToken2;
@Mock WindowManagerInternal mMockWindowManagerInternal;
@@ -187,6 +190,9 @@ public class DisplayManagerServiceTest {
LocalServices.addService(LightsManager.class, mMockLightsManager);
LocalServices.removeServiceForTest(SensorManagerInternal.class);
LocalServices.addService(SensorManagerInternal.class, mMockSensorManagerInternal);
LocalServices.removeServiceForTest(VirtualDeviceManagerInternal.class);
LocalServices.addService(
VirtualDeviceManagerInternal.class, mMockVirtualDeviceManagerInternal);
mContext = spy(new ContextWrapper(ApplicationProvider.getApplicationContext()));
mDeviceConfig = new FakeDeviceConfigInterface();
@@ -660,6 +666,101 @@ public class DisplayManagerServiceTest {
/*deviceConfigAllows*/ false, /*flagExpected*/ false);
}
/**
* Tests that specifying VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP is allowed when the permission
* ADD_TRUSTED_DISPLAY is granted.
*/
@Test
public void testOwnDisplayGroup_allowCreationWithAddTrustedDisplayPermission() {
DisplayManagerService displayManager =
new DisplayManagerService(mContext, mBasicInjector);
registerDefaultDisplays(displayManager);
DisplayManagerService.BinderService bs = displayManager.new BinderService();
when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
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(DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP);
builder.setUniqueId("uniqueId --- OWN_DISPLAY_GROUP");
int displayId = bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */,
null /* projection */, null /* virtualDeviceToken */, PACKAGE_NAME);
displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayId);
assertNotNull(ddi);
assertNotEquals(0, ddi.flags & DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP);
}
/**
* Tests that specifying VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP is blocked when the permission
* ADD_TRUSTED_DISPLAY is denied.
*/
@Test
public void testOwnDisplayGroup_withoutAddTrustedDisplayPermission_throwsSecurityException() {
DisplayManagerService displayManager =
new DisplayManagerService(mContext, mBasicInjector);
registerDefaultDisplays(displayManager);
DisplayManagerService.BinderService bs = displayManager.new BinderService();
when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
when(mContext.checkCallingPermission(ADD_TRUSTED_DISPLAY)).thenReturn(
PackageManager.PERMISSION_DENIED);
final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
VIRTUAL_DISPLAY_NAME, 600, 800, 320);
builder.setFlags(DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP);
builder.setUniqueId("uniqueId --- OWN_DISPLAY_GROUP");
try {
bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */,
null /* projection */, null /* virtualDeviceToken */, PACKAGE_NAME);
fail("Creating virtual display with VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP without "
+ "ADD_TRUSTED_DISPLAY permission should throw SecurityException.");
} catch (SecurityException e) {
// SecurityException is expected
}
}
/**
* Tests that specifying VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP is allowed when called with
* a virtual device, even if ADD_TRUSTED_DISPLAY is not granted.
*/
@Test
public void testOwnDisplayGroup_allowCreationWithVirtualDevice() {
DisplayManagerService displayManager =
new DisplayManagerService(mContext, mBasicInjector);
registerDefaultDisplays(displayManager);
DisplayManagerService.BinderService bs = displayManager.new BinderService();
when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
when(mContext.checkCallingPermission(ADD_TRUSTED_DISPLAY)).thenReturn(
PackageManager.PERMISSION_DENIED);
final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
VIRTUAL_DISPLAY_NAME, 600, 800, 320);
builder.setFlags(DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP);
builder.setUniqueId("uniqueId --- OWN_DISPLAY_GROUP");
IVirtualDevice virtualDevice = mock(IVirtualDevice.class);
when(mMockVirtualDeviceManagerInternal.isValidVirtualDevice(virtualDevice))
.thenReturn(true);
int displayId = bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */,
null /* projection */, virtualDevice /* virtualDeviceToken */, PACKAGE_NAME);
displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayId);
assertNotNull(ddi);
assertNotEquals(0, ddi.flags & DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP);
}
/**
* Tests that there is a display change notification if the frame rate override
* list is updated.