Camera1: Handle multiple logical cameras with same facing
For Camera1-HAL3 shim, the camera ID filtering logic is revised to
handle case of multiple logical cameras facing the same direction,
and are backed by same/different set of physical camera IDs.
Example 1 (all facing back):
ID1 = ID3 + ID4
ID2 = ID5 + ID6
Example 2 (all facing back):
ID5 = ID1 + ID2
ID6 = ID3 + ID4
In both examples, only ID1 will be advertised to camera1 app.
Test: Check cameras on devices with multiple logical cameras
Test: Camera CTS
Bug: 113705942
Change-Id: I76f370938b3311bbe7adcac8eddf8b6cf08e4571
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index d6789a4..09638d0 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -120,8 +120,8 @@
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.
+ // for each camera facing, only take the first id advertised by HAL in
+ // all [logical, physical1, physical2, ...] id combos, and filter out the rest.
filterLogicalCameraIdsLocked(providerDeviceIds);
deviceIds.insert(deviceIds.end(), providerDeviceIds.begin(), providerDeviceIds.end());
@@ -2500,8 +2500,11 @@
void CameraProviderManager::filterLogicalCameraIdsLocked(
std::vector<std::string>& deviceIds) const
{
- std::unordered_set<std::string> removedIds;
+ // Map between camera facing and camera IDs related to logical camera.
+ std::map<int, std::unordered_set<std::string>> idCombos;
+ // Collect all logical and its underlying physical camera IDs for each
+ // facing.
for (auto& deviceId : deviceIds) {
auto deviceInfo = findDeviceInfoLocked(deviceId);
if (deviceInfo == nullptr) continue;
@@ -2509,25 +2512,38 @@
if (!deviceInfo->mIsLogicalCamera) {
continue;
}
- // idCombo contains the ids of a logical camera and its physical cameras
- std::vector<std::string> idCombo = deviceInfo->mPhysicalIds;
- idCombo.push_back(deviceId);
+ // combo contains the ids of a logical camera and its physical cameras
+ std::vector<std::string> combo = deviceInfo->mPhysicalIds;
+ combo.push_back(deviceId);
+
+ hardware::CameraInfo info;
+ status_t res = deviceInfo->getCameraInfo(&info);
+ if (res != OK) {
+ ALOGE("%s: Error reading camera info: %s (%d)", __FUNCTION__, strerror(-res), res);
+ continue;
+ }
+ idCombos[info.facing].insert(combo.begin(), combo.end());
+ }
+
+ // Only expose one camera ID per facing for all logical and underlying
+ // physical camera IDs.
+ for (auto& r : idCombos) {
+ auto& removedIds = r.second;
for (auto& id : deviceIds) {
- auto foundId = std::find(idCombo.begin(), idCombo.end(), id);
- if (foundId == idCombo.end()) {
+ auto foundId = std::find(removedIds.begin(), removedIds.end(), id);
+ if (foundId == removedIds.end()) {
continue;
}
- idCombo.erase(foundId);
- removedIds.insert(idCombo.begin(), idCombo.end());
+ removedIds.erase(foundId);
break;
}
+ deviceIds.erase(std::remove_if(deviceIds.begin(), deviceIds.end(),
+ [&removedIds](const std::string& s) {
+ return removedIds.find(s) != removedIds.end();}),
+ deviceIds.end());
}
-
- deviceIds.erase(std::remove_if(deviceIds.begin(), deviceIds.end(),
- [&removedIds](const std::string& s) {return removedIds.find(s) != removedIds.end();}),
- deviceIds.end());
}
} // namespace android