Merge "Implement device awareness in camera service" into main
diff --git a/camera/Camera.cpp b/camera/Camera.cpp
index 6b040ab..5d32871 100644
--- a/camera/Camera.cpp
+++ b/camera/Camera.cpp
@@ -71,10 +71,11 @@
sp<Camera> Camera::connect(int cameraId, const std::string& clientPackageName,
int clientUid, int clientPid, int targetSdkVersion, bool overrideToPortrait,
- bool forceSlowJpegMode)
+ bool forceSlowJpegMode, int32_t deviceId, int32_t devicePolicy)
{
return CameraBaseT::connect(cameraId, clientPackageName, clientUid,
- clientPid, targetSdkVersion, overrideToPortrait, forceSlowJpegMode);
+ clientPid, targetSdkVersion, overrideToPortrait, forceSlowJpegMode, deviceId,
+ devicePolicy);
}
status_t Camera::reconnect()
diff --git a/camera/CameraBase.cpp b/camera/CameraBase.cpp
index 6759f3b..b2f7cc7 100644
--- a/camera/CameraBase.cpp
+++ b/camera/CameraBase.cpp
@@ -73,6 +73,9 @@
if (res != OK) return res;
res = parcel->writeString16(toString16(clientPackage));
+ if (res != OK) return res;
+
+ res = parcel->writeInt32(deviceId);
return res;
}
@@ -97,6 +100,7 @@
if (res != OK) return res;
clientPackage = toStdString(tempClientPackage);
+ res = parcel->readInt32(&deviceId);
return res;
}
@@ -123,7 +127,7 @@
};
sp<DeathNotifier> gDeathNotifier;
-}; // namespace anonymous
+} // namespace anonymous
///////////////////////////////////////////////////////////
// CameraBase definition
@@ -159,7 +163,8 @@
sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId,
const std::string& clientPackageName,
int clientUid, int clientPid, int targetSdkVersion,
- bool overrideToPortrait, bool forceSlowJpegMode)
+ bool overrideToPortrait, bool forceSlowJpegMode,
+ int32_t deviceId, int32_t devicePolicy)
{
ALOGV("%s: connect", __FUNCTION__);
sp<TCam> c = new TCam(cameraId);
@@ -172,8 +177,8 @@
ALOGI("Connect camera (legacy API) - overrideToPortrait %d, forceSlowJpegMode %d",
overrideToPortrait, forceSlowJpegMode);
ret = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid,
- clientPid, targetSdkVersion, overrideToPortrait, forceSlowJpegMode,
- /*out*/ &c->mCamera);
+ clientPid, targetSdkVersion, overrideToPortrait, forceSlowJpegMode, deviceId,
+ devicePolicy, /*out*/ &c->mCamera);
}
if (ret.isOk() && c->mCamera != nullptr) {
IInterface::asBinder(c->mCamera)->linkToDeath(c);
@@ -252,7 +257,7 @@
}
template <typename TCam, typename TCamTraits>
-int CameraBase<TCam, TCamTraits>::getNumberOfCameras() {
+int CameraBase<TCam, TCamTraits>::getNumberOfCameras(int32_t deviceId, int32_t devicePolicy) {
const sp<::android::hardware::ICameraService> cs = getCameraService();
if (!cs.get()) {
@@ -261,8 +266,8 @@
}
int32_t count;
binder::Status res = cs->getNumberOfCameras(
- ::android::hardware::ICameraService::CAMERA_TYPE_BACKWARD_COMPATIBLE,
- &count);
+ ::android::hardware::ICameraService::CAMERA_TYPE_BACKWARD_COMPATIBLE, deviceId,
+ devicePolicy, &count);
if (!res.isOk()) {
ALOGE("Error reading number of cameras: %s",
res.toString8().c_str());
@@ -274,11 +279,12 @@
// this can be in BaseCamera but it should be an instance method
template <typename TCam, typename TCamTraits>
status_t CameraBase<TCam, TCamTraits>::getCameraInfo(int cameraId,
- bool overrideToPortrait,
+ bool overrideToPortrait, int32_t deviceId, int32_t devicePolicy,
struct hardware::CameraInfo* cameraInfo) {
const sp<::android::hardware::ICameraService> cs = getCameraService();
if (cs == 0) return UNKNOWN_ERROR;
- binder::Status res = cs->getCameraInfo(cameraId, overrideToPortrait, cameraInfo);
+ binder::Status res = cs->getCameraInfo(cameraId, overrideToPortrait, deviceId, devicePolicy,
+ cameraInfo);
return res.isOk() ? OK : res.serviceSpecificErrorCode();
}
diff --git a/camera/aidl/android/hardware/ICameraService.aidl b/camera/aidl/android/hardware/ICameraService.aidl
index 4bea896..81af7ee 100644
--- a/camera/aidl/android/hardware/ICameraService.aidl
+++ b/camera/aidl/android/hardware/ICameraService.aidl
@@ -63,14 +63,33 @@
const int CAMERA_TYPE_ALL = 1;
/**
- * Return the number of camera devices available in the system
+ * Return the number of camera devices available in the system.
+ *
+ * @param type The type of the camera, can be either CAMERA_TYPE_BACKWARD_COMPATIBLE
+ * or CAMERA_TYPE_ALL.
+ * @param deviceId The device id of the context associated with the caller.
+ * @param devicePolicy The camera policy of the device of the associated context (default
+ * policy for default device context). Only virtual cameras would be exposed
+ * only for custom policy and only real cameras would be exposed for default
+ * policy.
*/
- int getNumberOfCameras(int type);
+ int getNumberOfCameras(int type, int deviceId, int devicePolicy);
/**
- * Fetch basic camera information for a camera device
+ * Fetch basic camera information for a camera.
+ *
+ * @param cameraId The ID of the camera to fetch information for.
+ * @param overrideToPortrait Whether to override the sensor orientation information to
+ * correspond to portrait.
+ * @param deviceId The device id of the context associated with the caller.
+ * @param devicePolicy The camera policy of the device of the associated context (default
+ * policy for default device context). Only virtual cameras would be exposed
+ * only for custom policy and only real cameras would be exposed for default
+ * policy.
+ * @return CameraInfo for the camera.
*/
- CameraInfo getCameraInfo(int cameraId, boolean overrideToPortrait);
+ CameraInfo getCameraInfo(int cameraId, boolean overrideToPortrait, int deviceId,
+ int devicePolicy);
/**
* Default UID/PID values for non-privileged callers of
@@ -80,7 +99,20 @@
const int USE_CALLING_PID = -1;
/**
- * Open a camera device through the old camera API
+ * Open a camera device through the old camera API.
+ *
+ * @param cameraId The ID of the camera to open.
+ * @param opPackageName The package name to report for the app-ops.
+ * @param clientUid UID for the calling client.
+ * @param clientPid PID for the calling client.
+ * @param overrideToPortrait Whether to override the sensor orientation information to
+ * correspond to portrait.
+ * @param forceSlowJpegMode Whether to force slow jpeg mode.
+ * @param deviceId The device id of the context associated with the caller.
+ * @param devicePolicy The camera policy of the device of the associated context (default
+ * policy for default device context). Only virtual cameras would be exposed
+ * only for custom policy and only real cameras would be exposed for default
+ * policy.
*/
ICamera connect(ICameraClient client,
int cameraId,
@@ -88,11 +120,24 @@
int clientUid, int clientPid,
int targetSdkVersion,
boolean overrideToPortrait,
- boolean forceSlowJpegMode);
+ boolean forceSlowJpegMode,
+ int deviceId,
+ int devicePolicy);
/**
- * Open a camera device through the new camera API
- * Only supported for device HAL versions >= 3.2
+ * Open a camera device through the new camera API.
+ * Only supported for device HAL versions >= 3.2.
+ *
+ * @param cameraId The ID of the camera to open.
+ * @param opPackageName The package name to report for the app-ops.
+ * @param clientUid UID for the calling client.
+ * @param overrideToPortrait Whether to override the sensor orientation information to
+ * correspond to portrait.
+ * @param deviceId The device id of the context associated with the caller.
+ * @param devicePolicy The camera policy of the device of the associated context (default
+ * policy for default device context). Only virtual cameras would be exposed
+ * only for custom policy and only real cameras would be exposed for default
+ * policy.
*/
ICameraDeviceUser connectDevice(ICameraDeviceCallbacks callbacks,
@utf8InCpp String cameraId,
@@ -100,7 +145,9 @@
@nullable @utf8InCpp String featureId,
int clientUid, int oomScoreOffset,
int targetSdkVersion,
- boolean overrideToPortrait);
+ boolean overrideToPortrait,
+ int deviceId,
+ int devicePolicy);
/**
* Add listener for changes to camera device and flashlight state.
@@ -168,9 +215,19 @@
/**
* Read the static camera metadata for a camera device.
* Only supported for device HAL versions >= 3.2
+ *
+ * @param cameraId The ID of the camera to fetch metadata for.
+ * @param overrideToPortrait Whether to override the sensor orientation information to
+ * correspond to portrait.
+ * @param deviceId The device id of the context associated with the caller.
+ * @param devicePolicy The camera policy of the device of the associated context (default
+ * policy for default device context). Only virtual cameras would be exposed
+ * only for custom policy and only real cameras would be exposed for default
+ * policy.
+ * @return Characteristics for the given camera.
*/
CameraMetadataNative getCameraCharacteristics(@utf8InCpp String cameraId, int targetSdkVersion,
- boolean overrideToPortrait);
+ boolean overrideToPortrait, int deviceId, int devicePolicy);
/**
* Read in the vendor tag descriptors from the camera module HAL.
@@ -206,14 +263,46 @@
ICameraInjectionSession injectCamera(@utf8InCpp String packageName, @utf8InCpp String internalCamId,
@utf8InCpp String externalCamId, in ICameraInjectionCallback CameraInjectionCallback);
- void setTorchMode(@utf8InCpp String cameraId, boolean enabled, IBinder clientBinder);
+ /**
+ * Set the torch mode for a camera device.
+ *
+ * @param cameraId The ID of the camera to set torch mode for.
+ * @param deviceId The device id of the context associated with the caller.
+ * @param devicePolicy The camera policy of the device of the associated context (default
+ * policy for default device context). Only virtual cameras would be exposed
+ * only for custom policy and only real cameras would be exposed for default
+ * policy.
+ */
+ void setTorchMode(@utf8InCpp String cameraId, boolean enabled, IBinder clientBinder,
+ int deviceId, int devicePolicy);
- // Change the brightness level of the flash unit associated with cameraId to strengthLevel.
- // If the torch is in OFF state and strengthLevel > 0 then the torch will also be turned ON.
- void turnOnTorchWithStrengthLevel(@utf8InCpp String cameraId, int strengthLevel, IBinder clientBinder);
+ /**
+ * Change the brightness level of the flash unit associated with cameraId to strengthLevel.
+ * If the torch is in OFF state and strengthLevel > 0 then the torch will also be turned ON.
+ *
+ * @param cameraId The ID of the camera.
+ * @param strengthLevel The torch strength level to set for the camera.
+ * @param deviceId The device id of the context associated with the caller.
+ * @param devicePolicy The camera policy of the device of the associated context (default
+ * policy for default device context). Only virtual cameras would be exposed
+ * only for custom policy and only real cameras would be exposed for default
+ * policy.
+ */
+ void turnOnTorchWithStrengthLevel(@utf8InCpp String cameraId, int strengthLevel,
+ IBinder clientBinder, int deviceId, int devicePolicy);
- // Get the brightness level of the flash unit associated with cameraId.
- int getTorchStrengthLevel(@utf8InCpp String cameraId);
+ /**
+ * Get the brightness level of the flash unit associated with cameraId.
+ *
+ * @param cameraId The ID of the camera.
+ * @param deviceId The device id of the context associated with the caller.
+ * @param devicePolicy The camera policy of the device of the associated context (default
+ * policy for default device context). Only virtual cameras would be exposed
+ * only for custom policy and only real cameras would be exposed for default
+ * policy.
+ * @return Torch strength level for the camera.
+ */
+ int getTorchStrengthLevel(@utf8InCpp String cameraId, int deviceId, int devicePolicy);
/**
* Notify the camera service of a system event. Should only be called from system_server.
@@ -274,8 +363,20 @@
const int DEVICE_STATE_FOLDED = 4;
const int DEVICE_STATE_LAST_FRAMEWORK_BIT = 0x80000000; // 1 << 31;
- // Create a CaptureRequest metadata based on template id
- CameraMetadataNative createDefaultRequest(@utf8InCpp String cameraId, int templateId);
+ /**
+ * Create a CaptureRequest metadata based on template id
+ *
+ * @param cameraId The camera id to create the CaptureRequest for.
+ * @param templateId The template id create the CaptureRequest for.
+ * @param deviceId the device id of the context associated with the caller.
+ * @param devicePolicy The camera policy of the device of the associated context (default
+ * policy for default device context). Only virtual cameras would be exposed
+ * only for custom policy and only real cameras would be exposed for default
+ * policy.
+ * @return Metadata representing the CaptureRequest.
+ */
+ CameraMetadataNative createDefaultRequest(@utf8InCpp String cameraId, int templateId,
+ int deviceId, int devicePolicy);
/**
* Check whether a particular session configuration with optional session parameters
@@ -283,23 +384,35 @@
*
* @param cameraId The camera id to query session configuration for
* @param sessionConfiguration Specific session configuration to be verified.
+ * @param deviceId The device id of the context associated with the caller.
+ * @param devicePolicy The camera policy of the device of the associated context (default
+ * policy for default device context). Only virtual cameras would be exposed
+ * only for custom policy and only real cameras would be exposed for default
+ * policy.
* @return true - in case the stream combination is supported.
* false - in case there is no device support.
*/
boolean isSessionConfigurationWithParametersSupported(@utf8InCpp String cameraId,
- in SessionConfiguration sessionConfiguration);
+ in SessionConfiguration sessionConfiguration, int deviceId, int devicePolicy);
/**
* Get the camera characteristics for a particular session configuration for
* the given camera device.
*
* @param cameraId ID of the device for which the session characteristics must be fetched.
- * @param sessionConfiguration session configuration for which the characteristics
+ * @param sessionConfiguration Session configuration for which the characteristics
* must be fetched.
- * @return - characteristics associated with the given session.
+ * @param deviceId The device id of the context associated with the caller.
+ * @param devicePolicy The camera policy of the device of the associated context (default
+ * policy for default device context). Only virtual cameras would be exposed
+ * only for custom policy and only real cameras would be exposed for default
+ * policy.
+ * @return Characteristics associated with the given session.
*/
CameraMetadataNative getSessionCharacteristics(@utf8InCpp String cameraId,
- int targetSdkVersion,
- boolean overrideToPortrait,
- in SessionConfiguration sessionConfiguration);
+ int targetSdkVersion,
+ boolean overrideToPortrait,
+ in SessionConfiguration sessionConfiguration,
+ int deviceId,
+ int devicePolicy);
}
diff --git a/camera/aidl/android/hardware/ICameraServiceListener.aidl b/camera/aidl/android/hardware/ICameraServiceListener.aidl
index 23a87d3..9c8c88a 100644
--- a/camera/aidl/android/hardware/ICameraServiceListener.aidl
+++ b/camera/aidl/android/hardware/ICameraServiceListener.aidl
@@ -51,14 +51,20 @@
// Use to initialize variables only
const int STATUS_UNKNOWN = -1;
- oneway void onStatusChanged(int status, @utf8InCpp String cameraId);
+ // We pass deviceId associated with a camera in the callbacks, which is the id of the virtual
+ // device owning the camera (for virtual cameras), or kDefaultDeviceId (for real
+ // cameras). The deviceId is being passed so that the API layer (CameraManagerGlobal) can filter
+ // out the cameras that don't correspond to the context associated with the caller who
+ // registers a callback.
+
+ oneway void onStatusChanged(int status, @utf8InCpp String cameraId, int deviceId);
/**
* Notify registered client about status changes for a physical camera backing
* a logical camera.
*/
oneway void onPhysicalCameraStatusChanged(int status, @utf8InCpp String cameraId,
- @utf8InCpp String physicalCameraId);
+ @utf8InCpp String physicalCameraId, int deviceId);
/**
* The torch mode status of a camera.
@@ -82,9 +88,9 @@
// Use to initialize variables only
const int TORCH_STATUS_UNKNOWN = -1;
- oneway void onTorchStatusChanged(int status, @utf8InCpp String cameraId);
+ oneway void onTorchStatusChanged(int status, @utf8InCpp String cameraId, int deviceId);
- oneway void onTorchStrengthLevelChanged(@utf8InCpp String cameraId, int newTorchStrength);
+ oneway void onTorchStrengthLevelChanged(@utf8InCpp String cameraId, int newTorchStrength, int deviceId);
/**
* Notify registered clients about camera access priority changes.
@@ -98,6 +104,6 @@
* Only clients with android.permission.CAMERA_OPEN_CLOSE_LISTENER permission
* will receive such callbacks.
*/
- oneway void onCameraOpened(@utf8InCpp String cameraId, @utf8InCpp String clientPackageId);
- oneway void onCameraClosed(@utf8InCpp String cameraId);
+ oneway void onCameraOpened(@utf8InCpp String cameraId, @utf8InCpp String clientPackageId, int deviceId);
+ oneway void onCameraClosed(@utf8InCpp String cameraId, int deviceId);
}
diff --git a/camera/include/camera/Camera.h b/camera/include/camera/Camera.h
index 6655f82..dfa53d2 100644
--- a/camera/include/camera/Camera.h
+++ b/camera/include/camera/Camera.h
@@ -27,6 +27,7 @@
#include <camera/android/hardware/ICamera.h>
#include <camera/android/hardware/ICameraClient.h>
#include <camera/CameraBase.h>
+#include <camera/CameraUtils.h>
namespace android {
@@ -58,7 +59,7 @@
typedef ::android::hardware::ICameraClient TCamCallbacks;
typedef ::android::binder::Status (::android::hardware::ICameraService::*TCamConnectService)
(const sp<::android::hardware::ICameraClient>&,
- int, const std::string&, int, int, int, bool, bool,
+ int, const std::string&, int, int, int, bool, bool, int32_t, int32_t,
/*out*/
sp<::android::hardware::ICamera>*);
static TCamConnectService fnConnectService;
@@ -82,7 +83,8 @@
static sp<Camera> connect(int cameraId,
const std::string& clientPackageName,
int clientUid, int clientPid, int targetSdkVersion,
- bool overrideToPortrait, bool forceSlowJpegMode);
+ bool overrideToPortrait, bool forceSlowJpegMode,
+ int32_t deviceId = kDefaultDeviceId, int32_t devicePolicy = 0);
virtual ~Camera();
@@ -197,6 +199,6 @@
friend class CameraBase;
};
-}; // namespace android
+} // namespace android
#endif
diff --git a/camera/include/camera/CameraBase.h b/camera/include/camera/CameraBase.h
index 6af7f2a..85ddbd6 100644
--- a/camera/include/camera/CameraBase.h
+++ b/camera/include/camera/CameraBase.h
@@ -62,16 +62,15 @@
virtual status_t writeToParcel(android::Parcel* parcel) const;
virtual status_t readFromParcel(const android::Parcel* parcel);
-
};
/**
- * Basic status information about a camera device - its name and its current
+ * Basic status information about a camera device - its id and its current
* state.
*/
struct CameraStatus : public android::Parcelable {
/**
- * The name of the camera device
+ * The app-visible id of the camera device
*/
std::string cameraId;
@@ -90,12 +89,19 @@
*/
std::string clientPackage;
+ /**
+ * The id of the device owning the camera. For virtual cameras, this is the id of the virtual
+ * device owning the camera. For real cameras, this is the default device id, i.e.,
+ * kDefaultDeviceId.
+ */
+ int32_t deviceId;
+
virtual status_t writeToParcel(android::Parcel* parcel) const;
virtual status_t readFromParcel(const android::Parcel* parcel);
CameraStatus(std::string id, int32_t s, const std::vector<std::string>& unavailSubIds,
- const std::string& clientPkg) : cameraId(id), status(s),
- unavailablePhysicalIds(unavailSubIds), clientPackage(clientPkg) {}
+ const std::string& clientPkg, int32_t devId) : cameraId(id), status(s),
+ unavailablePhysicalIds(unavailSubIds), clientPackage(clientPkg), deviceId(devId) {}
CameraStatus() : status(ICameraServiceListener::STATUS_PRESENT) {}
};
@@ -103,7 +109,6 @@
using hardware::CameraInfo;
-
template <typename TCam>
struct CameraTraits {
};
@@ -120,15 +125,18 @@
static sp<TCam> connect(int cameraId,
const std::string& clientPackageName,
int clientUid, int clientPid, int targetSdkVersion,
- bool overrideToPortrait, bool forceSlowJpegMode);
+ bool overrideToPortrait, bool forceSlowJpegMode,
+ int32_t deviceId, int32_t devicePolicy);
virtual void disconnect();
void setListener(const sp<TCamListener>& listener);
- static int getNumberOfCameras();
+ static int getNumberOfCameras(int32_t deviceId, int32_t devicePolicy);
static status_t getCameraInfo(int cameraId,
bool overrideToPortrait,
+ int32_t deviceId,
+ int32_t devicePolicy,
/*out*/
struct hardware::CameraInfo* cameraInfo);
@@ -167,6 +175,6 @@
typedef CameraBase<TCam> CameraBaseT;
};
-}; // namespace android
+} // namespace android
#endif
diff --git a/camera/include/camera/CameraUtils.h b/camera/include/camera/CameraUtils.h
index 31d25e7..d358407 100644
--- a/camera/include/camera/CameraUtils.h
+++ b/camera/include/camera/CameraUtils.h
@@ -26,6 +26,9 @@
namespace android {
+// Device id of a context associated with the default device.
+constexpr int32_t kDefaultDeviceId = 0;
+
/**
* CameraUtils contains utility methods that are shared between the native
* camera client, and the camera service.
diff --git a/camera/ndk/impl/ACameraManager.cpp b/camera/ndk/impl/ACameraManager.cpp
index 8c3424f..0744992 100644
--- a/camera/ndk/impl/ACameraManager.cpp
+++ b/camera/ndk/impl/ACameraManager.cpp
@@ -32,6 +32,9 @@
namespace android {
namespace acam {
+
+// TODO(b/291736219): Add device-awareness to ACameraManager.
+
// Static member definitions
const char* CameraManagerGlobal::kCameraIdKey = "CameraId";
const char* CameraManagerGlobal::kPhysicalCameraIdKey = "PhysicalCameraId";
@@ -125,6 +128,12 @@
std::vector<hardware::CameraStatus> cameraStatuses{};
mCameraService->addListener(mCameraServiceListener, &cameraStatuses);
for (auto& c : cameraStatuses) {
+ // Skip callback for cameras not belonging to the default device, as NDK doesn't support
+ // device awareness yet.
+ if (c.deviceId != kDefaultDeviceId) {
+ continue;
+ }
+
onStatusChangedLocked(c.status, c.cameraId);
for (auto& unavailablePhysicalId : c.unavailablePhysicalIds) {
@@ -461,7 +470,13 @@
}
binder::Status CameraManagerGlobal::CameraServiceListener::onStatusChanged(
- int32_t status, const std::string& cameraId) {
+ int32_t status, const std::string& cameraId, int deviceId) {
+ // Skip callback for cameras not belonging to the default device, as NDK doesn't support
+ // device awareness yet.
+ if (deviceId != kDefaultDeviceId) {
+ return binder::Status::ok();
+ }
+
sp<CameraManagerGlobal> cm = mCameraManager.promote();
if (cm != nullptr) {
cm->onStatusChanged(status, cameraId);
@@ -472,7 +487,14 @@
}
binder::Status CameraManagerGlobal::CameraServiceListener::onPhysicalCameraStatusChanged(
- int32_t status, const std::string& cameraId, const std::string& physicalCameraId) {
+ int32_t status, const std::string& cameraId, const std::string& physicalCameraId,
+ int deviceId) {
+ // Skip callback for cameras not belonging to the default device, as NDK doesn't support
+ // device awareness yet.
+ if (deviceId != kDefaultDeviceId) {
+ return binder::Status::ok();
+ }
+
sp<CameraManagerGlobal> cm = mCameraManager.promote();
if (cm != nullptr) {
cm->onStatusChanged(status, cameraId, physicalCameraId);
@@ -697,7 +719,8 @@
CameraMetadata rawMetadata;
int targetSdkVersion = android_get_application_target_sdk_version();
binder::Status serviceRet = cs->getCameraCharacteristics(cameraIdStr,
- targetSdkVersion, /*overrideToPortrait*/false, &rawMetadata);
+ targetSdkVersion, /*overrideToPortrait*/false, kDefaultDeviceId, /*devicePolicy*/0,
+ &rawMetadata);
if (!serviceRet.isOk()) {
switch(serviceRet.serviceSpecificErrorCode()) {
case hardware::ICameraService::ERROR_DISCONNECTED:
@@ -749,7 +772,8 @@
binder::Status serviceRet = cs->connectDevice(
callbacks, cameraId, "", {},
hardware::ICameraService::USE_CALLING_UID, /*oomScoreOffset*/0,
- targetSdkVersion, /*overrideToPortrait*/false, /*out*/&deviceRemote);
+ targetSdkVersion, /*overrideToPortrait*/false, kDefaultDeviceId, /*devicePolicy*/0,
+ /*out*/&deviceRemote);
if (!serviceRet.isOk()) {
ALOGE("%s: connect camera device failed: %s", __FUNCTION__, serviceRet.toString8().c_str());
diff --git a/camera/ndk/impl/ACameraManager.h b/camera/ndk/impl/ACameraManager.h
index c135d0f..c6e2bf9 100644
--- a/camera/ndk/impl/ACameraManager.h
+++ b/camera/ndk/impl/ACameraManager.h
@@ -87,23 +87,24 @@
class CameraServiceListener final : public hardware::BnCameraServiceListener {
public:
explicit CameraServiceListener(CameraManagerGlobal* cm) : mCameraManager(cm) {}
- virtual binder::Status onStatusChanged(int32_t status, const std::string& cameraId);
+ virtual binder::Status onStatusChanged(int32_t status, const std::string& cameraId,
+ int32_t deviceId);
virtual binder::Status onPhysicalCameraStatusChanged(int32_t status,
- const std::string& cameraId, const std::string& physicalCameraId);
+ const std::string& cameraId, const std::string& physicalCameraId, int32_t deviceId);
// Torch API not implemented yet
- virtual binder::Status onTorchStatusChanged(int32_t, const std::string&) {
+ virtual binder::Status onTorchStatusChanged(int32_t, const std::string&, int32_t) {
return binder::Status::ok();
}
- virtual binder::Status onTorchStrengthLevelChanged(const std::string&, int32_t) {
+ virtual binder::Status onTorchStrengthLevelChanged(const std::string&, int32_t, int32_t) {
return binder::Status::ok();
}
virtual binder::Status onCameraAccessPrioritiesChanged();
- virtual binder::Status onCameraOpened(const std::string&, const std::string&) {
+ virtual binder::Status onCameraOpened(const std::string&, const std::string&, int32_t) {
return binder::Status::ok();
}
- virtual binder::Status onCameraClosed(const std::string&) {
+ virtual binder::Status onCameraClosed(const std::string&, int32_t) {
return binder::Status::ok();
}
diff --git a/camera/tests/CameraBinderTests.cpp b/camera/tests/CameraBinderTests.cpp
index bb963ab..e5f99be 100644
--- a/camera/tests/CameraBinderTests.cpp
+++ b/camera/tests/CameraBinderTests.cpp
@@ -43,6 +43,7 @@
#include <camera/camera2/OutputConfiguration.h>
#include <camera/camera2/SessionConfiguration.h>
#include <camera/camera2/SubmitInfo.h>
+#include <camera/CameraUtils.h>
#include <camera/StringUtils.h>
#include <gui/BufferItemConsumer.h>
@@ -77,29 +78,34 @@
public:
virtual ~TestCameraServiceListener() {};
- virtual binder::Status onStatusChanged(int32_t status, const std::string& cameraId) override {
+ virtual binder::Status onStatusChanged(int32_t status, const std::string& cameraId,
+ [[maybe_unused]] int32_t /*deviceId*/) override {
Mutex::Autolock l(mLock);
mCameraStatuses[cameraId] = status;
mCondition.broadcast();
return binder::Status::ok();
- };
+ }
- virtual binder::Status onPhysicalCameraStatusChanged(int32_t /*status*/,
- const std::string& /*cameraId*/, const std::string& /*physicalCameraId*/) override {
+ virtual binder::Status onPhysicalCameraStatusChanged([[maybe_unused]] int32_t /*status*/,
+ [[maybe_unused]] const std::string& /*cameraId*/,
+ [[maybe_unused]] const std::string& /*physicalCameraId*/,
+ [[maybe_unused]] int32_t /*deviceId*/) override {
// No op
return binder::Status::ok();
- };
+ }
virtual binder::Status onTorchStatusChanged(int32_t status,
- const std::string& cameraId) override {
+ const std::string& cameraId, [[maybe_unused]] int32_t /*deviceId*/) override {
Mutex::Autolock l(mLock);
mCameraTorchStatuses[cameraId] = status;
mTorchCondition.broadcast();
return binder::Status::ok();
- };
+ }
- virtual binder::Status onTorchStrengthLevelChanged(const std::string& /*cameraId*/,
- int32_t /*torchStrength*/) override {
+ virtual binder::Status onTorchStrengthLevelChanged(
+ [[maybe_unused]] const std::string& /*cameraId*/,
+ [[maybe_unused]] int32_t /*torchStrength*/,
+ [[maybe_unused]] int32_t /*deviceId*/) override {
// No op
return binder::Status::ok();
}
@@ -109,13 +115,15 @@
return binder::Status::ok();
}
- virtual binder::Status onCameraOpened(const std::string& /*cameraId*/,
- const std::string& /*clientPackageName*/) {
+ virtual binder::Status onCameraOpened([[maybe_unused]] const std::string& /*cameraId*/,
+ [[maybe_unused]] const std::string& /*clientPackageName*/,
+ [[maybe_unused]] int32_t /*deviceId*/) {
// No op
return binder::Status::ok();
}
- virtual binder::Status onCameraClosed(const std::string& /*cameraId*/) override {
+ virtual binder::Status onCameraClosed([[maybe_unused]] const std::string& /*cameraId*/,
+ [[maybe_unused]] int32_t /*deviceId*/) override {
// No op
return binder::Status::ok();
}
@@ -133,7 +141,7 @@
}
}
return true;
- };
+ }
bool waitForTorchState(int32_t status, int32_t cameraId) const {
Mutex::Autolock l(mLock);
@@ -153,7 +161,7 @@
foundStatus = (iter != mCameraTorchStatuses.end() && iter->second == status);
}
return true;
- };
+ }
int32_t getTorchStatus(int32_t cameraId) const {
Mutex::Autolock l(mLock);
@@ -162,7 +170,7 @@
return hardware::ICameraServiceListener::TORCH_STATUS_UNKNOWN;
}
return iter->second;
- };
+ }
int32_t getStatus(const std::string& cameraId) const {
Mutex::Autolock l(mLock);
@@ -171,7 +179,7 @@
return hardware::ICameraServiceListener::STATUS_UNKNOWN;
}
return iter->second;
- };
+ }
};
// Callback implementation
@@ -230,7 +238,6 @@
return binder::Status::ok();
}
-
virtual binder::Status onResultReceived(const CameraMetadata& metadata,
const CaptureResultExtras& resultExtras,
const std::vector<PhysicalCaptureResultInfo>& physicalResultInfos) {
@@ -296,7 +303,6 @@
mStatusesHit.clear();
return true;
-
}
void clearStatus() const {
@@ -307,7 +313,6 @@
bool waitForIdle() const {
return waitForStatus(IDLE);
}
-
};
namespace {
@@ -324,7 +329,7 @@
}
};
sp<DeathNotifier> gDeathNotifier;
-}; // anonymous namespace
+} // anonymous namespace
// Exercise basic binder calls for the camera service
TEST(CameraServiceBinderTest, CheckBinderCameraService) {
@@ -342,7 +347,8 @@
binder::Status res;
int32_t numCameras = 0;
- res = service->getNumberOfCameras(hardware::ICameraService::CAMERA_TYPE_ALL, &numCameras);
+ res = service->getNumberOfCameras(hardware::ICameraService::CAMERA_TYPE_ALL, kDefaultDeviceId,
+ /*devicePolicy*/0, &numCameras);
EXPECT_TRUE(res.isOk()) << res;
EXPECT_LE(0, numCameras);
@@ -354,7 +360,7 @@
EXPECT_EQ(numCameras, static_cast<const int>(statuses.size()));
for (const auto &it : statuses) {
- listener->onStatusChanged(it.status, it.cameraId);
+ listener->onStatusChanged(it.status, it.cameraId, kDefaultDeviceId);
}
for (int32_t i = 0; i < numCameras; i++) {
@@ -372,7 +378,8 @@
// Check metadata binder call
CameraMetadata metadata;
res = service->getCameraCharacteristics(cameraId,
- /*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/false, &metadata);
+ /*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/false,
+ kDefaultDeviceId, /*devicePolicy*/0, &metadata);
EXPECT_TRUE(res.isOk()) << res;
EXPECT_FALSE(metadata.isEmpty());
@@ -389,7 +396,7 @@
res = service->connectDevice(callbacks, cameraId, "meeeeeeeee!",
{}, hardware::ICameraService::USE_CALLING_UID, /*oomScoreOffset*/ 0,
/*targetSdkVersion*/__ANDROID_API_FUTURE__,
- /*overrideToPortrait*/false, /*out*/&device);
+ /*overrideToPortrait*/false, kDefaultDeviceId, /*devicePolicy*/0, /*out*/&device);
EXPECT_TRUE(res.isOk()) << res;
ASSERT_NE(nullptr, device.get());
device->disconnect();
@@ -399,12 +406,12 @@
if (torchStatus == hardware::ICameraServiceListener::TORCH_STATUS_AVAILABLE_OFF) {
// Check torch calls
res = service->setTorchMode(cameraId,
- /*enabled*/true, callbacks);
+ /*enabled*/true, callbacks, kDefaultDeviceId, /*devicePolicy*/0);
EXPECT_TRUE(res.isOk()) << res;
EXPECT_TRUE(listener->waitForTorchState(
hardware::ICameraServiceListener::TORCH_STATUS_AVAILABLE_ON, i));
res = service->setTorchMode(cameraId,
- /*enabled*/false, callbacks);
+ /*enabled*/false, callbacks, kDefaultDeviceId, /*devicePolicy*/0);
EXPECT_TRUE(res.isOk()) << res;
EXPECT_TRUE(listener->waitForTorchState(
hardware::ICameraServiceListener::TORCH_STATUS_AVAILABLE_OFF, i));
@@ -433,7 +440,8 @@
binder::Status res = service->connectDevice(callbacks, deviceId, "meeeeeeeee!",
{}, hardware::ICameraService::USE_CALLING_UID, /*oomScoreOffset*/ 0,
/*targetSdkVersion*/__ANDROID_API_FUTURE__,
- /*overrideToPortrait*/false, /*out*/&device);
+ /*overrideToPortrait*/false, kDefaultDeviceId, /*devicePolicy*/0,
+ /*out*/&device);
EXPECT_TRUE(res.isOk()) << res;
}
auto p = std::make_pair(callbacks, device);
@@ -466,10 +474,10 @@
std::vector<hardware::CameraStatus> statuses;
service->addListener(serviceListener, &statuses);
for (const auto &it : statuses) {
- serviceListener->onStatusChanged(it.status, it.cameraId);
+ serviceListener->onStatusChanged(it.status, it.cameraId, kDefaultDeviceId);
}
service->getNumberOfCameras(hardware::ICameraService::CAMERA_TYPE_BACKWARD_COMPATIBLE,
- &numCameras);
+ kDefaultDeviceId, /*devicePolicy*/0, &numCameras);
}
virtual void TearDown() {
@@ -479,7 +487,6 @@
closeDevice(p);
}
}
-
};
TEST_F(CameraClientBinderTest, CheckBinderCameraDeviceUser) {
@@ -647,8 +654,7 @@
closeDevice(p);
}
-
-};
+}
TEST_F(CameraClientBinderTest, CheckBinderCaptureRequest) {
sp<CaptureRequest> requestOriginal, requestParceled;
@@ -707,4 +713,4 @@
EXPECT_TRUE(it->settings.exists(ANDROID_CONTROL_CAPTURE_INTENT));
entry = it->settings.find(ANDROID_CONTROL_CAPTURE_INTENT);
EXPECT_EQ(entry.data.u8[0], intent2);
-};
+}
diff --git a/camera/tests/CameraCharacteristicsPermission.cpp b/camera/tests/CameraCharacteristicsPermission.cpp
index 1de7cb4..10f7f22 100644
--- a/camera/tests/CameraCharacteristicsPermission.cpp
+++ b/camera/tests/CameraCharacteristicsPermission.cpp
@@ -24,6 +24,7 @@
#include <utils/Log.h>
#include <camera/CameraMetadata.h>
#include <camera/Camera.h>
+#include <camera/CameraUtils.h>
#include <android/hardware/ICameraService.h>
using namespace android;
@@ -31,7 +32,6 @@
class CameraCharacteristicsPermission : public ::testing::Test {
protected:
-
CameraCharacteristicsPermission() : numCameras(0){}
//Gtest interface
void SetUp() override;
@@ -48,7 +48,8 @@
sp<IBinder> binder = sm->getService(String16("media.camera"));
mCameraService = interface_cast<ICameraService>(binder);
rc = mCameraService->getNumberOfCameras(
- hardware::ICameraService::CAMERA_TYPE_ALL, &numCameras);
+ hardware::ICameraService::CAMERA_TYPE_ALL, kDefaultDeviceId, /*devicePolicy*/0,
+ &numCameras);
EXPECT_TRUE(rc.isOk());
}
@@ -61,7 +62,6 @@
// a camera permission.
TEST_F(CameraCharacteristicsPermission, TestCameraPermission) {
for (int32_t cameraId = 0; cameraId < numCameras; cameraId++) {
-
std::string cameraIdStr = std::to_string(cameraId);
bool isSupported = false;
auto rc = mCameraService->supportsCameraApi(cameraIdStr,
@@ -75,7 +75,7 @@
std::vector<int32_t> tagsNeedingPermission;
rc = mCameraService->getCameraCharacteristics(cameraIdStr,
/*targetSdkVersion*/__ANDROID_API_FUTURE__,
- /*overrideToPortrait*/false, &metadata);
+ /*overrideToPortrait*/false, kDefaultDeviceId, /*devicePolicy*/0, &metadata);
ASSERT_TRUE(rc.isOk());
EXPECT_FALSE(metadata.isEmpty());
EXPECT_EQ(metadata.removePermissionEntries(CAMERA_METADATA_INVALID_VENDOR_ID,
diff --git a/camera/tests/CameraZSLTests.cpp b/camera/tests/CameraZSLTests.cpp
index 3ae7659..56fcfa4 100644
--- a/camera/tests/CameraZSLTests.cpp
+++ b/camera/tests/CameraZSLTests.cpp
@@ -27,6 +27,7 @@
#include <camera/CameraParameters.h>
#include <camera/CameraMetadata.h>
#include <camera/Camera.h>
+#include <camera/CameraUtils.h>
#include <camera/StringUtils.h>
#include <android/hardware/ICameraService.h>
@@ -84,7 +85,8 @@
sp<IBinder> binder = sm->getService(String16("media.camera"));
mCameraService = interface_cast<ICameraService>(binder);
rc = mCameraService->getNumberOfCameras(
- hardware::ICameraService::CAMERA_TYPE_ALL, &numCameras);
+ hardware::ICameraService::CAMERA_TYPE_ALL, kDefaultDeviceId, /*devicePolicy*/0,
+ &numCameras);
EXPECT_TRUE(rc.isOk());
mComposerClient = new SurfaceComposerClient;
@@ -109,7 +111,6 @@
void CameraZSLTests::dataCallback(int32_t msgType, const sp<IMemory>& /*data*/,
camera_frame_metadata_t *) {
-
switch (msgType) {
case CAMERA_MSG_PREVIEW_FRAME: {
Mutex::Autolock l(mPreviewLock);
@@ -127,7 +128,7 @@
default:
ALOGV("%s: msgType: %d", __FUNCTION__, msgType);
}
-};
+}
status_t CameraZSLTests::waitForPreviewStart() {
status_t rc = NO_ERROR;
@@ -184,7 +185,7 @@
CameraMetadata metadata;
rc = mCameraService->getCameraCharacteristics(cameraIdStr,
/*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/false,
- &metadata);
+ kDefaultDeviceId, /*devicePolicy*/0, &metadata);
if (!rc.isOk()) {
// The test is relevant only for cameras with Hal 3.x
// support.
@@ -212,7 +213,8 @@
"ZSLTest", hardware::ICameraService::USE_CALLING_UID,
hardware::ICameraService::USE_CALLING_PID,
/*targetSdkVersion*/__ANDROID_API_FUTURE__,
- /*overrideToPortrait*/false, /*forceSlowJpegMode*/false, &cameraDevice);
+ /*overrideToPortrait*/false, /*forceSlowJpegMode*/false, kDefaultDeviceId,
+ /*devicePolicy*/0, &cameraDevice);
EXPECT_TRUE(rc.isOk());
CameraParameters params(cameraDevice->getParameters());
diff --git a/camera/tests/fuzzer/camera_fuzzer.cpp b/camera/tests/fuzzer/camera_fuzzer.cpp
index c2a7549..0812096 100644
--- a/camera/tests/fuzzer/camera_fuzzer.cpp
+++ b/camera/tests/fuzzer/camera_fuzzer.cpp
@@ -16,6 +16,7 @@
#include <Camera.h>
#include <CameraParameters.h>
+#include <CameraUtils.h>
#include <binder/MemoryDealer.h>
#include <fuzzer/FuzzedDataProvider.h>
#include <gui/Surface.h>
@@ -115,7 +116,7 @@
hardware::ICameraService::USE_CALLING_PID,
/*targetSdkVersion*/ __ANDROID_API_FUTURE__,
/*overrideToPortrait*/ false, /*forceSlowJpegMode*/ false,
- &cameraDevice);
+ kDefaultDeviceId, /*devicePolicy*/0, &cameraDevice);
} else {
cameraService->connect(this, mFDP->ConsumeIntegral<int32_t>() /* cameraId */,
mFDP->ConsumeRandomLengthString(kMaxBytes).c_str(),
@@ -123,7 +124,8 @@
mFDP->ConsumeIntegral<int8_t>() /* clientPid */,
/*targetSdkVersion*/ mFDP->ConsumeIntegral<int32_t>(),
/*overrideToPortrait*/ mFDP->ConsumeBool(),
- /*forceSlowJpegMode*/ mFDP->ConsumeBool(), &cameraDevice);
+ /*forceSlowJpegMode*/ mFDP->ConsumeBool(), kDefaultDeviceId,
+ /*devicePolicy*/0, &cameraDevice);
}
mCamera = Camera::create(cameraDevice);
@@ -150,13 +152,14 @@
}
int32_t cameraId = mFDP->ConsumeIntegral<int32_t>();
- Camera::getNumberOfCameras();
+ Camera::getNumberOfCameras(kDefaultDeviceId, /*devicePolicy*/0);
CameraInfo cameraInfo;
cameraInfo.facing = mFDP->ConsumeBool() ? mFDP->PickValueInArray(kValidFacing)
: mFDP->ConsumeIntegral<int32_t>();
cameraInfo.orientation = mFDP->ConsumeBool() ? mFDP->PickValueInArray(kValidOrientation)
: mFDP->ConsumeIntegral<int32_t>();
- Camera::getCameraInfo(cameraId, /*overrideToPortrait*/false, &cameraInfo);
+ Camera::getCameraInfo(cameraId, /*overrideToPortrait*/false, kDefaultDeviceId,
+ /*devicePolicy*/0, &cameraInfo);
mCamera->reconnect();
sp<SurfaceComposerClient> composerClient = new SurfaceComposerClient;
diff --git a/camera/tests/fuzzer/camera_utils_fuzzer.cpp b/camera/tests/fuzzer/camera_utils_fuzzer.cpp
index 365305e..c816f82 100644
--- a/camera/tests/fuzzer/camera_utils_fuzzer.cpp
+++ b/camera/tests/fuzzer/camera_utils_fuzzer.cpp
@@ -112,7 +112,8 @@
}
string clientPackage = mFDP->ConsumeRandomLengthString(kMaxBytes);
- cameraStatus = new CameraStatus(id, status, unavailSubIds, clientPackage);
+ cameraStatus = new CameraStatus(id, status, unavailSubIds, clientPackage,
+ kDefaultDeviceId);
}
if (mFDP->ConsumeBool()) {
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index b9b30f6..ee30e46 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -74,6 +74,7 @@
"libstagefright_foundation",
"libxml2",
"libyuv",
+ "android.companion.virtual.virtualdevice_aidl-cpp",
"android.companion.virtualdevice.flags-aconfig-cc",
"android.hardware.camera.common@1.0",
"android.hardware.camera.device@1.0",
@@ -197,6 +198,7 @@
"utils/TagMonitor.cpp",
"utils/LatencyHistogram.cpp",
"utils/Utils.cpp",
+ "utils/VirtualDeviceCameraIdMapper.cpp",
],
header_libs: [
@@ -228,7 +230,6 @@
"-Werror",
"-Wno-ignored-qualifiers",
],
-
}
cc_library_static {
@@ -278,5 +279,4 @@
"-Werror",
"-Wno-ignored-qualifiers",
],
-
}
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index e30775d..20ea5bb 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -38,6 +38,8 @@
#include <aidl/AidlCameraService.h>
#include <android-base/macros.h>
#include <android-base/parseint.h>
+#include <android_companion_virtualdevice_flags.h>
+#include <android/companion/virtualnative/IVirtualDeviceManagerNative.h>
#include <binder/ActivityManager.h>
#include <binder/AppOpsManager.h>
#include <binder/IPCThreadState.h>
@@ -72,6 +74,7 @@
#include <system/camera_metadata.h>
#include <binder/IServiceManager.h>
#include <binder/IActivityManager.h>
+#include <camera/CameraUtils.h>
#include <camera/StringUtils.h>
#include <system/camera.h>
@@ -90,7 +93,18 @@
const char* kSensorPrivacyServiceName = "sensor_privacy";
const char* kAppopsServiceName = "appops";
const char* kProcessInfoServiceName = "processinfo";
-}; // namespace anonymous
+ const char* kVirtualDeviceBackCameraId = "0";
+ const char* kVirtualDeviceFrontCameraId = "1";
+
+ int32_t getDeviceId(const android::CameraMetadata& cameraInfo) {
+ if (!cameraInfo.exists(ANDROID_INFO_DEVICE_ID)) {
+ return android::kDefaultDeviceId;
+ }
+
+ const auto &deviceIdEntry = cameraInfo.find(ANDROID_INFO_DEVICE_ID);
+ return deviceIdEntry.data.i32[0];
+ }
+} // namespace anonymous
namespace android {
@@ -98,6 +112,7 @@
using namespace camera3::SessionConfigurationUtils;
using binder::Status;
+using companion::virtualnative::IVirtualDeviceManagerNative;
using frameworks::cameraservice::service::V2_0::implementation::HidlCameraService;
using frameworks::cameraservice::service::implementation::AidlCameraService;
using hardware::ICamera;
@@ -107,7 +122,9 @@
using hardware::camera2::ICameraInjectionSession;
using hardware::camera2::utils::CameraIdAndSessionConfiguration;
using hardware::camera2::utils::ConcurrentCameraIdCombination;
+
namespace flags = com::android::internal::camera::flags;
+namespace vd_flags = android::companion::virtualdevice::flags;
// ----------------------------------------------------------------------------
// Logging support -- this is for debugging only
@@ -189,7 +206,6 @@
void CameraService::onFirstRef()
{
-
ALOGI("CameraService process starting");
BnCameraService::onFirstRef();
@@ -261,7 +277,6 @@
}
}
-
// Setup vendor tags before we call get_camera_info the first time
// because HAL might need to setup static vendor keys in get_camera_info
// TODO: maybe put this into CameraProviderManager::initialize()?
@@ -279,7 +294,6 @@
deviceIds = mCameraProviderManager->getCameraDeviceIds(&unavailPhysicalIds);
}
-
for (auto& cameraId : deviceIds) {
if (getCameraState(cameraId) == nullptr) {
onDeviceStatusChanged(cameraId, CameraDeviceStatus::PRESENT);
@@ -308,6 +322,10 @@
void CameraService::broadcastTorchModeStatus(const std::string& cameraId, TorchModeStatus status,
SystemCameraKind systemCameraKind) {
+ // Get the device id and app-visible camera id for the given HAL-visible camera id.
+ auto [deviceId, mappedCameraId] =
+ mVirtualDeviceCameraIdMapper.getDeviceIdAndMappedCameraIdPair(cameraId);
+
Mutex::Autolock lock(mStatusListenerLock);
for (auto& i : mListenerList) {
if (shouldSkipStatusUpdates(systemCameraKind, i->isVendorListener(), i->getListenerPid(),
@@ -316,18 +334,29 @@
__FUNCTION__, cameraId.c_str());
continue;
}
+
auto ret = i->getListener()->onTorchStatusChanged(mapToInterface(status),
- cameraId);
+ mappedCameraId, deviceId);
i->handleBinderStatus(ret, "%s: Failed to trigger onTorchStatusChanged for %d:%d: %d",
__FUNCTION__, i->getListenerUid(), i->getListenerPid(), ret.exceptionCode());
- // Also trigger the torch callbacks for cameras that were remapped to the current cameraId
- // for the specific package that this listener belongs to.
- std::vector<std::string> remappedCameraIds =
- findOriginalIdsForRemappedCameraId(cameraId, i->getListenerUid());
- for (auto& remappedCameraId : remappedCameraIds) {
- ret = i->getListener()->onTorchStatusChanged(mapToInterface(status), remappedCameraId);
- i->handleBinderStatus(ret, "%s: Failed to trigger onTorchStatusChanged for %d:%d: %d",
- __FUNCTION__, i->getListenerUid(), i->getListenerPid(), ret.exceptionCode());
+
+ // Only cameras of the default device can be remapped to a different camera (using
+ // remapCameraIds method), so do the following only if the camera is associated with the
+ // default device.
+ if (deviceId == kDefaultDeviceId) {
+ // For the default device, also trigger the torch callbacks for cameras that were
+ // remapped to the current cameraId for the specific package that this listener belongs
+ // to.
+ std::vector<std::string> remappedCameraIds =
+ findOriginalIdsForRemappedCameraId(cameraId, i->getListenerUid());
+ for (auto &remappedCameraId: remappedCameraIds) {
+ ret = i->getListener()->onTorchStatusChanged(mapToInterface(status),
+ remappedCameraId, kDefaultDeviceId);
+ i->handleBinderStatus(ret,
+ "%s: Failed to trigger onTorchStatusChanged for %d:%d: %d",
+ __FUNCTION__, i->getListenerUid(), i->getListenerPid(),
+ ret.exceptionCode());
+ }
}
}
}
@@ -346,10 +375,28 @@
void CameraService::filterAPI1SystemCameraLocked(
const std::vector<std::string> &normalDeviceIds) {
mNormalDeviceIdsWithoutSystemCamera.clear();
- for (auto &deviceId : normalDeviceIds) {
+ for (auto &cameraId : normalDeviceIds) {
+ if (vd_flags::camera_device_awareness()) {
+ CameraMetadata cameraInfo;
+ status_t res = mCameraProviderManager->getCameraCharacteristics(
+ cameraId, false, &cameraInfo, false);
+ int32_t deviceId = kDefaultDeviceId;
+ if (res != OK) {
+ ALOGW("%s: Not able to get camera characteristics for camera id %s",
+ __FUNCTION__, cameraId.c_str());
+ } else {
+ deviceId = getDeviceId(cameraInfo);
+ }
+ // Cameras associated with non-default device id's (i.e., virtual cameras) can never be
+ // system cameras, so skip for non-default device id's.
+ if (deviceId != kDefaultDeviceId) {
+ continue;
+ }
+ }
+
SystemCameraKind deviceKind = SystemCameraKind::PUBLIC;
- if (getSystemCameraKind(deviceId, &deviceKind) != OK) {
- ALOGE("%s: Invalid camera id %s, skipping", __FUNCTION__, deviceId.c_str());
+ if (getSystemCameraKind(cameraId, &deviceKind) != OK) {
+ ALOGE("%s: Invalid camera id %s, skipping", __FUNCTION__, cameraId.c_str());
continue;
}
if (deviceKind == SystemCameraKind::SYSTEM_ONLY_CAMERA) {
@@ -357,7 +404,7 @@
// device ids as per the HAL interface contract.
break;
}
- mNormalDeviceIdsWithoutSystemCamera.push_back(deviceId);
+ mNormalDeviceIdsWithoutSystemCamera.push_back(cameraId);
}
ALOGV("%s: number of API1 compatible public cameras is %zu", __FUNCTION__,
mNormalDeviceIdsWithoutSystemCamera.size());
@@ -511,10 +558,10 @@
if (newStatus == StatusInternal::NOT_PRESENT) {
logDeviceRemoved(cameraId, fmt::format("Device status changed from {} to {}",
oldStatus, newStatus));
-
// Set the device status to NOT_PRESENT, clients will no longer be able to connect
// to this device until the status changes
updateStatus(StatusInternal::NOT_PRESENT, cameraId);
+ mVirtualDeviceCameraIdMapper.removeCamera(cameraId);
sp<BasicClient> clientToDisconnectOnline, clientToDisconnectOffline;
{
@@ -596,7 +643,7 @@
continue;
}
auto ret = listener->getListener()->onPhysicalCameraStatusChanged(
- mapToInterface(newStatus), id, physicalId);
+ mapToInterface(newStatus), id, physicalId, kDefaultDeviceId);
listener->handleBinderStatus(ret,
"%s: Failed to trigger onPhysicalCameraStatusChanged for %d:%d: %d",
__FUNCTION__, listener->getListenerUid(), listener->getListenerPid(),
@@ -630,7 +677,6 @@
onTorchStatusChangedLocked(cameraId, newStatus, systemCameraKind);
}
-
void CameraService::onTorchStatusChanged(const std::string& cameraId,
TorchModeStatus newStatus, SystemCameraKind systemCameraKind) {
Mutex::Autolock al(mTorchStatusMutex);
@@ -639,9 +685,14 @@
void CameraService::broadcastTorchStrengthLevel(const std::string& cameraId,
int32_t newStrengthLevel) {
+ // Get the device id and app-visible camera id for the given HAL-visible camera id.
+ auto [deviceId, mappedCameraId] =
+ mVirtualDeviceCameraIdMapper.getDeviceIdAndMappedCameraIdPair(cameraId);
+
Mutex::Autolock lock(mStatusListenerLock);
for (auto& i : mListenerList) {
- auto ret = i->getListener()->onTorchStrengthLevelChanged(cameraId, newStrengthLevel);
+ auto ret = i->getListener()->onTorchStrengthLevelChanged(mappedCameraId,
+ newStrengthLevel, deviceId);
i->handleBinderStatus(ret,
"%s: Failed to trigger onTorchStrengthLevelChanged for %d:%d: %d", __FUNCTION__,
i->getListenerUid(), i->getListenerPid(), ret.exceptionCode());
@@ -746,8 +797,15 @@
return true;
}
-Status CameraService::getNumberOfCameras(int32_t type, int32_t* numCameras) {
+Status CameraService::getNumberOfCameras(int32_t type, int32_t deviceId, int32_t devicePolicy,
+ int32_t* numCameras) {
ATRACE_CALL();
+ if (vd_flags::camera_device_awareness() && (deviceId != kDefaultDeviceId)
+ && (devicePolicy != IVirtualDeviceManagerNative::DEVICE_POLICY_DEFAULT)) {
+ *numCameras = mVirtualDeviceCameraIdMapper.getNumberOfCameras(deviceId);
+ return Status::ok();
+ }
+
Mutex::Autolock l(mServiceLock);
bool hasSystemCameraPermissions =
hasPermissionsForSystemCamera(std::string(), getCallingPid(),
@@ -795,6 +853,7 @@
}
Status CameraService::createDefaultRequest(const std::string& unresolvedCameraId, int templateId,
+ int32_t deviceId, int32_t devicePolicy,
/* out */
hardware::camera2::impl::CameraMetadataNative* request) {
ATRACE_CALL();
@@ -809,8 +868,15 @@
return STATUS_ERROR(ERROR_DISCONNECTED, "Camera subsystem is not available");
}
- const std::string cameraId = resolveCameraId(unresolvedCameraId,
- getCallingUid());
+ std::optional<std::string> cameraIdOptional = resolveCameraId(unresolvedCameraId, deviceId,
+ devicePolicy, getCallingUid());
+ if (!cameraIdOptional.has_value()) {
+ std::string msg = fmt::sprintf("Camera %s: Invalid camera id for device id %d",
+ unresolvedCameraId.c_str(), deviceId);
+ ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
+ }
+ std::string cameraId = cameraIdOptional.value();
binder::Status res;
if (request == nullptr) {
@@ -851,6 +917,7 @@
Status CameraService::isSessionConfigurationWithParametersSupported(
const std::string& unresolvedCameraId,
const SessionConfiguration& sessionConfiguration,
+ int32_t deviceId, int32_t devicePolicy,
/*out*/
bool* supported) {
ATRACE_CALL();
@@ -865,8 +932,16 @@
return STATUS_ERROR(ERROR_DISCONNECTED, "Camera subsystem is not available");
}
- const std::string cameraId = resolveCameraId(unresolvedCameraId,
- getCallingUid());
+ std::optional<std::string> cameraIdOptional = resolveCameraId(unresolvedCameraId, deviceId,
+ devicePolicy, getCallingUid());
+ if (!cameraIdOptional.has_value()) {
+ std::string msg = fmt::sprintf("Camera %s: Invalid camera id for device id %d",
+ unresolvedCameraId.c_str(), deviceId);
+ ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
+ }
+ std::string cameraId = cameraIdOptional.value();
+
if (supported == nullptr) {
std::string msg = fmt::sprintf("Camera %s: Invalid 'support' input!",
unresolvedCameraId.c_str());
@@ -911,9 +986,9 @@
}
Status CameraService::getSessionCharacteristics(const std::string& unresolvedCameraId,
- int targetSdkVersion, bool overrideToPortrait,
- const SessionConfiguration& sessionConfiguration,
- /*out*/ CameraMetadata* outMetadata) {
+ int targetSdkVersion, bool overrideToPortrait,
+ const SessionConfiguration& sessionConfiguration, int32_t deviceId, int32_t devicePolicy,
+ /*out*/ CameraMetadata* outMetadata) {
ATRACE_CALL();
if (!mInitialized) {
@@ -922,9 +997,6 @@
return STATUS_ERROR(ERROR_DISCONNECTED, "Camera subsystem is not available");
}
- const std::string cameraId =
- resolveCameraId(unresolvedCameraId, getCallingUid());
-
if (outMetadata == nullptr) {
std::string msg =
fmt::sprintf("Camera %s: Invalid 'outMetadata' input!", unresolvedCameraId.c_str());
@@ -932,6 +1004,16 @@
return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
}
+ std::optional<std::string> cameraIdOptional = resolveCameraId(unresolvedCameraId, deviceId,
+ devicePolicy, getCallingUid());
+ if (!cameraIdOptional.has_value()) {
+ std::string msg = fmt::sprintf("Camera %s: Invalid camera id for device id %d",
+ unresolvedCameraId.c_str(), deviceId);
+ ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
+ }
+ std::string cameraId = cameraIdOptional.value();
+
bool overrideForPerfClass = SessionConfigurationUtils::targetPerfClassPrimaryCamera(
mPerfClassPrimaryCameraIds, cameraId, targetSdkVersion);
@@ -970,7 +1052,7 @@
/* out */ TCameraIdRemapping* cameraIdRemappingMap) {
std::string packageName;
std::string cameraIdToReplace, updatedCameraId;
- for(const auto& packageIdRemapping: cameraIdRemapping.packageIdRemappings) {
+ for (const auto& packageIdRemapping: cameraIdRemapping.packageIdRemappings) {
packageName = packageIdRemapping.packageName;
if (packageName.empty()) {
return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT,
@@ -982,7 +1064,7 @@
"CameraIdRemapping: Mismatch in CameraId Remapping lists sizes for package %s",
packageName.c_str());
}
- for(size_t i = 0; i < packageIdRemapping.cameraIdsToReplace.size(); i++) {
+ for (size_t i = 0; i < packageIdRemapping.cameraIdsToReplace.size(); i++) {
cameraIdToReplace = packageIdRemapping.cameraIdsToReplace[i];
updatedCameraId = packageIdRemapping.updatedCameraIds[i];
if (cameraIdToReplace.empty() || updatedCameraId.empty()) {
@@ -996,6 +1078,22 @@
" as updatedCameraId for %s",
packageName.c_str());
}
+
+ // Do not allow any camera remapping that involves a virtual camera.
+ auto [deviceIdForCameraToReplace, _] =
+ mVirtualDeviceCameraIdMapper.getDeviceIdAndMappedCameraIdPair(
+ cameraIdToReplace);
+ if (deviceIdForCameraToReplace != kDefaultDeviceId) {
+ return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT,
+ "CameraIdRemapping: CameraIdToReplace cannot be a virtual camera");
+ }
+ [[maybe_unused]] auto [deviceIdForUpdatedCamera, unusedMappedCameraId] =
+ mVirtualDeviceCameraIdMapper.getDeviceIdAndMappedCameraIdPair(updatedCameraId);
+ if (deviceIdForUpdatedCamera != kDefaultDeviceId) {
+ return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT,
+ "CameraIdRemapping: UpdatedCameraId cannot be a virtual camera");
+ }
+
(*cameraIdRemappingMap)[packageName][cameraIdToReplace] = updatedCameraId;
}
}
@@ -1064,9 +1162,9 @@
}
Status CameraService::injectSessionParams(
- const std::string& cameraId,
- const CameraMetadata& sessionParams) {
- if (!checkCallingPermission(toString16(sCameraInjectExternalCameraPermission))) {
+ const std::string& cameraId,
+ const CameraMetadata& sessionParams) {
+ if (!checkCallingPermission(toString16(sCameraInjectExternalCameraPermission))) {
const int pid = getCallingPid();
const int uid = getCallingUid();
ALOGE("%s: Permission Denial: can't inject session params pid=%d, uid=%d",
@@ -1075,6 +1173,13 @@
"Permission Denial: no permission to inject session params");
}
+ // Do not allow session params injection for a virtual camera.
+ auto [deviceId, _] = mVirtualDeviceCameraIdMapper.getDeviceIdAndMappedCameraIdPair(cameraId);
+ if (deviceId != kDefaultDeviceId) {
+ return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT,
+ "Cannot inject session params for a virtual camera");
+ }
+
std::unique_ptr<AutoConditionLock> serviceLockWrapper =
AutoConditionLock::waitAndAcquire(mServiceLockWrapper);
@@ -1140,13 +1245,40 @@
return inputCameraId;
}
-Status CameraService::getCameraInfo(int cameraId, bool overrideToPortrait,
- CameraInfo* cameraInfo) {
+std::optional<std::string> CameraService::resolveCameraId(
+ const std::string& inputCameraId,
+ int32_t deviceId,
+ int32_t devicePolicy,
+ int clientUid,
+ const std::string& packageName) {
+ if ((deviceId == kDefaultDeviceId)
+ || (devicePolicy == IVirtualDeviceManagerNative::DEVICE_POLICY_DEFAULT)) {
+ auto [storedDeviceId, _] =
+ mVirtualDeviceCameraIdMapper.getDeviceIdAndMappedCameraIdPair(inputCameraId);
+ if (storedDeviceId != kDefaultDeviceId) {
+ // Trying to access a virtual camera from default-policy device context, we should fail.
+ std::string msg = fmt::sprintf("Camera %s: Invalid camera id for device id %d",
+ inputCameraId.c_str(), deviceId);
+ ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+ return std::nullopt;
+ }
+ return resolveCameraId(inputCameraId, clientUid, packageName);
+ }
+
+ return mVirtualDeviceCameraIdMapper.getActualCameraId(deviceId, inputCameraId);
+}
+
+Status CameraService::getCameraInfo(int cameraId, bool overrideToPortrait, int32_t deviceId,
+ int32_t devicePolicy, CameraInfo* cameraInfo) {
ATRACE_CALL();
Mutex::Autolock l(mServiceLock);
- std::string unresolvedCameraId = cameraIdIntToStrLocked(cameraId);
- std::string cameraIdStr = resolveCameraId(
- unresolvedCameraId, getCallingUid());
+ std::string cameraIdStr = cameraIdIntToStrLocked(cameraId, deviceId, devicePolicy);
+ if (cameraIdStr.empty()) {
+ std::string msg = fmt::sprintf("Camera %d: Invalid camera id for device id %d",
+ cameraId, deviceId);
+ ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
+ }
if (shouldRejectSystemCameraConnection(cameraIdStr)) {
return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Unable to retrieve camera"
@@ -1184,36 +1316,44 @@
return ret;
}
-std::string CameraService::cameraIdIntToStrLocked(int cameraIdInt) {
- const std::vector<std::string> *deviceIds = &mNormalDeviceIdsWithoutSystemCamera;
+std::string CameraService::cameraIdIntToStrLocked(int cameraIdInt,
+ int32_t deviceId, int32_t devicePolicy) {
+ if (vd_flags::camera_device_awareness() && (deviceId != kDefaultDeviceId)
+ && (devicePolicy != IVirtualDeviceManagerNative::DEVICE_POLICY_DEFAULT)) {
+ std::optional<std::string> cameraIdOptional =
+ mVirtualDeviceCameraIdMapper.getActualCameraId(cameraIdInt, deviceId);
+ return cameraIdOptional.has_value() ? cameraIdOptional.value() : std::string{};
+ }
+
+ const std::vector<std::string> *cameraIds = &mNormalDeviceIdsWithoutSystemCamera;
auto callingPid = getCallingPid();
auto callingUid = getCallingUid();
bool systemCameraPermissions = hasPermissionsForSystemCamera(std::to_string(cameraIdInt),
callingPid, callingUid, /* checkCameraPermissions= */ false);
if (systemCameraPermissions || getpid() == callingPid) {
- deviceIds = &mNormalDeviceIds;
+ cameraIds = &mNormalDeviceIds;
}
- if (cameraIdInt < 0 || cameraIdInt >= static_cast<int>(deviceIds->size())) {
- ALOGE("%s: input id %d invalid: valid range (0, %zu)",
- __FUNCTION__, cameraIdInt, deviceIds->size());
+ if (cameraIdInt < 0 || cameraIdInt >= static_cast<int>(cameraIds->size())) {
+ ALOGE("%s: input id %d invalid: valid range (0, %zu)",
+ __FUNCTION__, cameraIdInt, cameraIds->size());
return std::string{};
}
- return (*deviceIds)[cameraIdInt];
+ std::string unresolvedCameraId = (*cameraIds)[cameraIdInt];
+ return resolveCameraId(unresolvedCameraId, getCallingUid());
}
-std::string CameraService::cameraIdIntToStr(int cameraIdInt) {
+std::string CameraService::cameraIdIntToStr(int cameraIdInt, int32_t deviceId,
+ int32_t devicePolicy) {
Mutex::Autolock lock(mServiceLock);
- return cameraIdIntToStrLocked(cameraIdInt);
+ return cameraIdIntToStrLocked(cameraIdInt, deviceId, devicePolicy);
}
Status CameraService::getCameraCharacteristics(const std::string& unresolvedCameraId,
- int targetSdkVersion, bool overrideToPortrait, CameraMetadata* cameraInfo) {
+ int targetSdkVersion, bool overrideToPortrait, int32_t deviceId, int32_t devicePolicy,
+ CameraMetadata* cameraInfo) {
ATRACE_CALL();
- const std::string cameraId = resolveCameraId(unresolvedCameraId,
- getCallingUid());
-
if (!cameraInfo) {
ALOGE("%s: cameraInfo is NULL", __FUNCTION__);
return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, "cameraInfo is NULL");
@@ -1226,6 +1366,16 @@
"Camera subsystem is not available");;
}
+ std::optional<std::string> cameraIdOptional = resolveCameraId(unresolvedCameraId, deviceId,
+ devicePolicy, getCallingUid());
+ if (!cameraIdOptional.has_value()) {
+ std::string msg = fmt::sprintf("Camera %s: Invalid camera id for device id %d",
+ unresolvedCameraId.c_str(), deviceId);
+ ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
+ }
+ std::string cameraId = cameraIdOptional.value();
+
if (shouldRejectSystemCameraConnection(cameraId)) {
return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Unable to retrieve camera"
"characteristics for system only device %s: ", cameraId.c_str());
@@ -1292,19 +1442,27 @@
return ret;
}
-Status CameraService::getTorchStrengthLevel(const std::string& unresolvedCameraId,
- int32_t* torchStrength) {
+Status CameraService::getTorchStrengthLevel(const std::string& unresolvedCameraId, int32_t deviceId,
+ int32_t devicePolicy, int32_t* torchStrength) {
ATRACE_CALL();
Mutex::Autolock l(mServiceLock);
- const std::string cameraId = resolveCameraId(
- unresolvedCameraId, getCallingUid());
+ std::optional<std::string> cameraIdOptional = resolveCameraId(unresolvedCameraId, deviceId,
+ devicePolicy, getCallingUid());
+ if (!cameraIdOptional.has_value()) {
+ std::string msg = fmt::sprintf("Camera %s: Invalid camera id for device id %d",
+ unresolvedCameraId.c_str(), deviceId);
+ ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
+ }
+ std::string cameraId = cameraIdOptional.value();
+
if (!mInitialized) {
ALOGE("%s: Camera HAL couldn't be initialized.", __FUNCTION__);
return STATUS_ERROR(ERROR_DISCONNECTED, "Camera HAL couldn't be initialized.");
}
- if(torchStrength == NULL) {
+ if (torchStrength == NULL) {
ALOGE("%s: strength level must not be null.", __FUNCTION__);
return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, "Strength level should not be null.");
}
@@ -2077,15 +2235,20 @@
int targetSdkVersion,
bool overrideToPortrait,
bool forceSlowJpegMode,
+ int32_t deviceId,
+ int32_t devicePolicy,
/*out*/
sp<ICamera>* device) {
-
ATRACE_CALL();
Status ret = Status::ok();
- std::string unresolvedCameraId = cameraIdIntToStr(api1CameraId);
- std::string cameraIdStr = resolveCameraId(unresolvedCameraId,
- getCallingUid());
+ std::string cameraIdStr = cameraIdIntToStr(api1CameraId, deviceId, devicePolicy);
+ if (cameraIdStr.empty()) {
+ std::string msg = fmt::sprintf("Camera %d: Invalid camera id for device id %d",
+ api1CameraId, deviceId);
+ ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
+ }
sp<Client> client = nullptr;
ret = connectHelper<ICameraClient,Client>(cameraClient, cameraIdStr, api1CameraId,
@@ -2093,9 +2256,8 @@
/*shimUpdateOnly*/ false, /*oomScoreOffset*/ 0, targetSdkVersion,
overrideToPortrait, forceSlowJpegMode, cameraIdStr, /*out*/client);
- if(!ret.isOk()) {
- logRejected(cameraIdStr, getCallingPid(), clientPackageName,
- toStdString(ret.toString8()));
+ if (!ret.isOk()) {
+ logRejected(cameraIdStr, getCallingPid(), clientPackageName, toStdString(ret.toString8()));
return ret;
}
@@ -2175,10 +2337,9 @@
const std::string& clientPackageName,
const std::optional<std::string>& clientFeatureId,
int clientUid, int oomScoreOffset, int targetSdkVersion,
- bool overrideToPortrait,
+ bool overrideToPortrait, int32_t deviceId, int32_t devicePolicy,
/*out*/
sp<hardware::camera2::ICameraDeviceUser>* device) {
-
ATRACE_CALL();
Status ret = Status::ok();
sp<CameraDeviceClient> client = nullptr;
@@ -2192,10 +2353,15 @@
systemNativeClient = true;
}
- const std::string cameraId = resolveCameraId(
- unresolvedCameraId,
- callingUid,
- clientPackageNameAdj);
+ std::optional<std::string> cameraIdOptional = resolveCameraId(unresolvedCameraId, deviceId,
+ devicePolicy, callingUid, clientPackageNameAdj);
+ if (!cameraIdOptional.has_value()) {
+ std::string msg = fmt::sprintf("Camera %s: Invalid camera id for device id %d",
+ unresolvedCameraId.c_str(), deviceId);
+ ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
+ }
+ std::string cameraId = cameraIdOptional.value();
if (oomScoreOffset < 0) {
std::string msg =
@@ -2238,7 +2404,7 @@
targetSdkVersion, overrideToPortrait, /*forceSlowJpegMode*/false, unresolvedCameraId,
/*out*/client);
- if(!ret.isOk()) {
+ if (!ret.isOk()) {
logRejected(cameraId, callingPid, clientPackageNameAdj, toStdString(ret.toString8()));
return ret;
}
@@ -2397,7 +2563,7 @@
}
// Enforce client permissions and do basic validity checks
- if(!(ret = validateConnectLocked(cameraId, clientPackageName,
+ if (!(ret = validateConnectLocked(cameraId, clientPackageName,
/*inout*/clientUid, /*inout*/clientPid, /*out*/originalClientPid)).isOk()) {
return ret;
}
@@ -2755,7 +2921,8 @@
}
Status CameraService::turnOnTorchWithStrengthLevel(const std::string& unresolvedCameraId,
- int32_t torchStrength, const sp<IBinder>& clientBinder) {
+ int32_t torchStrength, const sp<IBinder>& clientBinder, int32_t deviceId,
+ int32_t devicePolicy) {
Mutex::Autolock lock(mServiceLock);
ATRACE_CALL();
@@ -2766,7 +2933,16 @@
}
int uid = getCallingUid();
- const std::string cameraId = resolveCameraId(unresolvedCameraId, uid);
+ std::optional<std::string> cameraIdOptional = resolveCameraId(unresolvedCameraId, deviceId,
+ devicePolicy, uid);
+ if (!cameraIdOptional.has_value()) {
+ std::string msg = fmt::sprintf("Camera %s: Invalid camera id for device id %d",
+ unresolvedCameraId.c_str(), deviceId);
+ ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
+ }
+ std::string cameraId = cameraIdOptional.value();
+
if (shouldRejectSystemCameraConnection(cameraId)) {
return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT, "Unable to change the strength level"
"for system only device %s: ", cameraId.c_str());
@@ -2883,7 +3059,7 @@
}
Status CameraService::setTorchMode(const std::string& unresolvedCameraId, bool enabled,
- const sp<IBinder>& clientBinder) {
+ const sp<IBinder>& clientBinder, int32_t deviceId, int32_t devicePolicy) {
Mutex::Autolock lock(mServiceLock);
ATRACE_CALL();
@@ -2894,7 +3070,15 @@
}
int uid = getCallingUid();
- const std::string cameraId = resolveCameraId(unresolvedCameraId, uid);
+ std::optional<std::string> cameraIdOptional = resolveCameraId(unresolvedCameraId, deviceId,
+ devicePolicy, uid);
+ if (!cameraIdOptional.has_value()) {
+ std::string msg = fmt::sprintf("Camera %s: Invalid camera id for device id %d",
+ unresolvedCameraId.c_str(), deviceId);
+ ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
+ }
+ std::string cameraId = cameraIdOptional.value();
if (shouldRejectSystemCameraConnection(cameraId)) {
return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT, "Unable to set torch mode"
@@ -3165,6 +3349,7 @@
return Status::ok();
}
+// TODO(b/291736219): This to be made device-aware.
Status CameraService::getConcurrentCameraIds(
std::vector<ConcurrentCameraIdCombination>* concurrentCameraIds) {
ATRACE_CALL();
@@ -3261,7 +3446,6 @@
/*out*/
std::vector<hardware::CameraStatus> *cameraStatuses,
bool isVendorListener, bool isProcessLocalTest) {
-
ATRACE_CALL();
ALOGV("%s: Add listener %p", __FUNCTION__, listener.get());
@@ -3309,9 +3493,14 @@
{
Mutex::Autolock lock(mCameraStatesLock);
for (auto& i : mCameraStates) {
- cameraStatuses->emplace_back(i.first,
+ // Get the device id and app-visible camera id for the given HAL-visible camera id.
+ auto [deviceId, mappedCameraId] =
+ mVirtualDeviceCameraIdMapper.getDeviceIdAndMappedCameraIdPair(i.first);
+
+ cameraStatuses->emplace_back(mappedCameraId,
mapToInterface(i.second->getStatus()), i.second->getUnavailablePhysicalIds(),
- openCloseCallbackAllowed ? i.second->getClientPackage() : std::string());
+ openCloseCallbackAllowed ? i.second->getClientPackage() : std::string(),
+ deviceId);
}
}
// Remove the camera statuses that should be hidden from the client, we do
@@ -3320,19 +3509,38 @@
// the same time.
cameraStatuses->erase(std::remove_if(cameraStatuses->begin(), cameraStatuses->end(),
[this, &isVendorListener, &clientPid, &clientUid](const hardware::CameraStatus& s) {
- SystemCameraKind deviceKind = SystemCameraKind::PUBLIC;
- if (getSystemCameraKind(s.cameraId, &deviceKind) != OK) {
- ALOGE("%s: Invalid camera id %s, skipping status update",
- __FUNCTION__, s.cameraId.c_str());
- return true;
- }
- return shouldSkipStatusUpdates(deviceKind, isVendorListener, clientPid,
- clientUid);}), cameraStatuses->end());
+ std::string cameraId = s.cameraId;
+ std::optional<std::string> cameraIdOptional = resolveCameraId(s.cameraId,
+ s.deviceId, IVirtualDeviceManagerNative::DEVICE_POLICY_CUSTOM,
+ clientUid);
+ if (!cameraIdOptional.has_value()) {
+ std::string msg =
+ fmt::sprintf(
+ "Camera %s: Invalid camera id for device id %d",
+ s.cameraId.c_str(), s.deviceId);
+ ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+ return true;
+ }
+ cameraId = cameraIdOptional.value();
+ SystemCameraKind deviceKind = SystemCameraKind::PUBLIC;
+ if (getSystemCameraKind(cameraId, &deviceKind) != OK) {
+ ALOGE("%s: Invalid camera id %s, skipping status update",
+ __FUNCTION__, s.cameraId.c_str());
+ return true;
+ }
+ return shouldSkipStatusUpdates(deviceKind, isVendorListener, clientPid,
+ clientUid);
+ }), cameraStatuses->end());
- //cameraStatuses will have non-eligible camera ids removed.
+ // cameraStatuses will have non-eligible camera ids removed.
std::set<std::string> idsChosenForCallback;
for (const auto &s : *cameraStatuses) {
- idsChosenForCallback.insert(s.cameraId);
+ // Add only default device cameras here, as virtual cameras currently don't support torch
+ // anyway. Note that this is a simplification of the implementation here, and we should
+ // change this when virtual cameras support torch.
+ if (s.deviceId == kDefaultDeviceId) {
+ idsChosenForCallback.insert(s.cameraId);
+ }
}
/*
@@ -3346,7 +3554,8 @@
// The camera id is visible to the client. Fine to send torch
// callback.
if (idsChosenForCallback.find(id) != idsChosenForCallback.end()) {
- listener->onTorchStatusChanged(mapToInterface(mTorchStatusMap.valueAt(i)), id);
+ listener->onTorchStatusChanged(mapToInterface(mTorchStatusMap.valueAt(i)), id,
+ kDefaultDeviceId);
}
}
}
@@ -3500,7 +3709,21 @@
const int uid = getCallingUid();
ALOGE("Permission Denial: can't inject camera pid=%d, uid=%d", pid, uid);
return STATUS_ERROR(ERROR_PERMISSION_DENIED,
- "Permission Denial: no permission to inject camera");
+ "Permission Denial: no permission to inject camera");
+ }
+
+ // Do not allow any camera injection that injects or replaces a virtual camera.
+ auto [deviceIdForInternalCamera, _] =
+ mVirtualDeviceCameraIdMapper.getDeviceIdAndMappedCameraIdPair(internalCamId);
+ if (deviceIdForInternalCamera != kDefaultDeviceId) {
+ return STATUS_ERROR(ICameraInjectionCallback::ERROR_INJECTION_UNSUPPORTED,
+ "Cannot replace a virtual camera");
+ }
+ [[maybe_unused]] auto [deviceIdForExternalCamera, unusedMappedCameraId] =
+ mVirtualDeviceCameraIdMapper.getDeviceIdAndMappedCameraIdPair(externalCamId);
+ if (deviceIdForExternalCamera != kDefaultDeviceId) {
+ return STATUS_ERROR(ICameraInjectionCallback::ERROR_INJECTION_UNSUPPORTED,
+ "Cannot inject a virtual camera to replace an internal camera");
}
ALOGV(
@@ -3530,7 +3753,7 @@
mInjectionExternalCamId.c_str());
}
res = clientSp->injectCamera(mInjectionExternalCamId, mCameraProviderManager);
- if(res != OK) {
+ if (res != OK) {
mInjectionStatusListener->notifyInjectionError(mInjectionExternalCamId, res);
}
} else {
@@ -3567,7 +3790,6 @@
std::unique_ptr<AutoConditionLock> lock =
AutoConditionLock::waitAndAcquire(mServiceLockWrapper);
-
std::vector<sp<BasicClient>> evicted;
for (auto& i : mActiveClientManager.getAll()) {
auto clientSp = i->getValue();
@@ -3836,7 +4058,6 @@
// We share the media players for shutter and recording sound for all clients.
// A reference count is kept to determine when we will actually release the
// media players.
-
sp<MediaPlayer> CameraService::newMediaPlayer(const char *file) {
sp<MediaPlayer> mp = new MediaPlayer();
status_t error;
@@ -4965,7 +5186,6 @@
}
}
-
// ----------------------------------------------------------------------------
// CameraClientManager
// ----------------------------------------------------------------------------
@@ -5496,6 +5716,36 @@
return;
}
+ if (vd_flags::camera_device_awareness() && status == StatusInternal::PRESENT) {
+ CameraMetadata cameraInfo;
+ status_t res = mCameraProviderManager->getCameraCharacteristics(
+ cameraId, false, &cameraInfo, false);
+ if (res != OK) {
+ ALOGW("%s: Not able to get camera characteristics for camera id %s",
+ __FUNCTION__, cameraId.c_str());
+ } else {
+ int32_t deviceId = getDeviceId(cameraInfo);
+ if (deviceId != kDefaultDeviceId) {
+ const auto &lensFacingEntry = cameraInfo.find(ANDROID_LENS_FACING);
+ camera_metadata_enum_android_lens_facing_t androidLensFacing =
+ static_cast<camera_metadata_enum_android_lens_facing_t>(
+ lensFacingEntry.data.u8[0]);
+ std::string mappedCameraId;
+ if (androidLensFacing == ANDROID_LENS_FACING_BACK) {
+ mappedCameraId = kVirtualDeviceBackCameraId;
+ } else if (androidLensFacing == ANDROID_LENS_FACING_FRONT) {
+ mappedCameraId = kVirtualDeviceFrontCameraId;
+ } else {
+ ALOGD("%s: Not adding entry for an external camera of a virtual device",
+ __func__);
+ }
+ if (!mappedCameraId.empty()) {
+ mVirtualDeviceCameraIdMapper.addCamera(cameraId, deviceId, mappedCameraId);
+ }
+ }
+ }
+ }
+
// Collect the logical cameras without holding mStatusLock in updateStatus
// as that can lead to a deadlock(b/162192331).
auto logicalCameraIds = getLogicalCameras(cameraId);
@@ -5504,55 +5754,67 @@
state->updateStatus(status, cameraId, rejectSourceStates, [this, &deviceKind,
&logicalCameraIds]
(const std::string& cameraId, StatusInternal status) {
+ // Get the device id and app-visible camera id for the given HAL-visible camera id.
+ auto [deviceId, mappedCameraId] =
+ mVirtualDeviceCameraIdMapper.getDeviceIdAndMappedCameraIdPair(cameraId);
- if (status != StatusInternal::ENUMERATING) {
- // Update torch status if it has a flash unit.
- Mutex::Autolock al(mTorchStatusMutex);
- TorchModeStatus torchStatus;
- if (getTorchStatusLocked(cameraId, &torchStatus) !=
- NAME_NOT_FOUND) {
- TorchModeStatus newTorchStatus =
- status == StatusInternal::PRESENT ?
- TorchModeStatus::AVAILABLE_OFF :
- TorchModeStatus::NOT_AVAILABLE;
- if (torchStatus != newTorchStatus) {
- onTorchStatusChangedLocked(cameraId, newTorchStatus, deviceKind);
+ if (status != StatusInternal::ENUMERATING) {
+ // Update torch status if it has a flash unit.
+ Mutex::Autolock al(mTorchStatusMutex);
+ TorchModeStatus torchStatus;
+ if (getTorchStatusLocked(cameraId, &torchStatus) !=
+ NAME_NOT_FOUND) {
+ TorchModeStatus newTorchStatus =
+ status == StatusInternal::PRESENT ?
+ TorchModeStatus::AVAILABLE_OFF :
+ TorchModeStatus::NOT_AVAILABLE;
+ if (torchStatus != newTorchStatus) {
+ onTorchStatusChangedLocked(cameraId, newTorchStatus, deviceKind);
+ }
}
}
- }
- Mutex::Autolock lock(mStatusListenerLock);
- notifyPhysicalCameraStatusLocked(mapToInterface(status), cameraId,
- logicalCameraIds, deviceKind);
+ Mutex::Autolock lock(mStatusListenerLock);
+ notifyPhysicalCameraStatusLocked(mapToInterface(status), mappedCameraId,
+ logicalCameraIds, deviceKind, deviceId);
- for (auto& listener : mListenerList) {
- bool isVendorListener = listener->isVendorListener();
- if (shouldSkipStatusUpdates(deviceKind, isVendorListener,
- listener->getListenerPid(), listener->getListenerUid())) {
- ALOGV("Skipping discovery callback for system-only camera device %s",
- cameraId.c_str());
- continue;
- }
- auto ret = listener->getListener()->onStatusChanged(mapToInterface(status),
- cameraId);
- listener->handleBinderStatus(ret,
- "%s: Failed to trigger onStatusChanged callback for %d:%d: %d",
- __FUNCTION__, listener->getListenerUid(), listener->getListenerPid(),
- ret.exceptionCode());
- // Also trigger the callbacks for cameras that were remapped to the current
- // cameraId for the specific package that this listener belongs to.
- std::vector<std::string> remappedCameraIds =
- findOriginalIdsForRemappedCameraId(cameraId, listener->getListenerUid());
- for (auto& remappedCameraId : remappedCameraIds) {
- ret = listener->getListener()->onStatusChanged(
- mapToInterface(status), remappedCameraId);
+ for (auto& listener : mListenerList) {
+ bool isVendorListener = listener->isVendorListener();
+ if (shouldSkipStatusUpdates(deviceKind, isVendorListener,
+ listener->getListenerPid(), listener->getListenerUid())) {
+ ALOGV("Skipping discovery callback for system-only camera device %s",
+ cameraId.c_str());
+ continue;
+ }
+
+ auto ret = listener->getListener()->onStatusChanged(mapToInterface(status),
+ mappedCameraId, deviceId);
listener->handleBinderStatus(ret,
- "%s: Failed to trigger onStatusChanged callback for %d:%d: %d",
+ "%s: Failed to trigger onStatusChanged callback for %d:%d: %d",
__FUNCTION__, listener->getListenerUid(), listener->getListenerPid(),
ret.exceptionCode());
+
+ // Only cameras of the default device can be remapped to a different camera
+ // (using remapCameraIds method), so do the following only if the camera is
+ // associated with the default device.
+ if (deviceId == kDefaultDeviceId) {
+ // For the default device, also trigger the callbacks for cameras that were
+ // remapped to the current cameraId for the specific package that this
+ // listener belongs to.
+ std::vector<std::string> remappedCameraIds =
+ findOriginalIdsForRemappedCameraId(cameraId,
+ listener->getListenerUid());
+ for (auto &remappedCameraId: remappedCameraIds) {
+ ret = listener->getListener()->onStatusChanged(
+ mapToInterface(status), remappedCameraId, kDefaultDeviceId);
+ listener->handleBinderStatus(ret,
+ "%s: Failed to trigger onStatusChanged callback for %d:%d: %d",
+ __FUNCTION__, listener->getListenerUid(),
+ listener->getListenerPid(), ret.exceptionCode());
+ }
+ }
}
- }
- });
+ });
}
void CameraService::updateOpenCloseStatus(const std::string& cameraId, bool open,
@@ -5569,6 +5831,10 @@
state->setClientPackage(std::string());
}
+ // Get the device id and app-visible camera id for the given HAL-visible camera id.
+ auto [deviceId, mappedCameraId] =
+ mVirtualDeviceCameraIdMapper.getDeviceIdAndMappedCameraIdPair(cameraId);
+
Mutex::Autolock lock(mStatusListenerLock);
for (const auto& it : mListenerList) {
@@ -5578,9 +5844,10 @@
binder::Status ret;
if (open) {
- ret = it->getListener()->onCameraOpened(cameraId, clientPackageName);
+ ret = it->getListener()->onCameraOpened(mappedCameraId, clientPackageName,
+ deviceId);
} else {
- ret = it->getListener()->onCameraClosed(cameraId);
+ ret = it->getListener()->onCameraClosed(mappedCameraId, deviceId);
}
it->handleBinderStatus(ret,
@@ -5673,7 +5940,7 @@
void CameraService::notifyPhysicalCameraStatusLocked(int32_t status,
const std::string& physicalCameraId, const std::list<std::string>& logicalCameraIds,
- SystemCameraKind deviceKind) {
+ SystemCameraKind deviceKind, int32_t deviceId) {
// mStatusListenerLock is expected to be locked
for (const auto& logicalCameraId : logicalCameraIds) {
for (auto& listener : mListenerList) {
@@ -5687,7 +5954,7 @@
continue;
}
auto ret = listener->getListener()->onPhysicalCameraStatusChanged(status,
- logicalCameraId, physicalCameraId);
+ logicalCameraId, physicalCameraId, deviceId);
listener->handleBinderStatus(ret,
"%s: Failed to trigger onPhysicalCameraStatusChanged for %d:%d: %d",
__FUNCTION__, listener->getListenerUid(), listener->getListenerPid(),
@@ -5696,7 +5963,6 @@
}
}
-
void CameraService::blockClientsForUid(uid_t uid) {
const auto clients = mActiveClientManager.getAll();
for (auto& current : clients) {
@@ -6086,7 +6352,7 @@
" prints the monitored information in real time\n"
" Hit return to exit\n"
" clear clears all buffers storing information for watch command");
- return BAD_VALUE;
+ return BAD_VALUE;
}
status_t CameraService::startWatchingTags(const Vector<String16> &args, int outFd) {
@@ -6494,4 +6760,4 @@
mInjectionStatusListener->removeListener();
}
-}; // namespace android
+} // namespace android
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index f25cf7d..b4c2edd 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -55,12 +55,14 @@
#include "utils/IPCTransport.h"
#include "utils/CameraServiceProxyWrapper.h"
#include "utils/AttributionAndPermissionUtils.h"
+#include "utils/VirtualDeviceCameraIdMapper.h"
#include <set>
#include <string>
#include <list>
#include <map>
#include <memory>
+#include <mutex>
#include <optional>
#include <utility>
#include <unordered_map>
@@ -150,14 +152,17 @@
/////////////////////////////////////////////////////////////////////
// ICameraService
// IMPORTANT: All binder calls that deal with logicalCameraId should use
- // resolveCameraId(logicalCameraId) to arrive at the correct cameraId to
- // perform the operation on (in case of Id Remapping).
- virtual binder::Status getNumberOfCameras(int32_t type, int32_t* numCameras);
+ // resolveCameraId(logicalCameraId, deviceId, devicePolicy) to arrive at the correct
+ // cameraId to perform the operation on (in case of Id Remapping, or in case of contexts
+ // associated with virtual devices).
+ virtual binder::Status getNumberOfCameras(int32_t type, int32_t deviceId,
+ int32_t devicePolicy, int32_t* numCameras);
virtual binder::Status getCameraInfo(int cameraId, bool overrideToPortrait,
- hardware::CameraInfo* cameraInfo) override;
+ int32_t deviceId, int32_t devicePolicy, hardware::CameraInfo* cameraInfo) override;
virtual binder::Status getCameraCharacteristics(const std::string& cameraId,
- int targetSdkVersion, bool overrideToPortrait, CameraMetadata* cameraInfo) override;
+ int targetSdkVersion, bool overrideToPortrait, int32_t deviceId,
+ int32_t devicePolicy, CameraMetadata* cameraInfo) override;
virtual binder::Status getCameraVendorTagDescriptor(
/*out*/
hardware::camera2::params::VendorTagDescriptor* desc);
@@ -168,15 +173,15 @@
virtual binder::Status connect(const sp<hardware::ICameraClient>& cameraClient,
int32_t cameraId, const std::string& clientPackageName,
int32_t clientUid, int clientPid, int targetSdkVersion,
- bool overrideToPortrait, bool forceSlowJpegMode,
- /*out*/
- sp<hardware::ICamera>* device) override;
+ bool overrideToPortrait, bool forceSlowJpegMode, int32_t deviceId,
+ int32_t devicePolicy, /*out*/ sp<hardware::ICamera>* device) override;
virtual binder::Status connectDevice(
const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb,
const std::string& cameraId,
const std::string& clientPackageName, const std::optional<std::string>& clientFeatureId,
int32_t clientUid, int scoreOffset, int targetSdkVersion, bool overrideToPortrait,
+ int32_t deviceId, int32_t devicePolicy,
/*out*/
sp<hardware::camera2::ICameraDeviceUser>* device);
@@ -186,6 +191,7 @@
virtual binder::Status removeListener(
const sp<hardware::ICameraServiceListener>& listener);
+ // TODO(b/291736219): This to be made device-aware.
virtual binder::Status getConcurrentCameraIds(
/*out*/
std::vector<hardware::camera2::utils::ConcurrentCameraIdCombination>* concurrentCameraIds);
@@ -200,13 +206,14 @@
std::string* parameters);
virtual binder::Status setTorchMode(const std::string& cameraId, bool enabled,
- const sp<IBinder>& clientBinder);
+ const sp<IBinder>& clientBinder, int32_t deviceId, int32_t devicePolicy);
virtual binder::Status turnOnTorchWithStrengthLevel(const std::string& cameraId,
- int32_t torchStrength, const sp<IBinder>& clientBinder);
+ int32_t torchStrength, const sp<IBinder>& clientBinder, int32_t deviceId,
+ int32_t devicePolicy);
- virtual binder::Status getTorchStrengthLevel(const std::string& cameraId,
- int32_t* torchStrength);
+ virtual binder::Status getTorchStrengthLevel(const std::string& cameraId, int32_t deviceId,
+ int32_t devicePolicy, int32_t* torchStrength);
virtual binder::Status notifySystemEvent(int32_t eventId,
const std::vector<int32_t>& args);
@@ -244,19 +251,21 @@
const hardware::camera2::impl::CameraMetadataNative& sessionParams);
virtual binder::Status createDefaultRequest(const std::string& cameraId, int templateId,
+ int32_t deviceId, int32_t devicePolicy,
/*out*/
hardware::camera2::impl::CameraMetadataNative* request);
virtual binder::Status isSessionConfigurationWithParametersSupported(
const std::string& cameraId,
const SessionConfiguration& sessionConfiguration,
+ int32_t deviceId, int32_t devicePolicy,
/*out*/
bool* supported);
virtual binder::Status getSessionCharacteristics(
const std::string& cameraId, int targetSdkVersion, bool overrideToPortrait,
- const SessionConfiguration& sessionConfiguration,
- /*out*/ CameraMetadata* outMetadata);
+ const SessionConfiguration& sessionConfiguration, int32_t deviceId,
+ int32_t devicePolicy, /*out*/ CameraMetadata* outMetadata);
// Extra permissions checks
virtual status_t onTransact(uint32_t code, const Parcel& data,
@@ -1045,10 +1054,11 @@
/* out */ TCameraIdRemapping* cameraIdRemappingMap);
/**
- * Resolve the (potentially remapped) camera Id to use for packageName.
+ * Resolve the (potentially remapped) camera id to use for packageName for the default device
+ * context.
*
- * This returns the Camera Id to use in case inputCameraId was remapped to a
- * different Id for the given packageName. Otherwise, it returns the inputCameraId.
+ * This returns the Camera id to use in case inputCameraId was remapped to a
+ * different id for the given packageName. Otherwise, it returns the inputCameraId.
*
* If the packageName is not provided, it will be inferred from the clientUid.
*/
@@ -1058,6 +1068,26 @@
const std::string& packageName = "");
/**
+ * Resolve the (potentially remapped) camera id for the given input camera id and the given
+ * device id and device policy (for the device associated with the context of the caller).
+ *
+ * For any context associated with the default device or a virtual device with default camera
+ * policy, this will return the actual camera id (in case inputCameraId was remapped using
+ * the remapCameraIds method).
+ *
+ * For any context associated with a virtual device with custom camera policy, this will return
+ * the actual camera id if inputCameraId corresponds to the mapped id of a virtual camera
+ * (for virtual devices with custom camera policy, the back and front virtual cameras of that
+ * device would have 0 and 1 respectively as their mapped camera id).
+ */
+ std::optional<std::string> resolveCameraId(
+ const std::string& inputCameraId,
+ int32_t deviceId,
+ int32_t devicePolicy,
+ int clientUid,
+ const std::string& packageName = "");
+
+ /**
* Updates the state of mCameraIdRemapping, while disconnecting active clients as necessary.
*/
void remapCameraIds(const TCameraIdRemapping& cameraIdRemapping);
@@ -1122,13 +1152,13 @@
* Returns the underlying camera Id string mapped to a camera id int
* Empty string is returned when the cameraIdInt is invalid.
*/
- std::string cameraIdIntToStr(int cameraIdInt);
+ std::string cameraIdIntToStr(int cameraIdInt, int32_t deviceId, int32_t devicePolicy);
/**
* Returns the underlying camera Id string mapped to a camera id int
* Empty string is returned when the cameraIdInt is invalid.
*/
- std::string cameraIdIntToStrLocked(int cameraIdInt);
+ std::string cameraIdIntToStrLocked(int cameraIdInt, int32_t deviceId, int32_t devicePolicy);
/**
* Remove a single client corresponding to the given camera id from the list of active clients.
@@ -1328,6 +1358,8 @@
*
* This method must be idempotent.
* This method acquires mStatusLock and mStatusListenerLock.
+ * For any virtual camera, this method must pass its mapped camera id and device id to
+ * ICameraServiceListeners (using mVirtualDeviceCameraIdMapper).
*/
void updateStatus(StatusInternal status,
const std::string& cameraId,
@@ -1381,7 +1413,8 @@
// notify physical camera status when the physical camera is public.
// Expects mStatusListenerLock to be locked.
void notifyPhysicalCameraStatusLocked(int32_t status, const std::string& physicalCameraId,
- const std::list<std::string>& logicalCameraIds, SystemCameraKind deviceKind);
+ const std::list<std::string>& logicalCameraIds, SystemCameraKind deviceKind,
+ int32_t virtualDeviceId);
// get list of logical cameras which are backed by physicalCameraId
std::list<std::string> getLogicalCameras(const std::string& physicalCameraId);
@@ -1617,6 +1650,8 @@
int64_t mDeviceState;
void updateTorchUidMapLocked(const std::string& cameraId, int uid);
+
+ VirtualDeviceCameraIdMapper mVirtualDeviceCameraIdMapper;
};
} // namespace android
diff --git a/services/camera/libcameraservice/TEST_MAPPING b/services/camera/libcameraservice/TEST_MAPPING
index ca6cc58..6257aee 100644
--- a/services/camera/libcameraservice/TEST_MAPPING
+++ b/services/camera/libcameraservice/TEST_MAPPING
@@ -4,6 +4,17 @@
"name": "cameraservice_test"
}
],
+ "postsubmit": [
+ {
+ "name": "CtsVirtualDevicesCameraTestCases",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ],
+ "keywords": ["primary-device"]
+ }
+ ],
"imports": [
{
"path": "frameworks/av/camera"
diff --git a/services/camera/libcameraservice/aidl/AidlCameraService.cpp b/services/camera/libcameraservice/aidl/AidlCameraService.cpp
index 79dbfed..cb11023 100644
--- a/services/camera/libcameraservice/aidl/AidlCameraService.cpp
+++ b/services/camera/libcameraservice/aidl/AidlCameraService.cpp
@@ -26,6 +26,7 @@
#include <android/binder_ibinder.h>
#include <android/binder_manager.h>
#include <binder/Status.h>
+#include <camera/CameraUtils.h>
#include <hidl/HidlTransportSupport.h>
#include <utils/Utils.h>
@@ -90,6 +91,8 @@
UStatus ret = mCameraService->getCameraCharacteristics(in_cameraId,
mVndkVersion,
/* overrideToPortrait= */ false,
+ kDefaultDeviceId,
+ /* devicePolicy= */ 0,
&cameraMetadata);
if (!ret.isOk()) {
if (ret.exceptionCode() != EX_SERVICE_SPECIFIC) {
@@ -148,6 +151,8 @@
/* scoreOffset= */ 0,
/* targetSdkVersion= */ __ANDROID_API_FUTURE__,
/* overrideToPortrait= */ false,
+ kDefaultDeviceId,
+ /* devicePolicy= */ 0,
&unstableDevice);
if (!serviceRet.isOk()) {
ALOGE("%s: Unable to connect to camera device: %s", __FUNCTION__,
diff --git a/services/camera/libcameraservice/aidl/AidlCameraServiceListener.cpp b/services/camera/libcameraservice/aidl/AidlCameraServiceListener.cpp
index d7ab0d9..dc5c7f5 100644
--- a/services/camera/libcameraservice/aidl/AidlCameraServiceListener.cpp
+++ b/services/camera/libcameraservice/aidl/AidlCameraServiceListener.cpp
@@ -18,6 +18,7 @@
#include <aidl/AidlUtils.h>
#include <aidl/android/frameworks/cameraservice/common/Status.h>
#include <aidl/android/frameworks/cameraservice/service/CameraStatusAndId.h>
+#include <camera/CameraUtils.h>
#include <camera/StringUtils.h>
namespace android::frameworks::cameraservice::service::implementation {
@@ -28,7 +29,10 @@
using SStatus = ::aidl::android::frameworks::cameraservice::common::Status;
binder::Status AidlCameraServiceListener::onStatusChanged(
- int32_t status, const std::string& cameraId) {
+ int32_t status, const std::string& cameraId, int32_t deviceId) {
+ if (deviceId != kDefaultDeviceId) {
+ return binder::Status::ok();
+ }
SCameraDeviceStatus sStatus = convertCameraStatusToAidl(status);
auto ret = mBase->onStatusChanged(sStatus, cameraId);
LOG_STATUS_ERROR_IF_NOT_OK(ret, "onStatusChanged")
@@ -37,7 +41,10 @@
binder::Status AidlCameraServiceListener::onPhysicalCameraStatusChanged(
int32_t status, const std::string& cameraId,
- const std::string& physicalCameraId) {
+ const std::string& physicalCameraId, int32_t deviceId) {
+ if (deviceId != kDefaultDeviceId) {
+ return binder::Status::ok();
+ }
SCameraDeviceStatus sStatus = convertCameraStatusToAidl(status);
auto ret = mBase->onPhysicalCameraStatusChanged(sStatus, cameraId, physicalCameraId);
@@ -46,20 +53,22 @@
}
::android::binder::Status AidlCameraServiceListener::onTorchStatusChanged(
- int32_t, const std::string&) {
+ [[maybe_unused]] int32_t, [[maybe_unused]] const std::string&, int32_t) {
// We don't implement onTorchStatusChanged
return binder::Status::ok();
}
::android::binder::Status AidlCameraServiceListener::onTorchStrengthLevelChanged(
- const std::string&, int32_t) {
+ [[maybe_unused]] const std::string&, [[maybe_unused]] int32_t, [[maybe_unused]] int32_t) {
// We don't implement onTorchStrengthLevelChanged
return binder::Status::ok();
}
+
status_t AidlCameraServiceListener::linkToDeath(const sp<DeathRecipient>& recipient, void* cookie,
uint32_t flags) {
return mDeathPipe.linkToDeath(recipient, cookie, flags);
}
+
status_t AidlCameraServiceListener::unlinkToDeath(const wp<DeathRecipient>& recipient, void* cookie,
uint32_t flags,
wp<DeathRecipient>* outRecipient) {
diff --git a/services/camera/libcameraservice/aidl/AidlCameraServiceListener.h b/services/camera/libcameraservice/aidl/AidlCameraServiceListener.h
index 6483fe1..a7c32e3 100644
--- a/services/camera/libcameraservice/aidl/AidlCameraServiceListener.h
+++ b/services/camera/libcameraservice/aidl/AidlCameraServiceListener.h
@@ -45,25 +45,28 @@
~AidlCameraServiceListener() = default;
::android::binder::Status onStatusChanged(int32_t status,
- const std::string& cameraId) override;
+ const std::string& cameraId, int32_t deviceId) override;
::android::binder::Status onPhysicalCameraStatusChanged(int32_t status,
const std::string& cameraId,
- const std::string& physicalCameraId) override;
+ const std::string& physicalCameraId,
+ int32_t deviceId) override;
::android::binder::Status onTorchStatusChanged(
- int32_t status, const std::string& cameraId) override;
+ int32_t status, const std::string& cameraId, int32_t deviceId) override;
::android::binder::Status onTorchStrengthLevelChanged(
- const std::string& cameraId, int32_t newStrengthLevel) override;
+ const std::string& cameraId, int32_t newStrengthLevel, int32_t deviceId) override;
binder::Status onCameraAccessPrioritiesChanged() override {
// TODO: no implementation yet.
return binder::Status::ok();
}
- binder::Status onCameraOpened(const std::string& /*cameraId*/,
- const std::string& /*clientPackageId*/) override {
+ binder::Status onCameraOpened([[maybe_unused]] const std::string& /*cameraId*/,
+ [[maybe_unused]] const std::string& /*clientPackageId*/,
+ [[maybe_unused]] int32_t /*deviceId*/) override {
// empty implementation
return binder::Status::ok();
}
- binder::Status onCameraClosed(const std::string& /*cameraId*/) override {
+ binder::Status onCameraClosed([[maybe_unused]] const std::string& /*cameraId*/,
+ [[maybe_unused]] int32_t /*deviceId*/) override {
// empty implementation
return binder::Status::ok();
}
diff --git a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.cpp b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.cpp
index 2b81224..d28c7ab 100644
--- a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.cpp
+++ b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.cpp
@@ -16,6 +16,7 @@
#include <hidl/AidlCameraServiceListener.h>
#include <hidl/Utils.h>
+#include <camera/CameraUtils.h>
#include <camera/StringUtils.h>
namespace android {
@@ -29,7 +30,10 @@
typedef frameworks::cameraservice::service::V2_1::ICameraServiceListener HCameraServiceListener2_1;
binder::Status H2BCameraServiceListener::onStatusChanged(
- int32_t status, const std::string& cameraId) {
+ int32_t status, const std::string& cameraId, int32_t deviceId) {
+ if (deviceId != kDefaultDeviceId) {
+ return binder::Status::ok();
+ }
HCameraDeviceStatus hCameraDeviceStatus = convertToHidlCameraDeviceStatus(status);
CameraStatusAndId cameraStatusAndId;
cameraStatusAndId.deviceStatus = hCameraDeviceStatus;
@@ -44,7 +48,10 @@
binder::Status H2BCameraServiceListener::onPhysicalCameraStatusChanged(
int32_t status, const std::string& cameraId,
- const std::string& physicalCameraId) {
+ const std::string& physicalCameraId, int32_t deviceId) {
+ if (deviceId != kDefaultDeviceId) {
+ return binder::Status::ok();
+ }
auto cast2_1 = HCameraServiceListener2_1::castFrom(mBase);
sp<HCameraServiceListener2_1> interface2_1 = nullptr;
if (cast2_1.isOk()) {
@@ -66,13 +73,13 @@
}
::android::binder::Status H2BCameraServiceListener::onTorchStatusChanged(
- int32_t, const std::string&) {
+ [[maybe_unused]] int32_t, [[maybe_unused]] const std::string&, [[maybe_unused]] int32_t) {
// We don't implement onTorchStatusChanged
return binder::Status::ok();
}
::android::binder::Status H2BCameraServiceListener::onTorchStrengthLevelChanged(
- const std::string&, int32_t) {
+ [[maybe_unused]] const std::string&, [[maybe_unused]] int32_t, [[maybe_unused]] int32_t) {
return binder::Status::ok();
}
diff --git a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h
index 91a4c16..78fca4e 100644
--- a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h
+++ b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h
@@ -47,25 +47,28 @@
~H2BCameraServiceListener() { }
virtual ::android::binder::Status onStatusChanged(int32_t status,
- const std::string& cameraId) override;
+ const std::string& cameraId, int32_t deviceId) override;
virtual ::android::binder::Status onPhysicalCameraStatusChanged(int32_t status,
const std::string& cameraId,
- const std::string& physicalCameraId) override;
+ const std::string& physicalCameraId,
+ int32_t deviceId) override;
virtual ::android::binder::Status onTorchStatusChanged(
- int32_t status, const std::string& cameraId) override;
+ int32_t status, const std::string& cameraId, int32_t deviceId) override;
virtual ::android::binder::Status onTorchStrengthLevelChanged(
- const std::string& cameraId, int32_t newStrengthLevel) override;
+ const std::string& cameraId, int32_t newStrengthLevel, int32_t deviceId) override;
virtual binder::Status onCameraAccessPrioritiesChanged() {
// TODO: no implementation yet.
return binder::Status::ok();
}
- virtual binder::Status onCameraOpened(const std::string& /*cameraId*/,
- const std::string& /*clientPackageId*/) {
+ virtual binder::Status onCameraOpened([[maybe_unused]] const std::string& /*cameraId*/,
+ [[maybe_unused]] const std::string& /*clientPackageId*/,
+ [[maybe_unused]] int32_t /*deviceId*/) {
// empty implementation
return binder::Status::ok();
}
- virtual binder::Status onCameraClosed(const std::string& /*cameraId*/) {
+ virtual binder::Status onCameraClosed([[maybe_unused]] const std::string& /*cameraId*/,
+ [[maybe_unused]] int32_t /*deviceId*/) {
// empty implementation
return binder::Status::ok();
}
diff --git a/services/camera/libcameraservice/hidl/HidlCameraService.cpp b/services/camera/libcameraservice/hidl/HidlCameraService.cpp
index 1a5a6b9..8f25ad6 100644
--- a/services/camera/libcameraservice/hidl/HidlCameraService.cpp
+++ b/services/camera/libcameraservice/hidl/HidlCameraService.cpp
@@ -25,6 +25,7 @@
#include <hidl/HidlTransportSupport.h>
+#include <camera/CameraUtils.h>
#include <utils/Utils.h>
namespace android {
@@ -69,7 +70,7 @@
binder::Status serviceRet =
mAidlICameraService->getCameraCharacteristics(cameraId,
/*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/false,
- &cameraMetadata);
+ kDefaultDeviceId, 0, &cameraMetadata);
HCameraMetadata hidlMetadata;
if (!serviceRet.isOk()) {
switch(serviceRet.serviceSpecificErrorCode()) {
@@ -121,7 +122,7 @@
callbacks, cameraId, std::string(), {},
hardware::ICameraService::USE_CALLING_UID, 0/*oomScoreOffset*/,
/*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/false,
- /*out*/&deviceRemote);
+ kDefaultDeviceId, /*devicePolicy*/0, /*out*/&deviceRemote);
HStatus status = HStatus::NO_ERROR;
if (!serviceRet.isOk()) {
ALOGE("%s: Unable to connect to camera device", __FUNCTION__);
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp b/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp
index 854c342..778b428 100644
--- a/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp
@@ -27,6 +27,7 @@
#include <android/hardware/camera2/BnCameraDeviceCallbacks.h>
#include <android/hardware/ICameraServiceListener.h>
#include <android/hardware/camera2/ICameraDeviceUser.h>
+#include <camera/CameraUtils.h>
#include <camera/camera2/OutputConfiguration.h>
#include <gui/BufferItemConsumer.h>
#include <gui/IGraphicBufferProducer.h>
@@ -147,7 +148,7 @@
mAutoFocusMessage = true;
mAutoFocusCondition.broadcast();
}
-};
+}
void CameraFuzzer::dataCallback(int32_t msgType, const sp<IMemory> & /*data*/,
camera_frame_metadata_t *) {
@@ -169,7 +170,7 @@
default:
break;
}
-};
+}
status_t CameraFuzzer::waitForPreviewStart() {
status_t rc = NO_ERROR;
@@ -215,7 +216,7 @@
} else {
camType = kCamType[mFuzzedDataProvider->ConsumeBool()];
}
- mCameraService->getNumberOfCameras(camType, &mNumCameras);
+ mCameraService->getNumberOfCameras(camType, kDefaultDeviceId, /*devicePolicy*/0, &mNumCameras);
}
void CameraFuzzer::getCameraInformation(int32_t cameraId) {
@@ -235,11 +236,13 @@
mCameraService->getCameraVendorTagCache(&cache);
CameraInfo cameraInfo;
- mCameraService->getCameraInfo(cameraId, /*overrideToPortrait*/false, &cameraInfo);
+ mCameraService->getCameraInfo(cameraId, /*overrideToPortrait*/false, kDefaultDeviceId,
+ /*devicePolicy*/0, &cameraInfo);
CameraMetadata metadata;
mCameraService->getCameraCharacteristics(cameraIdStr,
- /*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/false, &metadata);
+ /*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/false,
+ kDefaultDeviceId, /*devicePolicy*/0, &metadata);
}
void CameraFuzzer::invokeCameraSound() {
@@ -321,12 +324,13 @@
std::string cameraIdStr = std::to_string(cameraId);
sp<IBinder> binder = new BBinder;
- mCameraService->setTorchMode(cameraIdStr, true, binder);
+ mCameraService->setTorchMode(cameraIdStr, true, binder, kDefaultDeviceId, /*devicePolicy*/0);
ALOGV("Turned torch on.");
int32_t torchStrength = rand() % 5 + 1;
ALOGV("Changing torch strength level to %d", torchStrength);
- mCameraService->turnOnTorchWithStrengthLevel(cameraIdStr, torchStrength, binder);
- mCameraService->setTorchMode(cameraIdStr, false, binder);
+ mCameraService->turnOnTorchWithStrengthLevel(cameraIdStr, torchStrength, binder,
+ kDefaultDeviceId, /*devicePolicy*/0);
+ mCameraService->setTorchMode(cameraIdStr, false, binder, kDefaultDeviceId, /*devicePolicy*/0);
ALOGV("Turned torch off.");
}
@@ -347,7 +351,7 @@
android::CameraService::USE_CALLING_PID,
/*targetSdkVersion*/ __ANDROID_API_FUTURE__,
/*overrideToPortrait*/true, /*forceSlowJpegMode*/false,
- &cameraDevice);
+ kDefaultDeviceId, /*devicePolicy*/0, &cameraDevice);
if (!rc.isOk()) {
// camera not connected
return;
@@ -484,20 +488,22 @@
public:
virtual ~TestCameraServiceListener() {};
- virtual binder::Status onStatusChanged(int32_t, const std::string&) {
+ virtual binder::Status onStatusChanged(int32_t /*status*/, const std::string& /*cameraId*/,
+ int32_t /*deviceId*/) {
return binder::Status::ok();
- };
+ }
virtual binder::Status onPhysicalCameraStatusChanged(int32_t /*status*/,
- const std::string& /*cameraId*/, const std::string& /*physicalCameraId*/) {
+ const std::string& /*cameraId*/, const std::string& /*physicalCameraId*/,
+ int32_t /*deviceId*/) {
// No op
return binder::Status::ok();
- };
+ }
virtual binder::Status onTorchStatusChanged(int32_t /*status*/,
- const std::string& /*cameraId*/) {
+ const std::string& /*cameraId*/, int32_t /*deviceId*/) {
return binder::Status::ok();
- };
+ }
virtual binder::Status onCameraAccessPrioritiesChanged() {
// No op
@@ -505,18 +511,18 @@
}
virtual binder::Status onCameraOpened(const std::string& /*cameraId*/,
- const std::string& /*clientPackageName*/) {
+ const std::string& /*clientPackageName*/, int32_t /*deviceId*/) {
// No op
return binder::Status::ok();
}
- virtual binder::Status onCameraClosed(const std::string& /*cameraId*/) {
+ virtual binder::Status onCameraClosed(const std::string& /*cameraId*/, int32_t /*deviceId*/) {
// No op
return binder::Status::ok();
}
virtual binder::Status onTorchStrengthLevelChanged(const std::string& /*cameraId*/,
- int32_t /*torchStrength*/) {
+ int32_t /*torchStrength*/, int32_t /*deviceId*/) {
// No op
return binder::Status::ok();
}
@@ -583,7 +589,7 @@
mCameraService->connectDevice(callbacks, s.cameraId, std::string(), {},
android::CameraService::USE_CALLING_UID, 0/*oomScoreDiff*/,
/*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/true,
- &device);
+ kDefaultDeviceId, /*devicePolicy*/0, &device);
if (device == nullptr) {
continue;
}
diff --git a/services/camera/libcameraservice/tests/CameraPermissionsTest.cpp b/services/camera/libcameraservice/tests/CameraPermissionsTest.cpp
index db43a02..30b4691 100644
--- a/services/camera/libcameraservice/tests/CameraPermissionsTest.cpp
+++ b/services/camera/libcameraservice/tests/CameraPermissionsTest.cpp
@@ -21,6 +21,8 @@
#include <private/android_filesystem_config.h>
+#include <camera/CameraUtils.h>
+
#include "../CameraService.h"
#include "../utils/CameraServiceProxyWrapper.h"
@@ -35,22 +37,23 @@
// Empty service listener.
class TestCameraServiceListener : public hardware::BnCameraServiceListener {
public:
- virtual ~TestCameraServiceListener() {};
+ virtual ~TestCameraServiceListener() {}
- virtual binder::Status onStatusChanged(int32_t , const std::string&) {
+ virtual binder::Status onStatusChanged(int32_t , const std::string&, int32_t) {
return binder::Status::ok();
- };
+ }
virtual binder::Status onPhysicalCameraStatusChanged(int32_t /*status*/,
- const std::string& /*cameraId*/, const std::string& /*physicalCameraId*/) {
+ const std::string& /*cameraId*/, const std::string& /*physicalCameraId*/,
+ int32_t /*deviceId*/) {
// No op
return binder::Status::ok();
- };
+ }
virtual binder::Status onTorchStatusChanged(int32_t /*status*/,
- const std::string& /*cameraId*/) {
+ const std::string& /*cameraId*/, int32_t /*deviceId*/) {
return binder::Status::ok();
- };
+ }
virtual binder::Status onCameraAccessPrioritiesChanged() {
// No op
@@ -58,18 +61,18 @@
}
virtual binder::Status onCameraOpened(const std::string& /*cameraId*/,
- const std::string& /*clientPackageName*/) {
+ const std::string& /*clientPackageName*/, int32_t /*deviceId*/) {
// No op
return binder::Status::ok();
}
- virtual binder::Status onCameraClosed(const std::string& /*cameraId*/) {
+ virtual binder::Status onCameraClosed(const std::string& /*cameraId*/, int32_t /*deviceId*/) {
// No op
return binder::Status::ok();
}
virtual binder::Status onTorchStrengthLevelChanged(const std::string& /*cameraId*/,
- int32_t /*torchStrength*/) {
+ int32_t /*torchStrength*/, int32_t /*deviceId*/) {
// No op
return binder::Status::ok();
}
@@ -227,7 +230,8 @@
binder::Status status =
sCameraService->connectDevice(callbacks, s.cameraId, std::string(), {},
android::CameraService::USE_CALLING_UID, 0/*oomScoreDiff*/,
- /*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/false, &device);
+ /*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/false,
+ kDefaultDeviceId, /*devicePolicy*/0, &device);
AutoDisconnectDevice autoDisconnect(device);
ASSERT_TRUE(!status.isOk()) << "connectDevice returned OK status";
ASSERT_EQ(status.serviceSpecificErrorCode(), hardware::ICameraService::ERROR_DISABLED)
@@ -241,7 +245,8 @@
binder::Status status =
sCameraService->connectDevice(callbacks, s.cameraId, std::string(), {},
android::CameraService::USE_CALLING_UID, 0/*oomScoreDiff*/,
- /*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/false, &device);
+ /*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/false,
+ kDefaultDeviceId, /*devicePolicy*/0, &device);
AutoDisconnectDevice autoDisconnect(device);
ASSERT_TRUE(status.isOk());
}
@@ -260,14 +265,16 @@
binder::Status status =
sCameraService->connectDevice(callbacks, s.cameraId, std::string(), {},
android::CameraService::USE_CALLING_UID, 0/*oomScoreDiff*/,
- /*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/false, &deviceA);
+ /*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/false,
+ kDefaultDeviceId, /*devicePolicy*/0, &deviceA);
AutoDisconnectDevice autoDisconnectA(deviceA);
ASSERT_TRUE(status.isOk()) << "Exception code " << status.exceptionCode() <<
" service specific error code " << status.serviceSpecificErrorCode();
status =
sCameraService->connectDevice(callbacks, s.cameraId, std::string(), {},
android::CameraService::USE_CALLING_UID, 0/*oomScoreDiff*/,
- /*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/false, &deviceB);
+ /*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/false,
+ kDefaultDeviceId, /*devicePolicy*/0, &deviceB);
AutoDisconnectDevice autoDisconnectB(deviceB);
ASSERT_TRUE(status.isOk()) << "Exception code " << status.exceptionCode() <<
" service specific error code " << status.serviceSpecificErrorCode();
@@ -288,14 +295,16 @@
binder::Status status =
sCameraService->connectDevice(callbacks, s.cameraId, std::string(), {},
android::CameraService::USE_CALLING_UID, 0/*oomScoreDiff*/,
- /*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/false, &deviceA);
+ /*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/false,
+ kDefaultDeviceId, /*devicePolicy*/0, &deviceA);
AutoDisconnectDevice autoDisconnectA(deviceA);
ASSERT_TRUE(status.isOk()) << "Exception code " << status.exceptionCode() <<
" service specific error code " << status.serviceSpecificErrorCode();
status =
sCameraService->connectDevice(callbacks, s.cameraId, std::string(), {},
android::CameraService::USE_CALLING_UID, 1/*oomScoreDiff*/,
- /*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/false, &deviceB);
+ /*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/false,
+ kDefaultDeviceId, /*devicePolicy*/0, &deviceB);
AutoDisconnectDevice autoDisconnectB(deviceB);
ASSERT_TRUE(status.isOk()) << "Exception code " << status.exceptionCode() <<
" service specific error code " << status.serviceSpecificErrorCode();
diff --git a/services/camera/libcameraservice/utils/VirtualDeviceCameraIdMapper.cpp b/services/camera/libcameraservice/utils/VirtualDeviceCameraIdMapper.cpp
new file mode 100644
index 0000000..5a27087
--- /dev/null
+++ b/services/camera/libcameraservice/utils/VirtualDeviceCameraIdMapper.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "VirtualDeviceCameraIdMapper"
+
+#include <android_companion_virtualdevice_flags.h>
+#include <camera/CameraUtils.h>
+
+#include "VirtualDeviceCameraIdMapper.h"
+
+namespace android {
+
+namespace vd_flags = android::companion::virtualdevice::flags;
+
+void VirtualDeviceCameraIdMapper::addCamera(const std::string& cameraId,
+ int32_t deviceId, const std::string& mappedCameraId) {
+ if (!vd_flags::camera_device_awareness()) {
+ ALOGD("%s: Device-aware camera feature is not enabled", __func__);
+ return;
+ }
+
+ if (deviceId == kDefaultDeviceId) {
+ ALOGD("%s: Not adding entry for a camera of the default device", __func__);
+ return;
+ }
+
+ ALOGD("%s: Adding camera %s for device %d with mapped id %s", __func__, cameraId.c_str(),
+ deviceId, mappedCameraId.c_str());
+
+ std::scoped_lock lock(mLock);
+ mDeviceIdMappedCameraIdPairToCameraIdMap[{deviceId, mappedCameraId}] = cameraId;
+}
+
+void VirtualDeviceCameraIdMapper::removeCamera(const std::string& cameraId) {
+ if (!vd_flags::camera_device_awareness()) {
+ ALOGD("%s: Device-aware camera feature is not enabled", __func__);
+ return;
+ }
+
+ std::scoped_lock lock(mLock);
+ for (auto it = mDeviceIdMappedCameraIdPairToCameraIdMap.begin();
+ it != mDeviceIdMappedCameraIdPairToCameraIdMap.end(); ++it) {
+ if (it->first.second == cameraId) {
+ mDeviceIdMappedCameraIdPairToCameraIdMap.erase(it);
+ return;
+ }
+ }
+}
+
+std::optional<std::string> VirtualDeviceCameraIdMapper::getActualCameraId(
+ int32_t deviceId, const std::string& mappedCameraId) const {
+ if (deviceId == kDefaultDeviceId) {
+ ALOGD("%s: Returning the camera id as the mapped camera id for camera %s, as it "
+ "belongs to the default device", __func__, mappedCameraId.c_str());
+ return mappedCameraId;
+ }
+
+ if (!vd_flags::camera_device_awareness()) {
+ ALOGD("%s: Device-aware camera feature is not enabled, returning the camera id as "
+ "the mapped camera id for camera %s", __func__, mappedCameraId.c_str());
+ return mappedCameraId;
+ }
+
+ std::scoped_lock lock(mLock);
+ auto iterator = mDeviceIdMappedCameraIdPairToCameraIdMap.find(
+ {deviceId, mappedCameraId});
+ if (iterator == mDeviceIdMappedCameraIdPairToCameraIdMap.end()) {
+ ALOGW("%s: No entry found for device id %d and mapped camera id %s", __func__,
+ deviceId, mappedCameraId.c_str());
+ return std::nullopt;
+ }
+ return iterator->second;
+}
+
+std::pair<int32_t, std::string> VirtualDeviceCameraIdMapper::getDeviceIdAndMappedCameraIdPair(
+ const std::string& cameraId) const {
+ if (!vd_flags::camera_device_awareness()) {
+ ALOGD("%s: Device-aware camera feature is not enabled", __func__);
+ return std::make_pair(kDefaultDeviceId, cameraId);
+ }
+
+ std::scoped_lock lock(mLock);
+ for (const auto& [deviceIdMappedCameraIdPair, actualCameraId]
+ : mDeviceIdMappedCameraIdPairToCameraIdMap) {
+ if (actualCameraId == cameraId) {
+ return deviceIdMappedCameraIdPair;
+ }
+ }
+ ALOGD("%s: No device id and mapped camera id found for camera id %s, so it must belong "
+ "to the default device", __func__, cameraId.c_str());
+ return std::make_pair(kDefaultDeviceId, cameraId);
+}
+
+int VirtualDeviceCameraIdMapper::getNumberOfCameras(int32_t deviceId) const {
+ if (!vd_flags::camera_device_awareness()) {
+ return 0;
+ }
+
+ int numOfCameras = 0;
+ std::scoped_lock lock(mLock);
+ for (const auto& [deviceIdMappedCameraIdPair, _]
+ : mDeviceIdMappedCameraIdPairToCameraIdMap) {
+ if (deviceIdMappedCameraIdPair.first == deviceId) {
+ numOfCameras++;
+ }
+ }
+ return numOfCameras;
+}
+
+std::optional<std::string> VirtualDeviceCameraIdMapper::getActualCameraId(
+ int api1CameraId, int32_t deviceId) const {
+ if (!vd_flags::camera_device_awareness()) {
+ ALOGD("%s: Device-aware camera feature is not enabled", __func__);
+ return std::nullopt;
+ }
+
+ int matchingCameraIndex = 0;
+ std::scoped_lock lock(mLock);
+ for (const auto& [deviceIdMappedCameraIdPair, actualCameraId]
+ : mDeviceIdMappedCameraIdPairToCameraIdMap) {
+ if (deviceIdMappedCameraIdPair.first == deviceId) {
+ if (matchingCameraIndex == api1CameraId) {
+ return actualCameraId;
+ }
+ matchingCameraIndex++;
+ }
+ }
+ ALOGW("%s: No entry found for device id %d and API 1 camera id %d", __func__,
+ deviceId, api1CameraId);
+ return std::nullopt;
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/services/camera/libcameraservice/utils/VirtualDeviceCameraIdMapper.h b/services/camera/libcameraservice/utils/VirtualDeviceCameraIdMapper.h
new file mode 100644
index 0000000..96c0cb4
--- /dev/null
+++ b/services/camera/libcameraservice/utils/VirtualDeviceCameraIdMapper.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SERVERS_CAMERA_VIRTUAL_DEVICE_CAMERA_ID_MAPPER_H
+#define ANDROID_SERVERS_CAMERA_VIRTUAL_DEVICE_CAMERA_ID_MAPPER_H
+
+#include <string>
+#include <map>
+#include <mutex>
+
+#include <utils/Mutex.h>
+
+namespace android {
+
+class VirtualDeviceCameraIdMapper {
+public:
+ VirtualDeviceCameraIdMapper() {}
+
+ virtual ~VirtualDeviceCameraIdMapper() {}
+
+ void addCamera(const std::string& cameraId, int32_t deviceId,
+ const std::string& mappedCameraId) EXCLUDES(mLock);
+
+ void removeCamera(const std::string& cameraId) EXCLUDES(mLock);
+
+ /**
+ * Return the actual camera id for a given device id (i.e., the id of the device owning
+ * the camera, for a virtual camera this would be the id of the virtual device, and for
+ * any other cameras this would be default device id, i.e., 0) and mapped camera
+ * id (for virtual devices, the back and front virtual cameras of that device would have
+ * 0 and 1 respectively as their mapped camera id, and for any other cameras this
+ * would be their actual camera id). When the camera device awareness flag is disabled,
+ * this will return the given camera id itself.
+ */
+ std::optional<std::string> getActualCameraId(int32_t deviceId,
+ const std::string& mappedCameraId) const EXCLUDES(mLock);
+
+ /**
+ * Return the device id (i.e., the id of the device owning the camera, for a virtual
+ * camera this would be the id of the virtual device, and for any other cameras this
+ * would be default device id, i.e., 0) and the mapped camera id (for virtual
+ * devices, the back and front virtual cameras of that device would have 0 and 1
+ * respectively as their mapped camera id, and for any other cameras this would
+ * be their actual camera id) for a given camera id. When the camera device awareness flag is
+ * disabled, this will return a pair of kDefaultDeviceId and the given cameraId.
+ */
+ std::pair<int32_t, std::string> getDeviceIdAndMappedCameraIdPair(
+ const std::string& cameraId) const EXCLUDES(mLock);
+
+ /**
+ * Return the number of virtual cameras corresponding to the legacy camera API
+ * getNumberOfCameras. When the camera device awareness flag is disabled, this will return 0.
+ */
+ int getNumberOfCameras(int32_t deviceId) const EXCLUDES(mLock);
+
+ /**
+ * Return the actual camera id corresponding to the virtual camera with the given API 1 camera
+ * id. When the camera device awareness flag is disabled, this will return std::nullopt.
+ */
+ std::optional<std::string> getActualCameraId(int api1CameraId, int32_t deviceId)
+ const EXCLUDES(mLock);
+
+private:
+ mutable std::mutex mLock;
+
+ // Map of (deviceId, app-visible cameraId) -> HAL-visible cameraId
+ std::map<std::pair<int32_t, std::string>, std::string>
+ mDeviceIdMappedCameraIdPairToCameraIdMap GUARDED_BY(mLock);
+};
+
+} // namespace android
+
+#endif // ANDROID_SERVERS_CAMERA_VIRTUAL_DEVICE_CAMERA_ID_MAPPER_H
diff --git a/services/camera/virtualcamera/VirtualCameraDevice.cc b/services/camera/virtualcamera/VirtualCameraDevice.cc
index a5301e5..852ae2a 100644
--- a/services/camera/virtualcamera/VirtualCameraDevice.cc
+++ b/services/camera/virtualcamera/VirtualCameraDevice.cc
@@ -214,7 +214,8 @@
// TODO(b/301023410) - Populate camera characteristics according to camera configuration.
std::optional<CameraMetadata> initCameraCharacteristics(
const std::vector<SupportedStreamConfiguration>& supportedInputConfig,
- const SensorOrientation sensorOrientation, const LensFacing lensFacing) {
+ const SensorOrientation sensorOrientation, const LensFacing lensFacing,
+ const int32_t deviceId) {
if (!std::all_of(supportedInputConfig.begin(), supportedInputConfig.end(),
[](const SupportedStreamConfiguration& config) {
return isFormatSupportedForInput(
@@ -229,6 +230,7 @@
MetadataBuilder()
.setSupportedHardwareLevel(
ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL)
+ .setDeviceId(deviceId)
.setFlashAvailable(false)
.setLensFacing(
static_cast<camera_metadata_enum_android_lens_facing>(lensFacing))
@@ -389,13 +391,14 @@
} // namespace
VirtualCameraDevice::VirtualCameraDevice(
- const uint32_t cameraId, const VirtualCameraConfiguration& configuration)
+ const uint32_t cameraId, const VirtualCameraConfiguration& configuration,
+ int32_t deviceId)
: mCameraId(cameraId),
mVirtualCameraClientCallback(configuration.virtualCameraCallback),
mSupportedInputConfigurations(configuration.supportedStreamConfigs) {
std::optional<CameraMetadata> metadata = initCameraCharacteristics(
mSupportedInputConfigurations, configuration.sensorOrientation,
- configuration.lensFacing);
+ configuration.lensFacing, deviceId);
if (metadata.has_value()) {
mCameraCharacteristics = *metadata;
} else {
diff --git a/services/camera/virtualcamera/VirtualCameraDevice.h b/services/camera/virtualcamera/VirtualCameraDevice.h
index 0aebf6e..cba0674 100644
--- a/services/camera/virtualcamera/VirtualCameraDevice.h
+++ b/services/camera/virtualcamera/VirtualCameraDevice.h
@@ -39,7 +39,8 @@
explicit VirtualCameraDevice(
uint32_t cameraId,
const aidl::android::companion::virtualcamera::VirtualCameraConfiguration&
- configuration);
+ configuration,
+ int32_t deviceId);
virtual ~VirtualCameraDevice() override = default;
diff --git a/services/camera/virtualcamera/VirtualCameraProvider.cc b/services/camera/virtualcamera/VirtualCameraProvider.cc
index eed3e85..67eaec0 100644
--- a/services/camera/virtualcamera/VirtualCameraProvider.cc
+++ b/services/camera/virtualcamera/VirtualCameraProvider.cc
@@ -150,15 +150,16 @@
}
std::shared_ptr<VirtualCameraDevice> VirtualCameraProvider::createCamera(
- const VirtualCameraConfiguration& configuration, const int cameraId) {
+ const VirtualCameraConfiguration& configuration, const int cameraId,
+ const int32_t deviceId) {
if (cameraId < 0) {
ALOGE("%s: Cannot create camera with negative id. cameraId: %d", __func__,
cameraId);
return nullptr;
}
- auto camera =
- ndk::SharedRefBase::make<VirtualCameraDevice>(cameraId, configuration);
+ auto camera = ndk::SharedRefBase::make<VirtualCameraDevice>(
+ cameraId, configuration, deviceId);
std::shared_ptr<ICameraProviderCallback> callback;
{
const std::lock_guard<std::mutex> lock(mLock);
diff --git a/services/camera/virtualcamera/VirtualCameraProvider.h b/services/camera/virtualcamera/VirtualCameraProvider.h
index c1283a0..c536547 100644
--- a/services/camera/virtualcamera/VirtualCameraProvider.h
+++ b/services/camera/virtualcamera/VirtualCameraProvider.h
@@ -77,7 +77,7 @@
std::shared_ptr<VirtualCameraDevice> createCamera(
const aidl::android::companion::virtualcamera::VirtualCameraConfiguration&
configuration,
- int cameraId);
+ int cameraId, int32_t deviceId);
std::shared_ptr<VirtualCameraDevice> getCamera(const std::string& name);
diff --git a/services/camera/virtualcamera/VirtualCameraService.cc b/services/camera/virtualcamera/VirtualCameraService.cc
index 27873e7..5e3a6d9 100644
--- a/services/camera/virtualcamera/VirtualCameraService.cc
+++ b/services/camera/virtualcamera/VirtualCameraService.cc
@@ -62,6 +62,7 @@
constexpr int kVgaWidth = 640;
constexpr int kVgaHeight = 480;
constexpr int kMaxFps = 60;
+constexpr int kDefaultDeviceId = 0;
constexpr char kEnableTestCameraCmd[] = "enable_test_camera";
constexpr char kDisableTestCameraCmd[] = "disable_test_camera";
constexpr char kHelp[] = "help";
@@ -186,14 +187,15 @@
ndk::ScopedAStatus VirtualCameraService::registerCamera(
const ::ndk::SpAIBinder& token,
- const VirtualCameraConfiguration& configuration, bool* _aidl_return) {
- return registerCamera(token, configuration, sNextId++, _aidl_return);
+ const VirtualCameraConfiguration& configuration, const int32_t deviceId,
+ bool* _aidl_return) {
+ return registerCamera(token, configuration, sNextId++, deviceId, _aidl_return);
}
ndk::ScopedAStatus VirtualCameraService::registerCamera(
const ::ndk::SpAIBinder& token,
const VirtualCameraConfiguration& configuration, const int cameraId,
- bool* _aidl_return) {
+ const int32_t deviceId, bool* _aidl_return) {
if (!mPermissionProxy.checkCallingPermission(kCreateVirtualDevicePermission)) {
ALOGE("%s: caller (pid %d, uid %d) doesn't hold %s permission", __func__,
getpid(), getuid(), kCreateVirtualDevicePermission);
@@ -225,7 +227,7 @@
}
std::shared_ptr<VirtualCameraDevice> camera =
- mVirtualCameraProvider->createCamera(configuration, cameraId);
+ mVirtualCameraProvider->createCamera(configuration, cameraId, deviceId);
if (camera == nullptr) {
ALOGE("Failed to create camera for binder token 0x%" PRIxPTR,
reinterpret_cast<uintptr_t>(token.get()));
@@ -389,7 +391,7 @@
.maxFps = kMaxFps});
configuration.lensFacing = lensFacing.value_or(LensFacing::EXTERNAL);
registerCamera(mTestCameraToken, configuration, cameraId.value_or(sNextId++),
- &ret);
+ kDefaultDeviceId, &ret);
if (ret) {
dprintf(out, "Successfully registered test camera %s\n",
getCamera(mTestCameraToken)->getCameraName().c_str());
diff --git a/services/camera/virtualcamera/VirtualCameraService.h b/services/camera/virtualcamera/VirtualCameraService.h
index 0b80514..63a8c9d 100644
--- a/services/camera/virtualcamera/VirtualCameraService.h
+++ b/services/camera/virtualcamera/VirtualCameraService.h
@@ -43,14 +43,14 @@
const ::ndk::SpAIBinder& token,
const ::aidl::android::companion::virtualcamera::VirtualCameraConfiguration&
configuration,
- bool* _aidl_return) override EXCLUDES(mLock);
+ int32_t deviceId, bool* _aidl_return) override EXCLUDES(mLock);
// Register camera corresponding to the binder token.
ndk::ScopedAStatus registerCamera(
const ::ndk::SpAIBinder& token,
const ::aidl::android::companion::virtualcamera::VirtualCameraConfiguration&
configuration,
- int cameraId, bool* _aidl_return) EXCLUDES(mLock);
+ int cameraId, int32_t deviceId, bool* _aidl_return) EXCLUDES(mLock);
// Unregisters camera corresponding to the binder token.
ndk::ScopedAStatus unregisterCamera(const ::ndk::SpAIBinder& token) override
diff --git a/services/camera/virtualcamera/aidl/android/companion/virtualcamera/IVirtualCameraService.aidl b/services/camera/virtualcamera/aidl/android/companion/virtualcamera/IVirtualCameraService.aidl
index bb74f5c..1bd99be 100644
--- a/services/camera/virtualcamera/aidl/android/companion/virtualcamera/IVirtualCameraService.aidl
+++ b/services/camera/virtualcamera/aidl/android/companion/virtualcamera/IVirtualCameraService.aidl
@@ -28,7 +28,8 @@
* Registers a new camera with the virtual camera hal.
* @return true if the camera was successfully registered
*/
- boolean registerCamera(in IBinder token, in VirtualCameraConfiguration configuration);
+ boolean registerCamera(in IBinder token, in VirtualCameraConfiguration configuration,
+ int deviceId);
/**
* Unregisters the camera from the virtual camera hal. After this call the virtual camera won't
diff --git a/services/camera/virtualcamera/tests/VirtualCameraDeviceTest.cc b/services/camera/virtualcamera/tests/VirtualCameraDeviceTest.cc
index ad9d83b..5c9b3b9 100644
--- a/services/camera/virtualcamera/tests/VirtualCameraDeviceTest.cc
+++ b/services/camera/virtualcamera/tests/VirtualCameraDeviceTest.cc
@@ -64,6 +64,7 @@
constexpr int kHdWidth = 1280;
constexpr int kHdHeight = 720;
constexpr int kMaxFps = 30;
+constexpr int kDefaultDeviceId = 0;
const Stream kVgaYUV420Stream = Stream{
.streamType = StreamType::OUTPUT,
@@ -137,8 +138,8 @@
cameraCharacteristicsForInputFormat) {
const VirtualCameraConfigTestParam& param = GetParam();
std::shared_ptr<VirtualCameraDevice> camera =
- ndk::SharedRefBase::make<VirtualCameraDevice>(kCameraId,
- param.inputConfig);
+ ndk::SharedRefBase::make<VirtualCameraDevice>(
+ kCameraId, param.inputConfig, kDefaultDeviceId);
CameraMetadata metadata;
ASSERT_TRUE(camera->getCameraCharacteristics(&metadata).isOk());
@@ -293,15 +294,17 @@
public:
void SetUp() override {
mCamera = ndk::SharedRefBase::make<VirtualCameraDevice>(
- kCameraId, VirtualCameraConfiguration{
- .supportedStreamConfigs = {SupportedStreamConfiguration{
- .width = kVgaWidth,
- .height = kVgaHeight,
- .pixelFormat = Format::YUV_420_888,
- .maxFps = kMaxFps}},
- .virtualCameraCallback = nullptr,
- .sensorOrientation = SensorOrientation::ORIENTATION_0,
- .lensFacing = LensFacing::FRONT});
+ kCameraId,
+ VirtualCameraConfiguration{
+ .supportedStreamConfigs = {SupportedStreamConfiguration{
+ .width = kVgaWidth,
+ .height = kVgaHeight,
+ .pixelFormat = Format::YUV_420_888,
+ .maxFps = kMaxFps}},
+ .virtualCameraCallback = nullptr,
+ .sensorOrientation = SensorOrientation::ORIENTATION_0,
+ .lensFacing = LensFacing::FRONT},
+ kDefaultDeviceId);
}
protected:
diff --git a/services/camera/virtualcamera/tests/VirtualCameraProviderTest.cc b/services/camera/virtualcamera/tests/VirtualCameraProviderTest.cc
index cd64ca5..f1b2a92 100644
--- a/services/camera/virtualcamera/tests/VirtualCameraProviderTest.cc
+++ b/services/camera/virtualcamera/tests/VirtualCameraProviderTest.cc
@@ -54,6 +54,7 @@
constexpr int kVgaHeight = 480;
constexpr int kMaxFps = 30;
constexpr int kCameraId = 9999;
+constexpr int kDefaultDeviceId = 0;
constexpr char kVirtualCameraNameRegex[] =
"device@[0-9]+\\.[0-9]+/virtual/[0-9]+";
@@ -119,7 +120,7 @@
ASSERT_TRUE(mCameraProvider->setCallback(mMockCameraProviderCallback).isOk());
std::shared_ptr<VirtualCameraDevice> camera =
- mCameraProvider->createCamera(mInputConfig, kCameraId);
+ mCameraProvider->createCamera(mInputConfig, kCameraId, kDefaultDeviceId);
EXPECT_THAT(camera, Not(IsNull()));
EXPECT_THAT(camera->getCameraName(), MatchesRegex(kVirtualCameraNameRegex));
@@ -137,7 +138,7 @@
.WillOnce(Return(ndk::ScopedAStatus::ok()));
std::shared_ptr<VirtualCameraDevice> camera =
- mCameraProvider->createCamera(mInputConfig, kCameraId);
+ mCameraProvider->createCamera(mInputConfig, kCameraId, kDefaultDeviceId);
ASSERT_TRUE(mCameraProvider->setCallback(mMockCameraProviderCallback).isOk());
// Created camera should be in the list of cameras.
@@ -149,7 +150,7 @@
TEST_F(VirtualCameraProviderTest, RemoveCamera) {
ASSERT_TRUE(mCameraProvider->setCallback(mMockCameraProviderCallback).isOk());
std::shared_ptr<VirtualCameraDevice> camera =
- mCameraProvider->createCamera(mInputConfig, kCameraId);
+ mCameraProvider->createCamera(mInputConfig, kCameraId, kDefaultDeviceId);
EXPECT_CALL(*mMockCameraProviderCallback,
cameraDeviceStatusChange(Eq(camera->getCameraName()),
@@ -166,7 +167,7 @@
TEST_F(VirtualCameraProviderTest, RemoveNonExistingCamera) {
ASSERT_TRUE(mCameraProvider->setCallback(mMockCameraProviderCallback).isOk());
std::shared_ptr<VirtualCameraDevice> camera =
- mCameraProvider->createCamera(mInputConfig, kCameraId);
+ mCameraProvider->createCamera(mInputConfig, kCameraId, kDefaultDeviceId);
// Removing non-existing camera should fail.
const std::string cameraName = "DefinitelyNoTCamera";
diff --git a/services/camera/virtualcamera/tests/VirtualCameraServiceTest.cc b/services/camera/virtualcamera/tests/VirtualCameraServiceTest.cc
index 16f40ff..01f2b8c 100644
--- a/services/camera/virtualcamera/tests/VirtualCameraServiceTest.cc
+++ b/services/camera/virtualcamera/tests/VirtualCameraServiceTest.cc
@@ -69,6 +69,7 @@
constexpr SensorOrientation kSensorOrientation =
SensorOrientation::ORIENTATION_0;
constexpr LensFacing kLensFacing = LensFacing::FRONT;
+constexpr int kDefaultDeviceId = 0;
constexpr char kCreateVirtualDevicePermissions[] =
"android.permission.CREATE_VIRTUAL_DEVICE";
@@ -131,8 +132,8 @@
bool aidlRet;
ASSERT_TRUE(mCameraService
- ->registerCamera(mNdkOwnerToken,
- mVgaYUV420OnlyConfiguration, &aidlRet)
+ ->registerCamera(mNdkOwnerToken, mVgaYUV420OnlyConfiguration,
+ kDefaultDeviceId, &aidlRet)
.isOk());
ASSERT_TRUE(aidlRet);
}
@@ -196,10 +197,10 @@
ndk::SpAIBinder ndkToken(AIBinder_fromPlatformBinder(token));
bool aidlRet;
- ASSERT_TRUE(
- mCameraService
- ->registerCamera(ndkToken, mVgaYUV420OnlyConfiguration, &aidlRet)
- .isOk());
+ ASSERT_TRUE(mCameraService
+ ->registerCamera(ndkToken, mVgaYUV420OnlyConfiguration,
+ kDefaultDeviceId, &aidlRet)
+ .isOk());
EXPECT_TRUE(aidlRet);
EXPECT_THAT(getCameraIds(), SizeIs(1));
@@ -213,7 +214,9 @@
VirtualCameraConfiguration config =
createConfiguration(kVgaWidth, kVgaHeight, Format::RGBA_8888, kMaxFps);
- ASSERT_TRUE(mCameraService->registerCamera(ndkToken, config, &aidlRet).isOk());
+ ASSERT_TRUE(mCameraService
+ ->registerCamera(ndkToken, config, kDefaultDeviceId, &aidlRet)
+ .isOk());
EXPECT_TRUE(aidlRet);
EXPECT_THAT(getCameraIds(), SizeIs(1));
@@ -225,7 +228,7 @@
ASSERT_TRUE(mCameraService
->registerCamera(mNdkOwnerToken, mVgaYUV420OnlyConfiguration,
- &aidlRet)
+ kDefaultDeviceId, &aidlRet)
.isOk());
EXPECT_FALSE(aidlRet);
EXPECT_THAT(getCameraIds(), SizeIs(1));
@@ -236,7 +239,8 @@
ASSERT_FALSE(mCameraService
->registerCamera(mNdkOwnerToken,
- kEmptyVirtualCameraConfiguration, &aidlRet)
+ kEmptyVirtualCameraConfiguration,
+ kDefaultDeviceId, &aidlRet)
.isOk());
EXPECT_FALSE(aidlRet);
EXPECT_THAT(getCameraIds(), IsEmpty());
@@ -249,7 +253,9 @@
createConfiguration(kVgaWidth, kVgaHeight, Format::UNKNOWN, kMaxFps);
ASSERT_FALSE(
- mCameraService->registerCamera(mNdkOwnerToken, config, &aidlRet).isOk());
+ mCameraService
+ ->registerCamera(mNdkOwnerToken, config, kDefaultDeviceId, &aidlRet)
+ .isOk());
EXPECT_FALSE(aidlRet);
EXPECT_THAT(getCameraIds(), IsEmpty());
}
@@ -260,7 +266,9 @@
createConfiguration(1000000, 1000000, Format::YUV_420_888, kMaxFps);
ASSERT_FALSE(
- mCameraService->registerCamera(mNdkOwnerToken, config, &aidlRet).isOk());
+ mCameraService
+ ->registerCamera(mNdkOwnerToken, config, kDefaultDeviceId, &aidlRet)
+ .isOk());
EXPECT_FALSE(aidlRet);
EXPECT_THAT(getCameraIds(), IsEmpty());
}
@@ -271,7 +279,9 @@
createConfiguration(-1, kVgaHeight, Format::YUV_420_888, kMaxFps);
ASSERT_FALSE(
- mCameraService->registerCamera(mNdkOwnerToken, config, &aidlRet).isOk());
+ mCameraService
+ ->registerCamera(mNdkOwnerToken, config, kDefaultDeviceId, &aidlRet)
+ .isOk());
EXPECT_FALSE(aidlRet);
EXPECT_THAT(getCameraIds(), IsEmpty());
}
@@ -282,7 +292,9 @@
createConfiguration(kVgaWidth, kVgaHeight, Format::YUV_420_888, 0);
ASSERT_FALSE(
- mCameraService->registerCamera(mNdkOwnerToken, config, &aidlRet).isOk());
+ mCameraService
+ ->registerCamera(mNdkOwnerToken, config, kDefaultDeviceId, &aidlRet)
+ .isOk());
EXPECT_FALSE(aidlRet);
EXPECT_THAT(getCameraIds(), IsEmpty());
}
@@ -293,7 +305,9 @@
createConfiguration(kVgaWidth, kVgaHeight, Format::YUV_420_888, 90);
ASSERT_FALSE(
- mCameraService->registerCamera(mNdkOwnerToken, config, &aidlRet).isOk());
+ mCameraService
+ ->registerCamera(mNdkOwnerToken, config, kDefaultDeviceId, &aidlRet)
+ .isOk());
EXPECT_FALSE(aidlRet);
EXPECT_THAT(getCameraIds(), IsEmpty());
}
@@ -327,7 +341,7 @@
EXPECT_THAT(mCameraService
->registerCamera(mNdkOwnerToken, mVgaYUV420OnlyConfiguration,
- &aidlRet)
+ kDefaultDeviceId, &aidlRet)
.getExceptionCode(),
Eq(EX_SECURITY));
}
diff --git a/services/camera/virtualcamera/tests/VirtualCameraSessionTest.cc b/services/camera/virtualcamera/tests/VirtualCameraSessionTest.cc
index 5f313a0..671e031 100644
--- a/services/camera/virtualcamera/tests/VirtualCameraSessionTest.cc
+++ b/services/camera/virtualcamera/tests/VirtualCameraSessionTest.cc
@@ -47,6 +47,7 @@
constexpr int kStreamId = 0;
constexpr int kSecondStreamId = 1;
constexpr int kCameraId = 42;
+constexpr int kDefaultDeviceId = 0;
using ::aidl::android::companion::virtualcamera::BnVirtualCameraCallback;
using ::aidl::android::companion::virtualcamera::Format;
@@ -160,7 +161,8 @@
.maxFps = kMaxFps}},
.virtualCameraCallback = mMockVirtualCameraClientCallback,
.sensorOrientation = SensorOrientation::ORIENTATION_0,
- .lensFacing = LensFacing::FRONT});
+ .lensFacing = LensFacing::FRONT},
+ kDefaultDeviceId);
mVirtualCameraSession = ndk::SharedRefBase::make<VirtualCameraSession>(
mVirtualCameraDevice, mMockCameraDeviceCallback,
mMockVirtualCameraClientCallback);
@@ -305,11 +307,13 @@
std::shared_ptr<VirtualCameraSession> createSession(
const std::vector<SupportedStreamConfiguration>& supportedInputConfigs) {
mVirtualCameraDevice = ndk::SharedRefBase::make<VirtualCameraDevice>(
- kCameraId, VirtualCameraConfiguration{
- .supportedStreamConfigs = supportedInputConfigs,
- .virtualCameraCallback = mMockVirtualCameraClientCallback,
- .sensorOrientation = SensorOrientation::ORIENTATION_0,
- .lensFacing = LensFacing::FRONT});
+ kCameraId,
+ VirtualCameraConfiguration{
+ .supportedStreamConfigs = supportedInputConfigs,
+ .virtualCameraCallback = mMockVirtualCameraClientCallback,
+ .sensorOrientation = SensorOrientation::ORIENTATION_0,
+ .lensFacing = LensFacing::FRONT},
+ kDefaultDeviceId);
return ndk::SharedRefBase::make<VirtualCameraSession>(
mVirtualCameraDevice, mMockCameraDeviceCallback,
mMockVirtualCameraClientCallback);
diff --git a/services/camera/virtualcamera/util/MetadataUtil.cc b/services/camera/virtualcamera/util/MetadataUtil.cc
index 822862b..4eeff67 100644
--- a/services/camera/virtualcamera/util/MetadataUtil.cc
+++ b/services/camera/virtualcamera/util/MetadataUtil.cc
@@ -67,6 +67,11 @@
return *this;
}
+MetadataBuilder& MetadataBuilder::setDeviceId(int32_t deviceId) {
+ mEntryMap[ANDROID_INFO_DEVICE_ID] = std::vector<int32_t>({deviceId});
+ return *this;
+}
+
MetadataBuilder& MetadataBuilder::setFlashAvailable(bool flashAvailable) {
const uint8_t metadataVal = flashAvailable
? ANDROID_FLASH_INFO_AVAILABLE_TRUE
diff --git a/services/camera/virtualcamera/util/MetadataUtil.h b/services/camera/virtualcamera/util/MetadataUtil.h
index cee867e..4d2500b 100644
--- a/services/camera/virtualcamera/util/MetadataUtil.h
+++ b/services/camera/virtualcamera/util/MetadataUtil.h
@@ -66,6 +66,9 @@
MetadataBuilder& setSupportedHardwareLevel(
camera_metadata_enum_android_info_supported_hardware_level_t hwLevel);
+ // See ANDROID_INFO_DEVICE_ID in CameraMetadataTag.aidl.
+ MetadataBuilder& setDeviceId(int32_t deviceId);
+
// Whether this camera device has a flash unit
// See ANDROID_FLASH_INFO_AVAILABLE in CameraMetadataTag.aidl.
MetadataBuilder& setFlashAvailable(bool flashAvailable);