getCameraIdList() 获取当前设备的相机设备列表 根据这个列表可以查询当前存在几个相机
本文将从当设备启动时主动初始化的列表和当设备存在拔插时的被动回调两条线路分析这个api
getCameraIdList
路径 frameworks/base/core/java/android/hardware/camera2/CameraManager.java
获取idlist,在下面代码可以看出调用的是CameraManagerGlobal的getCameraIdList
@NonNull
public String[] getCameraIdList() throws CameraAccessException {
return CameraManagerGlobal.get().getCameraIdList();
}
CameraManagerGlobal::getCameraIdList
路径 frameworks/base/core/java/android/hardware/camera2/CameraManager.java
这里面主要是获取到cameraService
根据CameraManager的mDeviceStatus里面的数据进行返回
private final ArrayMap
public String[] getCameraIdList() {
String[] cameraIds = null;
synchronized(mLock) {
// Try to make sure we have an up-to-date list of camera devices.
//获取cameraService
connectCameraServiceLocked();
int idCount = 0;
for (int i = 0; i < mDeviceStatus.size(); i++) {
int status = mDeviceStatus.valueAt(i);
if (status == ICameraServiceListener.STATUS_NOT_PRESENT ||
status == ICameraServiceListener.STATUS_ENUMERATING) continue;
idCount++;
}
cameraIds = new String[idCount];
idCount = 0;
for (int i = 0; i < mDeviceStatus.size(); i++) {
int status = mDeviceStatus.valueAt(i);
if (status == ICameraServiceListener.STATUS_NOT_PRESENT ||
status == ICameraServiceListener.STATUS_ENUMERATING) continue;
cameraIds[idCount] = mDeviceStatus.keyAt(i);
idCount++;
}
}
//...接下来是排序
return cameraIds;
}
mDeviceStatus的添加 onStatusChangedLocked
路径 frameworks/base/core/java/android/hardware/camera2/CameraManager.java
可以明显看出这个数据结构中的值是受这个回调函数控制的当回调回来的是添加设备则添加移除则移除,这个回调是由函数connectCameraServiceLocked调用而来的
private final ArrayMap mDeviceStatus = new ArrayMap();
private void onStatusChangedLocked(int status, String id) {
//...
Integer oldStatus;
if (status == ICameraServiceListener.STATUS_NOT_PRESENT) {
oldStatus = mDeviceStatus.remove(id);
} else {
oldStatus = mDeviceStatus.put(id, status);
}
//...
final int callbackCount = mCallbackMap.size();
for (int i = 0; i < callbackCount; i++) {
Executor executor = mCallbackMap.valueAt(i);
final AvailabilityCallback callback = mCallbackMap.keyAt(i);
postSingleUpdate(callback, executor, id, status);
}
} // onStatusChangedLocked
connectCameraServiceLocked
路径 frameworks/base/core/java/android/hardware/camera2/CameraManager.java
这个函数是在getCameraIdList函数中调用过的 主要的用途就是获取链接到cameraService,并将自己作为监听注册给cameraService,
这样本文就从这开始介绍 主动:初始设备列表 和 被动:动态插拔设备列表 两种形式
主动:在调用注册函数后会获取到cameraStatuses的一个数组,这个里面存放了关于摄像头设备的挂载信息,遍历这个数组把他们放进mDeviceStatus中。
被动:当然这个类里面同样重写了onStatusChanged函数,并且这里面同样调用了onStatusChangedLocked,这样当cameraService想要通知当前的摄像设备的挂载状态时可以通过这个回调获取了
private void connectCameraServiceLocked() {
//...
IBinder cameraServiceBinder = ServiceManager.getService(CAMERA_SERVICE_BINDER_NAME);
//...
ICameraService cameraService = ICameraService.Stub.asInterface(cameraServiceBinder);
try {
CameraMetadataNative.setupGlobalVendorTagDescriptor();
} catch (ServiceSpecificException e) {
handleRecoverableSetupErrors(e);
}
try {
CameraStatus[] cameraStatuses = cameraService.addListener(this);
for (CameraStatus c : cameraStatuses) {
onStatusChangedLocked(c.status, c.cameraId);
}
mCameraService = cameraService;
} catch(ServiceSpecificException e) {
// Unexpected failure
throw new IllegalStateException("Failed to register a camera service listener", e);
} catch (RemoteException e) {
// Camera service is now down, leave mCameraService as null
}
}
//####################################################################
@Override
public void onStatusChanged(int status, String cameraId) throws RemoteException {
synchronized(mLock) {
onStatusChangedLocked(status, cameraId);
}
}
那当cameraManager被注册到cameraService后是如何首次返回摄像设备的挂载信息和在后续挂载信息改变时通知cameraManager的呢
首次获取
首次获取肯定是因为调用了注册监听的接口后返回的值
addListener ICameraService.aidl
路径 frameworks/av/camera/aidl/android/hardware/ICameraService.aidl
CameraStatus[] addListener(ICameraServiceListener listener);
动态插拔
动态插拔是调用观察者们的onStatusChanged函数
onStatusChanged ICameraServiceListener.aidl
路径 frameworks/av/camera/aidl/android/hardware/ICameraServiceListener.aidl
oneway void onStatusChanged(int status, String cameraId);
CameraService::addListener
路径 frameworks/av/services/camera/libcameraservice/CameraService.cpp
emplace_back 不需要构造添加进map
主动:cameraStatuses 是由vector结构保存的hardware::CameraStatus 而这个结构中的数据是由mCameraStates提供的
mCameraStates 是一个map结构
在这个函数中明显能看出设备的挂载信息是由mCameraStates vector结构 提供的,而后利用这个vector结构 调用返回cameraStatuses,那么就应该查找mCameraStates结构是何时填充的
被动:当CameraService收到设备挂载信息后,可以调用这个mListenerList结构中的观察者的onStatusChanged函数从而改变挂载设备数
Status CameraService::addListener(const sp& listener,
/*out*/
std::vector *cameraStatuses) {
//...
Mutex::Autolock lock(mServiceLock);
{
//...
mListenerList.push_back(listener);
}
{
Mutex::Autolock lock(mCameraStatesLock);
for (auto& i : mCameraStates) {
cameraStatuses->emplace_back(i.first, mapToInterface(i.second->getStatus()));
}
}
//...
return Status::ok();
}
// ####################################################################
//frameworks/av/services/camera/libcameraservice/CameraService.h
std::map> mCameraStates;
std::vector> mListenerList;
addStates mCameraStates的填充
路径 frameworks/av/services/camera/libcameraservice/CameraService.cpp
可以看出当调用CameraService::addStates mCameraStates中的数据被更新
void CameraService::addStates(const String8 id) {
std::string cameraId(id.c_str());
hardware::camera::common::V1_0::CameraResourceCost cost;
status_t res = mCameraProviderManager->getResourceCost(cameraId, &cost);
//...
std::set conflicting;
for (size_t i = 0; i < cost.conflictingDevices.size(); i++) {
conflicting.emplace(String8(cost.conflictingDevices[i].c_str()));
}
{
Mutex::Autolock lock(mCameraStatesLock);
mCameraStates.emplace(id, std::make_shared(id, cost.resourceCost,
conflicting));
}
//...
updateCameraNumAndIds();
logDeviceAdded(id, "Device added");
}
onDeviceStatusChanged addStates的调用
路径 frameworks/av/services/camera/libcameraservice/CameraService.cpp
主动:这里认为当主动调用onDeviceStatusChanged函数时addStates函数则被调用
根据上一篇CameraService启动流程分析在enumerateProviders流程中onDeviceStatusChanged被主动调用获取当前设备挂载状态,具体可参考Android Camera(三) CameraService启动流程 (androidP)_we1less的博客-CSDN博客
从这部分代码可以知道enumerateProviders流程中会向mCameraProviderManager请求deviceIds并遍历这个数据结构,调用onDeviceStatusChanged的PRESENT,这样相机列表就被添加进去了,接下来继续分析mCameraProviderManager->getCameraDeviceIds()
被动:同样的在该函数中存在一个updateStatus函数,这个函数就是上文中提到的,可以用来通知观察者们设备挂载信息改变了,从而完成被动调用流程,注意当调用enumerateProviders函数时,同样也调用了mCameraProviderManager->initialize(this);函数,将CameraService作为监听者注册到mCameraProviderManager中,这也是mCameraProviderManager能回调调用onDeviceStatusChanged函数,并且调用updateStatus函数回调的一个基础。
void CameraService::onDeviceStatusChanged(const String8& id,
CameraDeviceStatus newHalStatus) {
ALOGI("%s: Status changed for cameraId=%s, newStatus=%d", __FUNCTION__,
id.string(), newHalStatus);
StatusInternal newStatus = mapToInternal(newHalStatus);
std::shared_ptr state = getCameraState(id);
if (state == nullptr) {
if (newStatus == StatusInternal::PRESENT) {
ALOGI("%s: Unknown camera ID %s, a new camera is added",
__FUNCTION__, id.string());
// First add as absent to make sure clients are notified below
addStates(id);
updateStatus(newStatus, id);
} else {
ALOGE("%s: Bad camera ID %s", __FUNCTION__, id.string());
}
return;
}
//...
}
//####################################################
status_t CameraService::enumerateProviders() {
...
if (nullptr == mCameraProviderManager.get()) {
mCameraProviderManager = new CameraProviderManager();
//被动注册
res = mCameraProviderManager->initialize(this);
...
}
std::vector deviceIds;
deviceIds = mCameraProviderManager->getCameraDeviceIds();
...
for (auto& cameraId : deviceIds) {
String8 id8 = String8(cameraId.c_str());
onDeviceStatusChanged(id8, CameraDeviceStatus::PRESENT);
}
return OK;
}
//####################################################
void CameraService::updateStatus(StatusInternal status, const String8& cameraId,
std::initializer_list rejectSourceStates) {
auto state = getCameraState(cameraId);
//...
//回调的过程
for (auto& listener : mListenerList) {
listener->onStatusChanged(mapToInterface(status), String16(cameraId));
}
});
}
getCameraDeviceIds
路径 frameworks/av/services/camera/libcameraservice/common/CameraProviderManager.cpp
主动:这里可以看出先遍历mProviders这是一个由ProviderInfo对象组成的一个vector结构 并从其中的每个对象获取CameraId
mProviders在上一篇文章中已经介绍过了那么现在开始追溯provider->mUniqueCameraIds的填充
被动:在上一层的CameraService会在CameraProviderManager::initialize函数中被存放到CameraProviderManager::mListener中,在addProviderLocked函数中还会把CameraProviderManager对象作为mManager成员构造成ProviderInfo对象并添加到mProviders中,紧接着调用providerInfo->initialize(这个是回调的关键下面会说明),这样就可以通过ProviderInfo对象,获取其中的mManager成员(也就是CameraProviderManager对象,这个mManager对象中保存着成员mListener也就是CameraService)。可以通过CameraProviderManager::getStatusListener函数获取到这个成员mListener。
std::vector CameraProviderManager::getCameraDeviceIds() const {
std::lock_guard lock(mInterfaceMutex);
std::vector deviceIds;
for (auto& provider : mProviders) {
for (auto& id : provider->mUniqueCameraIds) {
deviceIds.push_back(id);
}
}
return deviceIds;
}
//########################################################################
//frameworks/av/services/camera/libcameraservice/common/CameraProviderManager.h
std::vector> mProviders;
//########################################################################
status_t CameraProviderManager::initialize(wp listener,
ServiceInteractionProxy* proxy) {
//...
mListener = listener;
mServiceProxy = proxy;
//...
addProviderLocked(kLegacyProviderName, /*expected*/ false);
addProviderLocked(kExternalProviderName, /*expected*/ false);
return OK;
}
//########################################################################
//frameworks/av/services/camera/libcameraservice/common/CameraProviderManager.h
wp mListener;
//########################################################################
//frameworks/av/services/camera/libcameraservice/common/CameraProviderManager.cpp
status_t CameraProviderManager::addProviderLocked(const std::string& newProvider, bool expected) {
//...
sp providerInfo =
new ProviderInfo(newProvider, interface, this);
status_t res = providerInfo->initialize();
//...
mProviders.push_back(providerInfo);
return OK;
}
CameraProviderManager::ProviderInfo::addDevice mUniqueCameraIds的填充
路径 frameworks/av/services/camera/libcameraservice/common/CameraProviderManager.cpp
主动:当调用了ProviderInfo::addDevice后,才会向mUniqueCameraIds中添加数据
上一篇文章中也提到addDevice是由ProviderInfo::initialize函数调用的,这个函数执行期间还调用了mInterface->getCameraIdList 而ProviderInfo::mInterface是CameraProvider的代理 参考
Android Camera(三) CameraService启动流程 (androidP)_we1less的博客-CSDN博客
也就是说代码会调用到CameraProvider的getCameraIdList
被动:这里注意ProviderInfo::initialize这里会调用setCallback将ProviderInfo作为CameraProvider的监听对象注册进去了,这一步在上一层已经说明了调用流程。
此时的ProviderInfo中存在着mManager成员(也就是CameraProviderManager对象),调用该对象的getStatusListener函数可以获取CameraProviderManager对象的mListener成员(CameraService),此时调用这个listener(CameraService)的onDeviceStatusChanged方法可以完成回调流程。那么对于CameraProvider来讲就可以调用cameraDeviceStatusChange完成对上层的回调
status_t CameraProviderManager::ProviderInfo::addDevice(const std::string& name,
CameraDeviceStatus initialStatus, /*out*/ std::string* parsedId) {
//...
status_t res = parseDeviceName(name, &major, &minor, &type, &id);
//...
std::unique_ptr deviceInfo;
//...
deviceInfo->mStatus = initialStatus;
bool isAPI1Compatible = deviceInfo->isAPI1Compatible();
mDevices.push_back(std::move(deviceInfo));
mUniqueCameraIds.insert(id);
if (isAPI1Compatible) {
mUniqueAPI1CompatibleCameraIds.push_back(id);
}
//...
return OK;
}
//###############################################################################
//frameworks/av/services/camera/libcameraservice/common/CameraProviderManager.cpp
status_t CameraProviderManager::ProviderInfo::initialize() {
//...
hardware::Return status = mInterface->setCallback(this);
//...
std::vector devices;
hardware::Return ret = mInterface->getCameraIdList([&status, &devices](
Status idStatus,
const hardware::hidl_vec& cameraDeviceNames) {
status = idStatus;
if (status == Status::OK) {
for (size_t i = 0; i < cameraDeviceNames.size(); i++) {
//将返回的设备填装到devices中
devices.push_back(cameraDeviceNames[i]);
}
} });
...
sp listener = mManager->getStatusListener();
for (auto& device : devices) {
std::string id;
status_t res = addDevice(device,
hardware::camera::common::V1_0::CameraDeviceStatus::PRESENT, &id);
...
}
...
mInitialized = true;
return OK;
}
//###############################################################################
hardware::Return CameraProviderManager::ProviderInfo::cameraDeviceStatusChange(
const hardware::hidl_string& cameraDeviceName,
CameraDeviceStatus newStatus) {
sp listener;
std::string id;
bool initialized = false;
{
std::lock_guard lock(mLock);
bool known = false;
//...
if (!known) {
//...
addDevice(cameraDeviceName, newStatus, &id);
} else if (newStatus == CameraDeviceStatus::NOT_PRESENT) {
removeDevice(id);
}
listener = mManager->getStatusListener();
initialized = mInitialized;
}
if (listener != nullptr && initialized) {
listener->onDeviceStatusChanged(String8(id.c_str()), newStatus);
}
return hardware::Void();
}
CameraProvider::getCameraIdList (主动)
CameraProvider::setCallback (被动)
路径 hardware/interfaces/camera/provider/2.4/default/CameraProvider.cpp
主动:这里面可知返回的是由mCameraDeviceNames (Vector)数组里面的deviceNamePair.second组成的一个(Vector)数组,接下来看看mCameraDeviceNames是何时被填充的
被动:可知上一层的ProviderInfo作为这一层的mCallbacks成员存在,这样就可以在本层调用ProviderInfo::cameraDeviceStatusChange函数,完成对上层的回调。
Return CameraProvider::getCameraIdList(getCameraIdList_cb _hidl_cb) {
std::vector deviceNameList;
for (auto const& deviceNamePair : mCameraDeviceNames) {
if (mCameraStatusMap[deviceNamePair.first] == CAMERA_DEVICE_STATUS_PRESENT) {
deviceNameList.push_back(deviceNamePair.second);
}
}
hidl_vec hidlDeviceNameList(deviceNameList);
_hidl_cb(Status::OK, hidlDeviceNameList);
return Void();
}
//#####################################################################
//hardware/interfaces/camera/provider/2.4/default/CameraProvider.h
SortedVector> mCameraDeviceNames;
//#####################################################################
Return CameraProvider::setCallback(const sp& callback) {
Mutex::Autolock _l(mCbLock);
mCallbacks = callback;
return Status::OK;
}
CameraProvider::addDeviceNames
路径 hardware/interfaces/camera/provider/2.4/default/CameraProvider.cpp
主动:在这个CameraProvider::addDeviceNames函数中mCameraDeviceNames被填充的
被动:在这个addDeviceNames环节中会调用mCallbacks的cameraDeviceStatusChange进行回调,由于CameraProvider是继承自结构体camera_module_callbacks_t的,所以可以向so中提供sCameraDeviceStatusChange指针提其在挂载变动时调用。在sCameraDeviceStatusChange函数中会调用mCallbacks的cameraDeviceStatusChange进行回调流程。
void CameraProvider::addDeviceNames(int camera_id, CameraDeviceStatus status, bool cam_new)
{
//...
int deviceVersion = mModule->getDeviceVersion(camera_id);
auto deviceNamePair = std::make_pair(cameraIdStr,
getHidlDeviceName(cameraIdStr, deviceVersion));
mCameraDeviceNames.add(deviceNamePair);
if (cam_new) {
mCallbacks->cameraDeviceStatusChange(deviceNamePair.second, status);
}
//...
}
//#######################################################################
void CameraProvider::sCameraDeviceStatusChange(
const struct camera_module_callbacks* callbacks,
int camera_id,
int new_status) {
CameraProvider* cp = const_cast(
static_cast(callbacks));
bool found = false;
if (cp == nullptr) {
ALOGE("%s: callback ops is null", __FUNCTION__);
return;
}
Mutex::Autolock _l(cp->mCbLock);
char cameraId[kMaxCameraIdLen];
snprintf(cameraId, sizeof(cameraId), "%d", camera_id);
std::string cameraIdStr(cameraId);
cp->mCameraStatusMap[cameraIdStr] = (camera_device_status_t) new_status;
if (cp->mCallbacks != nullptr) {
CameraDeviceStatus status = (CameraDeviceStatus) new_status;
for (auto const& deviceNamePair : cp->mCameraDeviceNames) {
if (cameraIdStr.compare(deviceNamePair.first) == 0) {
cp->mCallbacks->cameraDeviceStatusChange(
deviceNamePair.second, status);
found = true;
}
}
switch (status) {
case CameraDeviceStatus::PRESENT:
case CameraDeviceStatus::ENUMERATING:
if (!found) {
cp->addDeviceNames(camera_id, status, true);
}
break;
case CameraDeviceStatus::NOT_PRESENT:
if (found) {
cp->removeDeviceNames(camera_id);
}
}
}
}
//#######################################################################
CameraProvider::CameraProvider() :
camera_module_callbacks_t({sCameraDeviceStatusChange,
sTorchModeStatusChange}) {
mInitFailed = initialize();
}
//#######################################################################
//hardware/interfaces/camera/provider/2.4/default/CameraProvider.h
struct CameraProvider : public ICameraProvider, public camera_module_callbacks_t
CameraProvider::initialize
路径 hardware/interfaces/camera/provider/2.4/default/CameraProvider.cpp
主动:最后是在 CameraProvider初始化的时候向so中调用获取的
被动:会调用mModule->setCallbacks(this);将CameraProvider自己注册进去,这样so中就可以利用这个结构体中sCameraDeviceStatusChange指针进行回调,的一旦出现设备挂载变动就调用回调向上传递了。
bool CameraProvider::initialize() {
camera_module_t *rawModule;
int err = hw_get_module(CAMERA_HARDWARE_MODULE_ID,
(const hw_module_t **)&rawModule);
//...
mModule = new CameraModule(rawModule);
err = mModule->init();
//...
err = mModule->setCallbacks(this);
//...
mNumberOfLegacyCameras = mModule->getNumberOfCameras();
for (int i = 0; i < mNumberOfLegacyCameras; i++) {
//...
addDeviceNames(i);
}
return false; // mInitFailed
}
//#####################################################################
//hardware/interfaces/camera/common/1.0/default/CameraModule.cpp
int CameraModule::getNumberOfCameras() {
int numCameras;
ATRACE_BEGIN("camera_module->get_number_of_cameras");
numCameras = mModule->get_number_of_cameras();
ATRACE_END();
return numCameras;
}
int CameraModule::setCallbacks(const camera_module_callbacks_t *callbacks) {
int res = OK;
ATRACE_BEGIN("camera_module->set_callbacks");
if (getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_1) {
res = mModule->set_callbacks(callbacks);
}
ATRACE_END();
return res;
}