From f9d2c02eca0215ea4afcd92925c976585f6ffaef Mon Sep 17 00:00:00 2001 From: Shuzhen Wang Date: Tue, 21 Aug 2018 12:07:35 -0700 Subject: [PATCH] Camera: Add support for hidden physical camera IDs Support 3_5 HAL device version for querying physical camera characteristics. Test: Camera CTS on Pixel devices Bug: 79523700 Change-Id: I804cdb5dc75553d6b6f9fb42187a76bd69168179 --- .../aidl/android/hardware/ICameraService.aidl | 4 +- .../include/camera/NdkCameraMetadataTags.h | 10 +- services/camera/libcameraservice/Android.bp | 1 + .../camera/libcameraservice/CameraService.cpp | 16 +- .../camera/libcameraservice/CameraService.h | 5 + .../common/CameraProviderManager.cpp | 170 ++++++++++++++++-- .../common/CameraProviderManager.h | 23 ++- 7 files changed, 213 insertions(+), 16 deletions(-) diff --git a/camera/aidl/android/hardware/ICameraService.aidl b/camera/aidl/android/hardware/ICameraService.aidl index 9c0f28bfa9..c03831457f 100644 --- a/camera/aidl/android/hardware/ICameraService.aidl +++ b/camera/aidl/android/hardware/ICameraService.aidl @@ -149,8 +149,10 @@ interface ICameraService const int API_VERSION_1 = 1; const int API_VERSION_2 = 2; - // Determines if a particular API version is supported directly + // Determines if a particular API version is supported directly for a cameraId. boolean supportsCameraApi(String cameraId, int apiVersion); + // Determines if a cameraId is a hidden physical camera of a logical multi-camera. + boolean isHiddenPhysicalCamera(String cameraId); void setTorchMode(String cameraId, boolean enabled, IBinder clientBinder); diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h index c1f5ddcb42..6ebd850a4c 100644 --- a/camera/ndk/include/camera/NdkCameraMetadataTags.h +++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h @@ -7209,8 +7209,14 @@ typedef enum acamera_metadata_enum_acamera_request_available_capabilities { ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_MOTION_TRACKING = 10, /** - *

The camera device is a logical camera backed by two or more physical cameras that are - * also exposed to the application.

+ *

The camera device is a logical camera backed by two or more physical cameras. In + * API level 28, the physical cameras must also be exposed to the application via + * CameraManager#getCameraIdList. Starting from API + * level 29, some or all physical cameras may not be independently exposed to the + * application, in which case the physical camera IDs will not be available in + * CameraManager#getCameraIdList. But the application + * can still query the physical cameras' characteristics by calling + * CameraManager#getCameraCharacteristics.

*

