Camera: Filter logical camera ids to API1 app
A lot of API1 apps don't handle logical/physical cameras well.
For each [logical, physical1, phiscal2] id combo, only advertise the
first ids in the HAL id list.
Test: Camera CTS
Bug: 80075565
Change-Id: I1e300a8e13eff2bfef0a6a157a56717a7b73976c
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index c49de8e..98d0534 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -624,11 +624,19 @@
return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
}
- if (!checkPhysicalCameraId(physicalCameraId)) {
- String8 msg = String8::format("Camera %s: Camera doesn't support physicalCameraId %s.",
+ if (physicalCameraId.size() > 0) {
+ std::vector<std::string> physicalCameraIds;
+ std::string physicalId(physicalCameraId.string());
+ bool logicalCamera =
+ CameraProviderManager::isLogicalCamera(mDevice->info(), &physicalCameraIds);
+ if (!logicalCamera ||
+ std::find(physicalCameraIds.begin(), physicalCameraIds.end(), physicalId) ==
+ physicalCameraIds.end()) {
+ String8 msg = String8::format("Camera %s: Camera doesn't support physicalCameraId %s.",
mCameraIdStr.string(), physicalCameraId.string());
- ALOGE("%s: %s", __FUNCTION__, msg.string());
- return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+ ALOGE("%s: %s", __FUNCTION__, msg.string());
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+ }
}
std::vector<sp<Surface>> surfaces;
std::vector<sp<IBinder>> binders;
@@ -1144,43 +1152,6 @@
return binder::Status::ok();
}
-bool CameraDeviceClient::checkPhysicalCameraId(const String8& physicalCameraId) {
- if (0 == physicalCameraId.size()) {
- return true;
- }
-
- CameraMetadata staticInfo = mDevice->info();
- camera_metadata_entry_t entryCap;
- bool isLogicalCam = false;
-
- entryCap = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
- for (size_t i = 0; i < entryCap.count; ++i) {
- uint8_t capability = entryCap.data.u8[i];
- if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA) {
- isLogicalCam = true;
- }
- }
- if (!isLogicalCam) {
- return false;
- }
-
- camera_metadata_entry_t entryIds = staticInfo.find(ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS);
- const uint8_t* ids = entryIds.data.u8;
- size_t start = 0;
- for (size_t i = 0; i < entryIds.count; ++i) {
- if (ids[i] == '\0') {
- if (start != i) {
- String8 currentId((const char*)ids+start);
- if (currentId == physicalCameraId) {
- return true;
- }
- }
- start = i+1;
- }
- }
- return false;
-}
-
bool CameraDeviceClient::roundBufferDimensionNearest(int32_t width, int32_t height,
int32_t format, android_dataspace dataSpace, const CameraMetadata& info,
/*out*/int32_t* outWidth, /*out*/int32_t* outHeight) {
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 66e9196..43f1a91 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -98,9 +98,14 @@
std::lock_guard<std::mutex> lock(mInterfaceMutex);
std::vector<std::string> deviceIds;
for (auto& provider : mProviders) {
- for (auto& id : provider->mUniqueAPI1CompatibleCameraIds) {
- deviceIds.push_back(id);
- }
+ std::vector<std::string> providerDeviceIds = provider->mUniqueAPI1CompatibleCameraIds;
+
+ // API1 app doesn't handle logical and physical camera devices well. So
+ // for each [logical, physical1, physical2, ...] id combo, only take the
+ // first id advertised by HAL, and filter out the rest.
+ filterLogicalCameraIdsLocked(providerDeviceIds);
+
+ deviceIds.insert(deviceIds.end(), providerDeviceIds.begin(), providerDeviceIds.end());
}
std::sort(deviceIds.begin(), deviceIds.end(),
@@ -172,11 +177,7 @@
status_t CameraProviderManager::getCameraCharacteristics(const std::string &id,
CameraMetadata* characteristics) const {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
-
- auto deviceInfo = findDeviceInfoLocked(id, /*minVersion*/ {3,0}, /*maxVersion*/ {4,0});
- if (deviceInfo == nullptr) return NAME_NOT_FOUND;
-
- return deviceInfo->getCameraCharacteristics(characteristics);
+ return getCameraCharacteristicsLocked(id, characteristics);
}
status_t CameraProviderManager::getHighestSupportedVersion(const std::string &id,
@@ -391,6 +392,37 @@
return ret;
}
+bool CameraProviderManager::isLogicalCamera(const CameraMetadata& staticInfo,
+ std::vector<std::string>* physicalCameraIds) {
+ bool isLogicalCam = false;
+ camera_metadata_ro_entry_t entryCap;
+
+ entryCap = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
+ for (size_t i = 0; i < entryCap.count; ++i) {
+ uint8_t capability = entryCap.data.u8[i];
+ if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA) {
+ isLogicalCam = true;
+ break;
+ }
+ }
+ if (!isLogicalCam) {
+ return false;
+ }
+
+ camera_metadata_ro_entry_t entryIds = staticInfo.find(ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS);
+ const uint8_t* ids = entryIds.data.u8;
+ size_t start = 0;
+ for (size_t i = 0; i < entryIds.count; ++i) {
+ if (ids[i] == '\0') {
+ if (start != i) {
+ physicalCameraIds->push_back((const char*)ids+start);
+ }
+ start = i+1;
+ }
+ }
+ return true;
+}
+
status_t CameraProviderManager::addProviderLocked(const std::string& newProvider, bool expected) {
for (const auto& providerInfo : mProviders) {
if (providerInfo->mProviderName == newProvider) {
@@ -599,7 +631,7 @@
mUniqueCameraIds.insert(id);
if (isAPI1Compatible) {
- mUniqueAPI1CompatibleCameraIds.insert(id);
+ mUniqueAPI1CompatibleCameraIds.push_back(id);
}
if (parsedId != nullptr) {
@@ -613,7 +645,9 @@
if ((*it)->mId == id) {
mUniqueCameraIds.erase(id);
if ((*it)->isAPI1Compatible()) {
- mUniqueAPI1CompatibleCameraIds.erase(id);
+ mUniqueAPI1CompatibleCameraIds.erase(std::remove(
+ mUniqueAPI1CompatibleCameraIds.begin(),
+ mUniqueAPI1CompatibleCameraIds.end(), id));
}
mDevices.erase(it);
break;
@@ -1417,5 +1451,51 @@
return OK;
}
+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;
+
+ return deviceInfo->getCameraCharacteristics(characteristics);
+}
+
+void CameraProviderManager::filterLogicalCameraIdsLocked(
+ std::vector<std::string>& deviceIds) const
+{
+ std::unordered_set<std::string> removedIds;
+
+ for (auto& deviceId : deviceIds) {
+ CameraMetadata info;
+ status_t res = getCameraCharacteristicsLocked(deviceId, &info);
+ if (res != OK) {
+ ALOGE("%s: Failed to getCameraCharacteristics for id %s", __FUNCTION__,
+ deviceId.c_str());
+ return;
+ }
+
+ // idCombo contains the ids of a logical camera and its physical cameras
+ std::vector<std::string> idCombo;
+ bool logicalCamera = CameraProviderManager::isLogicalCamera(info, &idCombo);
+ if (!logicalCamera) {
+ continue;
+ }
+ idCombo.push_back(deviceId);
+
+ for (auto& id : deviceIds) {
+ auto foundId = std::find(idCombo.begin(), idCombo.end(), id);
+ if (foundId == idCombo.end()) {
+ continue;
+ }
+
+ idCombo.erase(foundId);
+ removedIds.insert(idCombo.begin(), idCombo.end());
+ break;
+ }
+ }
+
+ deviceIds.erase(std::remove_if(deviceIds.begin(), deviceIds.end(),
+ [&removedIds](const std::string& s) {return removedIds.find(s) != removedIds.end();}),
+ deviceIds.end());
+}
} // namespace android
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index bbe6789..b8b8b8c 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -230,6 +230,13 @@
hardware::hidl_version minVersion = hardware::hidl_version{0,0},
hardware::hidl_version maxVersion = hardware::hidl_version{1000,0}) const;
+ /*
+ * Check if a camera with staticInfo is a logical camera. And if yes, return
+ * the physical camera ids.
+ */
+ static bool isLogicalCamera(const CameraMetadata& staticInfo,
+ std::vector<std::string>* physicalCameraIds);
+
private:
// All private members, unless otherwise noted, expect mInterfaceMutex to be locked before use
mutable std::mutex mInterfaceMutex;
@@ -314,7 +321,7 @@
std::vector<std::unique_ptr<DeviceInfo>> mDevices;
std::unordered_set<std::string> mUniqueCameraIds;
int mUniqueDeviceCount;
- std::unordered_set<std::string> mUniqueAPI1CompatibleCameraIds;
+ std::vector<std::string> mUniqueAPI1CompatibleCameraIds;
// HALv1-specific camera fields, including the actual device interface
struct DeviceInfo1 : public DeviceInfo {
@@ -414,6 +421,9 @@
static const char* torchStatusToString(
const hardware::camera::common::V1_0::TorchModeStatus&);
+ status_t getCameraCharacteristicsLocked(const std::string &id,
+ CameraMetadata* characteristics) const;
+ void filterLogicalCameraIdsLocked(std::vector<std::string>& deviceIds) const;
};
} // namespace android