Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 299b7c44 authored by Dorin Drimus's avatar Dorin Drimus
Browse files

Protect virtual cameras on default policy with a flag

Add `external_camera_default_policy` flag to separate adding cameras on
the default device from the rest of the virtual external cameras support
and virtual camera metadata feature.

This is to decouple and separate any privacy concerns for the part that
still needs to be discussed by pwg when they have time from the rest of
the feature for which there are no concerns.

Bug: 431724713
Bug: 371167033
Test: atest VirtualCameraControllerTest
Test: atest VirtualCameraTest
Flag: android.companion.virtualdevice.flags.external_camera_default_policy
Change-Id: I8b1142d7110c9c7bdcc99c2e536a7682981452b3
parent 21439d00
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -239,3 +239,13 @@ flag {
        purpose: PURPOSE_BUGFIX
    }
}

flag {
    name: "external_camera_default_policy"
    namespace: "virtual_devices"
    description: "Allow virtual external cameras to be aded to a virtual device with a default camera policy"
    bug: "371167033"
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}
+13 −2
Original line number Diff line number Diff line
@@ -195,6 +195,13 @@ public final class VirtualCameraController implements IBinder.DeathRecipient {
    }

    private void checkConfigByPolicy(VirtualCameraConfig config) {
        // Don't allow any cameras on the default policy if the flag is disabled.
        if (!Flags.externalCameraDefaultPolicy() && mCameraPolicy == DEVICE_POLICY_DEFAULT) {
            throw new IllegalArgumentException(
                    "Cannot create virtual camera with DEVICE_POLICY_DEFAULT for "
                        + "POLICY_TYPE_CAMERA.");
        }

        // Multiple external cameras are allowed on any policy
        if (Flags.externalVirtualCameras()
                && CameraMetadata.LENS_FACING_EXTERNAL == config.getLensFacing()) {
@@ -259,8 +266,12 @@ public final class VirtualCameraController implements IBinder.DeathRecipient {
    private boolean registerCameraWithService(VirtualCameraConfig config) throws RemoteException {
        VirtualCameraConfiguration serviceConfiguration = getServiceCameraConfiguration(config);
        synchronized (mServiceLock) {
            int ownerDeviceId =
                    mCameraPolicy != DEVICE_POLICY_DEFAULT ? mDeviceId : Context.DEVICE_ID_DEFAULT;
            int ownerDeviceId = mDeviceId;

            if (Flags.externalCameraDefaultPolicy() && mCameraPolicy == DEVICE_POLICY_DEFAULT) {
                ownerDeviceId = Context.DEVICE_ID_DEFAULT;
            }

            return mVirtualCameraService.registerCamera(config.getCallback().asBinder(),
                    serviceConfiguration, ownerDeviceId);
        }
+25 −9
Original line number Diff line number Diff line
@@ -240,7 +240,7 @@ public class VirtualCameraControllerTest {
    }

    @Test
    @EnableFlags(Flags.FLAG_EXTERNAL_VIRTUAL_CAMERAS)
    @EnableFlags({Flags.FLAG_EXTERNAL_VIRTUAL_CAMERAS, Flags.FLAG_EXTERNAL_CAMERA_DEFAULT_POLICY})
    public void registerCamera_withDefaultCameraPolicy_allowsMultipleExternal() {
        mVirtualCameraController.close();
        mVirtualCameraController = new VirtualCameraController(mVirtualCameraServiceMock,
@@ -259,15 +259,14 @@ public class VirtualCameraControllerTest {

    @Test
    @DisableFlags(Flags.FLAG_EXTERNAL_VIRTUAL_CAMERAS)
    public void registerCamera_withDefaultCameraPolicy_throwsException_whenNotSupported() {
        mVirtualCameraController.close();
        mVirtualCameraController = new VirtualCameraController(mVirtualCameraServiceMock,
                DEVICE_POLICY_DEFAULT, DEVICE_ID);
    public void registerCamera_withDefaultCameraPolicy_throwsException_whenExternalNotSupported() {
        verifyRegisterDefaultPolicyCameraThrowsException();
    }

        assertThrows(IllegalArgumentException.class, () -> mVirtualCameraController.registerCamera(
                createVirtualCameraConfig(CAMERA_WIDTH_1, CAMERA_HEIGHT_1, CAMERA_FORMAT_1,
                        CAMERA_MAX_FPS_1, CAMERA_NAME_1, CAMERA_SENSOR_ORIENTATION_1,
                        LENS_FACING_EXTERNAL), AttributionSource.myAttributionSource()));
    @Test
    @DisableFlags(Flags.FLAG_EXTERNAL_CAMERA_DEFAULT_POLICY)
    public void registerCamera_withDefaultCameraPolicy_throwsException_whenDefaultNotSupported() {
        verifyRegisterDefaultPolicyCameraThrowsException();
    }

    public static void assertVirtualCameraConfigFromCharacteristics(VirtualCameraConfig config,
@@ -424,6 +423,23 @@ public class VirtualCameraControllerTest {
                width, height, format, maxFps, originalConfig.cameraCharacteristics);
    }

    private void verifyRegisterDefaultPolicyCameraThrowsException() {
        mVirtualCameraController.close();
        mVirtualCameraController = new VirtualCameraController(mVirtualCameraServiceMock,
                DEVICE_POLICY_DEFAULT, DEVICE_ID);

        assertThrows(IllegalArgumentException.class, () -> mVirtualCameraController.registerCamera(
                createVirtualCameraConfig(CAMERA_WIDTH_1, CAMERA_HEIGHT_1, CAMERA_FORMAT_1,
                        CAMERA_MAX_FPS_1, CAMERA_NAME_1, CAMERA_SENSOR_ORIENTATION_1,
                        LENS_FACING_EXTERNAL), AttributionSource.myAttributionSource()));

        assertThrows(IllegalArgumentException.class, () -> mVirtualCameraController.registerCamera(
                createVirtualCameraConfig(CAMERA_WIDTH_1, CAMERA_HEIGHT_1, CAMERA_FORMAT_1,
                        CAMERA_MAX_FPS_1, CAMERA_NAME_1, CAMERA_SENSOR_ORIENTATION_1,
                        LENS_FACING_FRONT), AttributionSource.myAttributionSource()));
    }


    @SuppressWarnings("unused") // Parameter for parametrized tests
    private static Integer[] getFixedCamerasLensFacingDirections() {
        return new Integer[]{