如果有配置双摄模式,Dual Camera 也会生成一个 Camera ID,提供打开双摄模式时使用
多出的Dual Camera ID也称为逻辑摄像头
Android Q 在 Framework 层会删除逻辑摄像头的ID,让上层获取最大摄像头数量时,只获取到物理摄像头的数量
但在删除逻辑摄像头数量时,Google的代码逻辑有点问题,会多删除一个物理摄像头的数量,导致获取最大相机数量时,少了一个物理摄像头(少的是搭配组成双摄的副摄)
假设物理摄像头一共有4颗,main 和 main2 组成双摄,会多出一个逻辑摄像头ID
Camera ID:main(ID0),sub(ID1),main2(ID2),sub2(ID3),DualCam(ID4)
frameworks/av/services/camera/libcameraservice/common/CameraProviderManager.cpp 此文件中
std::vector<std::string> CameraProviderManager::getAPI1CompatibleCameraDeviceIds() const {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
std::vector<std::string> deviceIds;
for (auto& provider : mProviders) {
std::vector<std::string> providerDeviceIds = provider->mUniqueAPI1CompatibleCameraIds;
// API1 app doesn't handle logical and physical camera devices well. So
// 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); '此函数的调用就是为了删除逻辑摄像头'
// Hidden secure camera ids are not to be exposed to camera1 api.
providerDeviceIds.erase(std::remove_if(providerDeviceIds.begin(), providerDeviceIds.end(),
[this](const std::string& s) {
return this->isPublicallyHiddenSecureCameraLocked(s);}),
providerDeviceIds.end());
deviceIds.insert(deviceIds.end(), providerDeviceIds.begin(), providerDeviceIds.end());
}
void CameraProviderManager::filterLogicalCameraIdsLocked( '函数的实现'
std::vector<std::string>& deviceIds) const
{
// 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;
if (!deviceInfo->mIsLogicalCamera) { '这里判断是否是逻辑摄像头'
continue;
}
// combo contains the ids of a logical camera and its physical cameras
std::vector<std::string> combo = deviceInfo->mPhysicalIds; '当遍历到ID4时,会把main 和 main2 的ID赋值给combo,ID0 和 ID2'
combo.push_back(deviceId); '这里又添加了双摄ID4,combo变成了3个成员'
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()); '这里添加了准备删除的Camera ID:ID0、ID2、ID4'
}
// Only expose one camera ID per facing for all logical and underlying
// physical camera IDs.
for (auto& r : idCombos) {
auto& removedIds = r.second; '准备删除的ID,从0开始遍历'
for (auto& id : deviceIds) {
auto foundId = std::find(removedIds.begin(), removedIds.end(), id);
if (foundId == removedIds.end()) {
continue;
}
removedIds.erase(foundId); '这里删除了ID0'
break; '接着就跳出循环了,没有把物理摄像头 main2(ID2)给删除'
} 'removedIds 里还有 ID2 和 ID4'
deviceIds.erase(std::remove_if(deviceIds.begin(), deviceIds.end(),
[&removedIds](const std::string& s) {
return removedIds.find(s) != removedIds.end();}),
deviceIds.end()); '这里把 ID2 和 ID4 删除了'
} '所以最大相机数量变成 5 - 2 = 3,多减去了一个物理摄像头'
}
所以当配置了双摄的时候,上层获取最大相机数量时,数量是错误的
void CameraProviderManager::filterLogicalCameraIdsLocked(
std::vector<std::string>& deviceIds) const
{
……
// combo contains the ids of a logical camera and its physical cameras
'这里不添加 ID0 和 ID2'
std::vector<std::string> combo; // = deviceInfo->mPhysicalIds;
combo.push_back(deviceId); 'combo中只有一个ID4'
……
'注掉下面这段代码'
/* for (auto& id : deviceIds) {
auto foundId = std::find(removedIds.begin(), removedIds.end(), id);
if (foundId == removedIds.end()) {
continue;
}
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()); '这里删除的时候只会删除ID4了'
对比了 Android P 的代码,发现也是有问题的
frameworks/av/services/camera/libcameraservice/common/CameraProviderManager.cpp
void CameraProviderManager::filterLogicalCameraIdsLocked(
std::vector<std::string>& deviceIds) const
{
……
for (auto& id : deviceIds) {
auto foundId = std::find(idCombo.begin(), idCombo.end(), id);
if (foundId == idCombo.end()) {
continue;
}
idCombo.erase(foundId); '先把ID4从idCombo中删除了'
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());
}
所以 Android P 中并没有删除逻辑摄像头ID