Improve virtual camera VDM implementation
- Add hidden API to get virtual camera id
- Avoid binder call inside VirtualCamera constructor
- Also, add CtsVirtualDevicesCameraTestCases to VDM
postsubmit
Test: atest CtsVirtualDevicesCameraTestCases
Bug: 310857519
Change-Id: Id8fcc802ae1561f2ffd5c38f763ee665364accde
diff --git a/core/java/android/companion/virtual/IVirtualDevice.aidl b/core/java/android/companion/virtual/IVirtualDevice.aidl
index 102cbf3..3520c0b 100644
--- a/core/java/android/companion/virtual/IVirtualDevice.aidl
+++ b/core/java/android/companion/virtual/IVirtualDevice.aidl
@@ -246,4 +246,10 @@
*/
@EnforcePermission("CREATE_VIRTUAL_DEVICE")
void unregisterVirtualCamera(in VirtualCameraConfig camera);
+
+ /**
+ * Returns the id of the virtual camera with given config.
+ */
+ @EnforcePermission("CREATE_VIRTUAL_DEVICE")
+ int getVirtualCameraId(in VirtualCameraConfig camera);
}
diff --git a/core/java/android/companion/virtual/VirtualDeviceInternal.java b/core/java/android/companion/virtual/VirtualDeviceInternal.java
index da8277c..9492a62 100644
--- a/core/java/android/companion/virtual/VirtualDeviceInternal.java
+++ b/core/java/android/companion/virtual/VirtualDeviceInternal.java
@@ -19,6 +19,7 @@
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.UserIdInt;
import android.app.PendingIntent;
import android.companion.virtual.audio.VirtualAudioDevice;
@@ -340,12 +341,17 @@
return mVirtualAudioDevice;
}
+ @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
@NonNull
VirtualCamera createVirtualCamera(@NonNull VirtualCameraConfig config) {
- return new VirtualCamera(mVirtualDevice, config);
+ try {
+ mVirtualDevice.registerVirtualCamera(config);
+ return new VirtualCamera(mVirtualDevice, config);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
- @NonNull
void setShowPointerIcon(boolean showPointerIcon) {
try {
mVirtualDevice.setShowPointerIcon(showPointerIcon);
diff --git a/core/java/android/companion/virtual/camera/VirtualCamera.java b/core/java/android/companion/virtual/camera/VirtualCamera.java
index beee86f..52afa4e 100644
--- a/core/java/android/companion/virtual/camera/VirtualCamera.java
+++ b/core/java/android/companion/virtual/camera/VirtualCamera.java
@@ -66,15 +66,8 @@
@RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
public VirtualCamera(
@NonNull IVirtualDevice virtualDevice, @NonNull VirtualCameraConfig config) {
- mVirtualDevice = virtualDevice;
+ mVirtualDevice = Objects.requireNonNull(virtualDevice);
mConfig = Objects.requireNonNull(config);
- Objects.requireNonNull(virtualDevice);
- // TODO(b/310857519): Avoid registration inside constructor.
- try {
- mVirtualDevice.registerVirtualCamera(config);
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
}
/** Returns the configuration of this virtual camera instance. */
@@ -83,6 +76,20 @@
return mConfig;
}
+ /**
+ * Returns the id of this virtual camera instance.
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
+ @NonNull
+ public String getId() {
+ try {
+ return Integer.toString(mVirtualDevice.getVirtualCameraId(mConfig));
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
@Override
@RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
public void close() {
diff --git a/services/companion/java/com/android/server/companion/virtual/TEST_MAPPING b/services/companion/java/com/android/server/companion/virtual/TEST_MAPPING
index 3583a78..a159a5e 100644
--- a/services/companion/java/com/android/server/companion/virtual/TEST_MAPPING
+++ b/services/companion/java/com/android/server/companion/virtual/TEST_MAPPING
@@ -55,5 +55,15 @@
}
]
}
+ ],
+ "postsubmit": [
+ {
+ "name": "CtsVirtualDevicesCameraTestCases",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ }
]
}
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
index e6bfeb7..2c31a4c 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
@@ -960,7 +960,7 @@
if (mVirtualCameraController == null) {
throw new UnsupportedOperationException("Virtual camera controller is not available");
}
- mVirtualCameraController.registerCamera(Objects.requireNonNull(cameraConfig));
+ mVirtualCameraController.registerCamera(cameraConfig);
}
@Override // Binder call
@@ -972,7 +972,19 @@
if (mVirtualCameraController == null) {
throw new UnsupportedOperationException("Virtual camera controller is not available");
}
- mVirtualCameraController.unregisterCamera(Objects.requireNonNull(cameraConfig));
+ mVirtualCameraController.unregisterCamera(cameraConfig);
+ }
+
+ @Override // Binder call
+ @EnforcePermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
+ public int getVirtualCameraId(@NonNull VirtualCameraConfig cameraConfig)
+ throws RemoteException {
+ super.getVirtualCameraId_enforcePermission();
+ Objects.requireNonNull(cameraConfig);
+ if (mVirtualCameraController == null) {
+ throw new UnsupportedOperationException("Virtual camera controller is not available");
+ }
+ return mVirtualCameraController.getCameraId(cameraConfig);
}
@Override
diff --git a/services/companion/java/com/android/server/companion/virtual/camera/VirtualCameraController.java b/services/companion/java/com/android/server/companion/virtual/camera/VirtualCameraController.java
index 06be3f3..5665ad5 100644
--- a/services/companion/java/com/android/server/companion/virtual/camera/VirtualCameraController.java
+++ b/services/companion/java/com/android/server/companion/virtual/camera/VirtualCameraController.java
@@ -67,14 +67,7 @@
* @param cameraConfig The {@link VirtualCameraConfig} sent by the client.
*/
public void registerCamera(@NonNull VirtualCameraConfig cameraConfig) {
- // Try to connect to service if not connected already.
- if (mVirtualCameraService == null) {
- connectVirtualCameraService();
- }
- // Throw exception if we are unable to connect to service.
- if (mVirtualCameraService == null) {
- throw new IllegalStateException("Virtual camera service is not connected.");
- }
+ connectVirtualCameraServiceIfNeeded();
try {
if (registerCameraWithService(cameraConfig)) {
@@ -110,6 +103,17 @@
}
}
+ /** Return the id of the virtual camera with the given config. */
+ public int getCameraId(@NonNull VirtualCameraConfig cameraConfig) {
+ connectVirtualCameraServiceIfNeeded();
+
+ try {
+ return mVirtualCameraService.getCameraId(cameraConfig.getCallback().asBinder());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
@Override
public void binderDied() {
Slog.d(TAG, "Virtual camera service died.");
@@ -152,6 +156,17 @@
}
}
+ private void connectVirtualCameraServiceIfNeeded() {
+ // Try to connect to service if not connected already.
+ if (mVirtualCameraService == null) {
+ connectVirtualCameraService();
+ }
+ // Throw exception if we are unable to connect to service.
+ if (mVirtualCameraService == null) {
+ throw new IllegalStateException("Virtual camera service is not connected.");
+ }
+ }
+
private void connectVirtualCameraService() {
final long callingId = Binder.clearCallingIdentity();
try {