Camera application shouldn't assume that there are at most 1 rear camera and 1 front * camera in the system. For an application that switches between front and back cameras, * the recommendation is to switch between the first rear camera and the first front diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp index eccbe54941..706ce3a5ca 100644 --- a/services/camera/libcameraservice/Android.bp +++ b/services/camera/libcameraservice/Android.bp @@ -82,6 +82,7 @@ cc_library_shared { "android.hardware.camera.device@3.2", "android.hardware.camera.device@3.3", "android.hardware.camera.device@3.4", + "android.hardware.camera.device@3.5", ], export_shared_lib_headers: [ diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index f9240db7ca..8e4ad2b33c 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -607,6 +607,7 @@ Status CameraService::makeClient(const sp& cameraService, case CAMERA_DEVICE_API_VERSION_3_2: case CAMERA_DEVICE_API_VERSION_3_3: case CAMERA_DEVICE_API_VERSION_3_4: + case CAMERA_DEVICE_API_VERSION_3_5: if (effectiveApiLevel == API_1) { // Camera1 API route sp tmp = static_cast(cameraCb.get()); *client = new Camera2Client(cameraService, tmp, packageName, @@ -1687,7 +1688,7 @@ Status CameraService::supportsCameraApi(const String16& cameraId, int apiVersion } int deviceVersion = getDeviceVersion(id); - switch(deviceVersion) { + switch (deviceVersion) { case CAMERA_DEVICE_API_VERSION_1_0: case CAMERA_DEVICE_API_VERSION_3_0: case CAMERA_DEVICE_API_VERSION_3_1: @@ -1704,6 +1705,7 @@ Status CameraService::supportsCameraApi(const String16& cameraId, int apiVersion case CAMERA_DEVICE_API_VERSION_3_2: case CAMERA_DEVICE_API_VERSION_3_3: case CAMERA_DEVICE_API_VERSION_3_4: + case CAMERA_DEVICE_API_VERSION_3_5: ALOGV("%s: Camera id %s uses HAL3.2 or newer, supports api1/api2 directly", __FUNCTION__, id.string()); *isSupported = true; @@ -1724,6 +1726,18 @@ Status CameraService::supportsCameraApi(const String16& cameraId, int apiVersion return Status::ok(); } +Status CameraService::isHiddenPhysicalCamera(const String16& cameraId, + /*out*/ bool *isSupported) { + ATRACE_CALL(); + + const String8 id = String8(cameraId); + + ALOGV("%s: for camera ID = %s", __FUNCTION__, id.string()); + *isSupported = mCameraProviderManager->isHiddenPhysicalCamera(id.string()); + + return Status::ok(); +} + void CameraService::removeByClient(const BasicClient* client) { Mutex::Autolock lock(mServiceLock); for (auto& i : mActiveClientManager.getAll()) { diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h index e4a18d3491..47ad8af991 100644 --- a/services/camera/libcameraservice/CameraService.h +++ b/services/camera/libcameraservice/CameraService.h @@ -159,6 +159,11 @@ public: /*out*/ bool *isSupported); + virtual binder::Status isHiddenPhysicalCamera( + const String16& cameraId, + /*out*/ + bool *isSupported); + // Extra permissions checks virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp index 3be6399959..c4944a67a5 100644 --- a/services/camera/libcameraservice/common/CameraProviderManager.cpp +++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp @@ -20,9 +20,12 @@ #include "CameraProviderManager.h" +#include + #include #include #include +#include #include #include #include @@ -424,6 +427,48 @@ bool CameraProviderManager::isLogicalCamera(const CameraMetadata& staticInfo, return true; } +bool CameraProviderManager::isHiddenPhysicalCamera(const std::string& cameraId) { + for (auto& provider : mProviders) { + for (auto& deviceInfo : provider->mDevices) { + if (deviceInfo->mId == cameraId) { + // cameraId is found in public camera IDs advertised by the + // provider. + return false; + } + } + } + + for (auto& provider : mProviders) { + for (auto& deviceInfo : provider->mDevices) { + CameraMetadata info; + status_t res = deviceInfo->getCameraCharacteristics(&info); + if (res != OK) { + ALOGE("%s: Failed to getCameraCharacteristics for id %s", __FUNCTION__, + deviceInfo->mId.c_str()); + return false; + } + + std::vector physicalIds; + if (isLogicalCamera(info, &physicalIds)) { + if (std::find(physicalIds.begin(), physicalIds.end(), cameraId) != + physicalIds.end()) { + int deviceVersion = HARDWARE_DEVICE_API_VERSION( + deviceInfo->mVersion.get_major(), deviceInfo->mVersion.get_minor()); + if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_5) { + ALOGE("%s: Wrong deviceVersion %x for hiddenPhysicalCameraId %s", + __FUNCTION__, deviceVersion, cameraId.c_str()); + return false; + } else { + return true; + } + } + } + } + } + + return false; +} + status_t CameraProviderManager::addProviderLocked(const std::string& newProvider, bool expected) { for (const auto& providerInfo : mProviders) { if (providerInfo->mProviderName == newProvider) { @@ -544,13 +589,22 @@ status_t CameraProviderManager::ProviderInfo::initialize() { // Get initial list of camera devices, if any std::vector devices; - hardware::Return ret = mInterface->getCameraIdList([&status, &devices]( + hardware::Return ret = mInterface->getCameraIdList([&status, this, &devices]( Status idStatus, const hardware::hidl_vec& cameraDeviceNames) { status = idStatus; if (status == Status::OK) { - for (size_t i = 0; i < cameraDeviceNames.size(); i++) { - devices.push_back(cameraDeviceNames[i]); + for (auto& name : cameraDeviceNames) { + uint16_t major, minor; + std::string type, id; + status_t res = parseDeviceName(name, &major, &minor, &type, &id); + if (res != OK) { + ALOGE("%s: Error parsing deviceName: %s: %d", __FUNCTION__, name.c_str(), res); + status = Status::INTERNAL_ERROR; + } else { + devices.push_back(name); + mProviderPublicCameraIds.push_back(id); + } } } }); if (!ret.isOk()) { @@ -705,6 +759,25 @@ status_t CameraProviderManager::ProviderInfo::dump(int fd, const Vector physicalIds; + if (isLogicalCamera(info2, &physicalIds)) { + for (auto& id : physicalIds) { + // Skip if physical id is an independent camera + if (std::find(mProviderPublicCameraIds.begin(), mProviderPublicCameraIds.end(), id) + != mProviderPublicCameraIds.end()) { + continue; + } + + CameraMetadata physicalInfo; + status_t status = device->getPhysicalCameraCharacteristics(id, &physicalInfo); + if (status == OK) { + dprintf(fd, " Physical camera %s characteristics:\n", id.c_str()); + physicalInfo.dump(fd, /*verbosity*/ 2, /*indentation*/ 4); + } + } + } + dprintf(fd, "== Camera HAL device %s (v%d.%d) dumpState: ==\n", device->mName.c_str(), device->mVersion.get_major(), device->mVersion.get_minor()); res = device->dumpState(fd); @@ -838,7 +911,7 @@ std::unique_ptr return std::unique_ptr( new DeviceInfoT(name, tagId, id, minorVersion, resourceCost, - cameraInterface)); + mProviderPublicCameraIds, cameraInterface)); } template @@ -912,9 +985,10 @@ CameraProviderManager::ProviderInfo::DeviceInfo1::DeviceInfo1(const std::string& const metadata_vendor_id_t tagId, const std::string &id, uint16_t minorVersion, const CameraResourceCost& resourceCost, + const std::vector& publicCameraIds, sp interface) : DeviceInfo(name, tagId, id, hardware::hidl_version{1, minorVersion}, - resourceCost), + publicCameraIds, resourceCost), mInterface(interface) { // Get default parameters and initialize flash unit availability // Requires powering on the camera device @@ -1011,9 +1085,10 @@ CameraProviderManager::ProviderInfo::DeviceInfo3::DeviceInfo3(const std::string& const metadata_vendor_id_t tagId, const std::string &id, uint16_t minorVersion, const CameraResourceCost& resourceCost, + const std::vector& publicCameraIds, sp interface) : DeviceInfo(name, tagId, id, hardware::hidl_version{3, minorVersion}, - resourceCost), + publicCameraIds, resourceCost), mInterface(interface) { // Get camera characteristics and initialize flash unit availability Status status; @@ -1054,6 +1129,59 @@ CameraProviderManager::ProviderInfo::DeviceInfo3::DeviceInfo3(const std::string& } else { mHasFlashUnit = false; } + + // Get physical camera characteristics if applicable + auto castResult = device::V3_5::ICameraDevice::castFrom(mInterface); + if (!castResult.isOk()) { + ALOGV("%s: Unable to convert ICameraDevice instance to version 3.5", __FUNCTION__); + return; + } + sp interface_3_5 = castResult; + if (interface_3_5 == nullptr) { + ALOGE("%s: Converted ICameraDevice instance to nullptr", __FUNCTION__); + return; + } + + std::vector physicalIds; + if (CameraProviderManager::isLogicalCamera(mCameraCharacteristics, &physicalIds)) { + for (auto& id : physicalIds) { + if (std::find(mPublicCameraIds.begin(), mPublicCameraIds.end(), id) != + mPublicCameraIds.end()) { + continue; + } + + hardware::hidl_string hidlId(id); + ret = interface_3_5->getPhysicalCameraCharacteristics(hidlId, + [&status, &id, this](Status s, device::V3_2::CameraMetadata metadata) { + status = s; + if (s == Status::OK) { + camera_metadata_t *buffer = + reinterpret_cast(metadata.data()); + size_t expectedSize = metadata.size(); + int res = validate_camera_metadata_structure(buffer, &expectedSize); + if (res == OK || res == CAMERA_METADATA_VALIDATION_SHIFTED) { + set_camera_metadata_vendor_id(buffer, mProviderTagid); + mPhysicalCameraCharacteristics[id] = buffer; + } else { + ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__); + status = Status::INTERNAL_ERROR; + } + } + }); + + if (!ret.isOk()) { + ALOGE("%s: Transaction error getting physical camera %s characteristics for %s: %s", + __FUNCTION__, id.c_str(), mId.c_str(), ret.description().c_str()); + return; + } + if (status != Status::OK) { + ALOGE("%s: Unable to get physical camera %s characteristics for device %s: %s (%d)", + __FUNCTION__, id.c_str(), mId.c_str(), + CameraProviderManager::statusToString(status), status); + return; + } + } + } } CameraProviderManager::ProviderInfo::DeviceInfo3::~DeviceInfo3() {} @@ -1129,6 +1257,18 @@ status_t CameraProviderManager::ProviderInfo::DeviceInfo3::getCameraCharacterist return OK; } +status_t CameraProviderManager::ProviderInfo::DeviceInfo3::getPhysicalCameraCharacteristics( + const std::string& physicalCameraId, CameraMetadata *characteristics) const { + if (characteristics == nullptr) return BAD_VALUE; + if (mPhysicalCameraCharacteristics.find(physicalCameraId) == + mPhysicalCameraCharacteristics.end()) { + return NAME_NOT_FOUND; + } + + *characteristics = mPhysicalCameraCharacteristics.at(physicalCameraId); + return OK; +} + status_t CameraProviderManager::ProviderInfo::parseProviderName(const std::string& name, std::string *type, uint32_t *id) { // Format must be "/" @@ -1460,10 +1600,20 @@ status_t HidlVendorTagDescriptor::createDescriptorFromHidl( status_t CameraProviderManager::getCameraCharacteristicsLocked(const std::string &id, CameraMetadata* characteristics) const { - auto deviceInfo = findDeviceInfoLocked(id, /*minVersion*/ {3,0}, /*maxVersion*/ {4,0}); - if (deviceInfo == nullptr) return NAME_NOT_FOUND; + auto deviceInfo = findDeviceInfoLocked(id, /*minVersion*/ {3,0}, /*maxVersion*/ {5,0}); + if (deviceInfo != nullptr) { + return deviceInfo->getCameraCharacteristics(characteristics); + } + + // Find hidden physical camera characteristics + for (auto& provider : mProviders) { + for (auto& deviceInfo : provider->mDevices) { + status_t res = deviceInfo->getPhysicalCameraCharacteristics(id, characteristics); + if (res != NAME_NOT_FOUND) return res; + } + } - return deviceInfo->getCameraCharacteristics(characteristics); + return NAME_NOT_FOUND; } void CameraProviderManager::filterLogicalCameraIdsLocked( @@ -1482,7 +1632,7 @@ void CameraProviderManager::filterLogicalCameraIdsLocked( // idCombo contains the ids of a logical camera and its physical cameras std::vector idCombo; - bool logicalCamera = CameraProviderManager::isLogicalCamera(info, &idCombo); + bool logicalCamera = isLogicalCamera(info, &idCombo); if (!logicalCamera) { continue; } diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h index c523c2d72f..61e21b4a18 100644 --- a/services/camera/libcameraservice/common/CameraProviderManager.h +++ b/services/camera/libcameraservice/common/CameraProviderManager.h @@ -237,6 +237,7 @@ public: static bool isLogicalCamera(const CameraMetadata& staticInfo, std::vector* physicalCameraIds); + bool isHiddenPhysicalCamera(const std::string& cameraId); private: // All private members, unless otherwise noted, expect mInterfaceMutex to be locked before use mutable std::mutex mInterfaceMutex; @@ -306,17 +307,25 @@ private: (void) characteristics; return INVALID_OPERATION; } + virtual status_t getPhysicalCameraCharacteristics(const std::string& physicalCameraId, + CameraMetadata *characteristics) const { + (void) physicalCameraId; + (void) characteristics; + return INVALID_OPERATION; + } DeviceInfo(const std::string& name, const metadata_vendor_id_t tagId, const std::string &id, const hardware::hidl_version& version, + const std::vector& publicCameraIds, const hardware::camera::common::V1_0::CameraResourceCost& resourceCost) : mName(name), mId(id), mVersion(version), mProviderTagid(tagId), mResourceCost(resourceCost), mStatus(hardware::camera::common::V1_0::CameraDeviceStatus::PRESENT), - mHasFlashUnit(false) {} + mHasFlashUnit(false), mPublicCameraIds(publicCameraIds) {} virtual ~DeviceInfo(); protected: bool mHasFlashUnit; + const std::vector& mPublicCameraIds; template static status_t setTorchMode(InterfaceT& interface, bool enabled); @@ -325,6 +334,12 @@ private: std::unordered_set mUniqueCameraIds; int mUniqueDeviceCount; std::vector mUniqueAPI1CompatibleCameraIds; + // The initial public camera IDs published by the camera provider. + // Currently logical multi-camera is not supported for hot-plug camera. + // And we use this list to keep track of initial public camera IDs + // advertised by the provider, and to distinguish against "hidden" + // physical camera IDs. + std::vector mProviderPublicCameraIds; // HALv1-specific camera fields, including the actual device interface struct DeviceInfo1 : public DeviceInfo { @@ -339,6 +354,7 @@ private: DeviceInfo1(const std::string& name, const metadata_vendor_id_t tagId, const std::string &id, uint16_t minorVersion, const hardware::camera::common::V1_0::CameraResourceCost& resourceCost, + const std::vector& publicCameraIds, sp interface); virtual ~DeviceInfo1(); private: @@ -356,14 +372,17 @@ private: virtual status_t dumpState(int fd) const override; virtual status_t getCameraCharacteristics( CameraMetadata *characteristics) const override; + virtual status_t getPhysicalCameraCharacteristics(const std::string& physicalCameraId, + CameraMetadata *characteristics) const override; DeviceInfo3(const std::string& name, const metadata_vendor_id_t tagId, const std::string &id, uint16_t minorVersion, const hardware::camera::common::V1_0::CameraResourceCost& resourceCost, - sp interface); + const std::vector& publicCameraIds, sp interface); virtual ~DeviceInfo3(); private: CameraMetadata mCameraCharacteristics; + std::unordered_map mPhysicalCameraCharacteristics; }; private: