diff options
5 files changed, 54 insertions, 17 deletions
diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 02cd00d0f86a..860089fb326f 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -3579,6 +3579,7 @@ package android.companion.virtual { field @FlaggedApi("android.companion.virtualdevice.flags.activity_control_api") public static final int POLICY_TYPE_BLOCKED_ACTIVITY = 6; // 0x6 field @FlaggedApi("android.companion.virtual.flags.virtual_camera") public static final int POLICY_TYPE_CAMERA = 5; // 0x5 field @FlaggedApi("android.companion.virtual.flags.cross_device_clipboard") public static final int POLICY_TYPE_CLIPBOARD = 4; // 0x4 + field @FlaggedApi("android.companion.virtualdevice.flags.default_device_camera_access_policy") public static final int POLICY_TYPE_DEFAULT_DEVICE_CAMERA_ACCESS = 7; // 0x7 field public static final int POLICY_TYPE_RECENTS = 2; // 0x2 field public static final int POLICY_TYPE_SENSORS = 0; // 0x0 } diff --git a/core/java/android/companion/virtual/VirtualDeviceParams.java b/core/java/android/companion/virtual/VirtualDeviceParams.java index 65f9cbefb052..6dad015cd63b 100644 --- a/core/java/android/companion/virtual/VirtualDeviceParams.java +++ b/core/java/android/companion/virtual/VirtualDeviceParams.java @@ -160,7 +160,7 @@ public final class VirtualDeviceParams implements Parcelable { */ @IntDef(prefix = "POLICY_TYPE_", value = {POLICY_TYPE_SENSORS, POLICY_TYPE_AUDIO, POLICY_TYPE_RECENTS, POLICY_TYPE_ACTIVITY, POLICY_TYPE_CLIPBOARD, POLICY_TYPE_CAMERA, - POLICY_TYPE_BLOCKED_ACTIVITY}) + POLICY_TYPE_BLOCKED_ACTIVITY, POLICY_TYPE_DEFAULT_DEVICE_CAMERA_ACCESS}) @Retention(RetentionPolicy.SOURCE) @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) public @interface PolicyType {} @@ -301,6 +301,21 @@ public final class VirtualDeviceParams implements Parcelable { @FlaggedApi(android.companion.virtualdevice.flags.Flags.FLAG_ACTIVITY_CONTROL_API) public static final int POLICY_TYPE_BLOCKED_ACTIVITY = 6; + /** + * Tells the virtual device framework how to handle camera access of the default device by apps + * running on the virtual device. + * + * <ul> + * <li>{@link #DEVICE_POLICY_DEFAULT}: Default device camera access will be allowed. + * <li>{@link #DEVICE_POLICY_CUSTOM}: Default device camera access will be blocked. + * </ul> + * + * @see Context#DEVICE_ID_DEFAULT + */ + @FlaggedApi(android.companion.virtualdevice.flags.Flags + .FLAG_DEFAULT_DEVICE_CAMERA_ACCESS_POLICY) + public static final int POLICY_TYPE_DEFAULT_DEVICE_CAMERA_ACCESS = 7; + private final int mLockState; @NonNull private final ArraySet<UserHandle> mUsersWithMatchingAccounts; @NavigationPolicy @@ -696,7 +711,7 @@ public final class VirtualDeviceParams implements Parcelable { @NonNull public static final Parcelable.Creator<VirtualDeviceParams> CREATOR = - new Parcelable.Creator<VirtualDeviceParams>() { + new Parcelable.Creator<>() { public VirtualDeviceParams createFromParcel(Parcel in) { return new VirtualDeviceParams(in); } @@ -1213,6 +1228,10 @@ public final class VirtualDeviceParams implements Parcelable { mDevicePolicies.delete(POLICY_TYPE_CAMERA); } + if (!android.companion.virtualdevice.flags.Flags.defaultDeviceCameraAccessPolicy()) { + mDevicePolicies.delete(POLICY_TYPE_DEFAULT_DEVICE_CAMERA_ACCESS); + } + if (!android.companion.virtualdevice.flags.Flags.activityControlApi()) { mDevicePolicies.delete(POLICY_TYPE_BLOCKED_ACTIVITY); } diff --git a/core/java/android/companion/virtual/flags.aconfig b/core/java/android/companion/virtual/flags.aconfig index fc9c94dd5b0f..3e6919bac5fa 100644 --- a/core/java/android/companion/virtual/flags.aconfig +++ b/core/java/android/companion/virtual/flags.aconfig @@ -67,13 +67,6 @@ flag { } flag { - name: "stream_camera" - namespace: "virtual_devices" - description: "Enable streaming camera to Virtual Devices" - bug: "291740640" -} - -flag { name: "persistent_device_id_api" is_exported: true namespace: "virtual_devices" diff --git a/services/companion/java/com/android/server/companion/virtual/CameraAccessController.java b/services/companion/java/com/android/server/companion/virtual/CameraAccessController.java index ef39846f4750..8a4b1faf2df9 100644 --- a/services/companion/java/com/android/server/companion/virtual/CameraAccessController.java +++ b/services/companion/java/com/android/server/companion/virtual/CameraAccessController.java @@ -59,14 +59,14 @@ class CameraAccessController extends CameraManager.AvailabilityCallback implemen private int mObserverCount = 0; @GuardedBy("mLock") - private ArrayMap<String, InjectionSessionData> mPackageToSessionData = new ArrayMap<>(); + private final ArrayMap<String, InjectionSessionData> mPackageToSessionData = new ArrayMap<>(); /** * Mapping from camera ID to open camera app associations. Key is the camera id, value is the * information of the app's uid and package name. */ @GuardedBy("mLock") - private ArrayMap<String, OpenCameraInfo> mAppsToBlockOnVirtualDevice = new ArrayMap<>(); + private final ArrayMap<String, OpenCameraInfo> mAppsToBlockOnVirtualDevice = new ArrayMap<>(); static class InjectionSessionData { public int appUid; @@ -179,6 +179,15 @@ class CameraAccessController extends CameraManager.AvailabilityCallback implemen Slog.w(TAG, "Unexpected close with observers remaining: " + mObserverCount); } } + // Clean up camera injection sessions (if any). + synchronized (mLock) { + for (InjectionSessionData sessionData : mPackageToSessionData.values()) { + for (CameraInjectionSession session : sessionData.cameraIdToSession.values()) { + session.close(); + } + } + mPackageToSessionData.clear(); + } mCameraManager.unregisterAvailabilityCallback(this); } diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java index f87e3c338df7..604aaa74306f 100644 --- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java +++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java @@ -17,6 +17,7 @@ package com.android.server.companion.virtual; import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT; +import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_DEFAULT_DEVICE_CAMERA_ACCESS; import static android.media.AudioManager.AUDIO_SESSION_ID_GENERATE; import static com.android.server.wm.ActivityInterceptorCallback.VIRTUAL_DEVICE_SERVICE_ORDERED_ID; @@ -27,6 +28,7 @@ import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SuppressLint; import android.app.ActivityOptions; +import android.app.compat.CompatChanges; import android.companion.AssociationInfo; import android.companion.AssociationRequest; import android.companion.CompanionDeviceManager; @@ -41,11 +43,14 @@ import android.companion.virtual.VirtualDeviceParams; import android.companion.virtual.flags.Flags; import android.companion.virtual.sensor.VirtualSensor; import android.companion.virtualnative.IVirtualDeviceManagerNative; +import android.compat.annotation.ChangeId; +import android.compat.annotation.EnabledAfter; import android.content.AttributionSource; import android.content.Context; import android.content.Intent; import android.hardware.display.DisplayManagerInternal; import android.os.Binder; +import android.os.Build; import android.os.Handler; import android.os.IBinder; import android.os.LocaleList; @@ -88,7 +93,6 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; import java.util.stream.Collectors; - @SuppressLint("LongLogTag") public class VirtualDeviceManagerService extends SystemService { @@ -101,6 +105,11 @@ public class VirtualDeviceManagerService extends SystemService { AssociationRequest.DEVICE_PROFILE_APP_STREAMING, AssociationRequest.DEVICE_PROFILE_NEARBY_DEVICE_STREAMING); + /** Enable default device camera access for apps running on virtual devices. */ + @ChangeId + @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) + public static final long ENABLE_DEFAULT_DEVICE_CAMERA_ACCESS = 371173368L; + /** * A virtual device association id corresponding to no CDM association. */ @@ -110,7 +119,7 @@ public class VirtualDeviceManagerService extends SystemService { private final VirtualDeviceManagerImpl mImpl; private final VirtualDeviceManagerNativeImpl mNativeImpl; private final VirtualDeviceManagerInternal mLocalService; - private VirtualDeviceLog mVirtualDeviceLog = new VirtualDeviceLog(getContext()); + private final VirtualDeviceLog mVirtualDeviceLog = new VirtualDeviceLog(getContext()); private final Handler mHandler = new Handler(Looper.getMainLooper()); private final PendingTrampolineMap mPendingTrampolines = new PendingTrampolineMap(mHandler); @@ -236,7 +245,7 @@ public class VirtualDeviceManagerService extends SystemService { } } - void onCameraAccessBlocked(int appUid) { + private void onCameraAccessBlocked(int appUid) { ArrayList<VirtualDeviceImpl> virtualDevicesSnapshot = getVirtualDevicesSnapshot(); for (int i = 0; i < virtualDevicesSnapshot.size(); i++) { VirtualDeviceImpl virtualDevice = virtualDevicesSnapshot.get(i); @@ -248,8 +257,13 @@ public class VirtualDeviceManagerService extends SystemService { } } - CameraAccessController getCameraAccessController(UserHandle userHandle) { - if (Flags.streamCamera()) { + private CameraAccessController getCameraAccessController(UserHandle userHandle, + VirtualDeviceParams params, String callingPackage) { + if (CompatChanges.isChangeEnabled(ENABLE_DEFAULT_DEVICE_CAMERA_ACCESS, callingPackage, + userHandle) + && android.companion.virtualdevice.flags.Flags.defaultDeviceCameraAccessPolicy() + && (params.getDevicePolicy(POLICY_TYPE_DEFAULT_DEVICE_CAMERA_ACCESS) + == DEVICE_POLICY_DEFAULT)) { return null; } int userId = userHandle.getIdentifier(); @@ -496,7 +510,8 @@ public class VirtualDeviceManagerService extends SystemService { final UserHandle userHandle = getCallingUserHandle(); final CameraAccessController cameraAccessController = - getCameraAccessController(userHandle); + getCameraAccessController(userHandle, params, + attributionSource.getPackageName()); final int deviceId = sNextUniqueIndex.getAndIncrement(); final Consumer<ArraySet<Integer>> runningAppsChangedCallback = runningUids -> notifyRunningAppsChanged(deviceId, runningUids); |