Android Camera getCameraIdList流程 (android P)

Posted we1less

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android Camera getCameraIdList流程 (android P)相关的知识,希望对你有一定的参考价值。

getCameraIdList() 获取当前设备的相机设备列表 根据这个列表可以查询当前存在几个相机

本文将从当设备启动时主动初始化的列表和当设备存在拔插时的被动回调两条线路分析这个api


getCameraIdList

路径  frameworks/base/core/java/android/hardware/camera2/CameraManager.java

        获取idlist,在下面代码可以看出调用的是CameraManagerGlobalgetCameraIdList

@NonNull
public String[] getCameraIdList() throws CameraAccessException 
    return CameraManagerGlobal.get().getCameraIdList();

CameraManagerGlobal::getCameraIdList

路径  frameworks/base/core/java/android/hardware/camera2/CameraManager.java

        这里面主要是获取到cameraService

        根据CameraManagermDeviceStatus里面的数据进行返回

        private final ArrayMap<String, Integer> mDeviceStatus = new ArrayMap<String, Integer>();

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<String, Integer> mDeviceStatus = new ArrayMap<String, Integer>();


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<ICameraServiceListener>& listener,
        /*out*/
        std::vector<hardware::CameraStatus> *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<String8, std::shared_ptr<CameraState>> mCameraStates;

std::vector<sp<hardware::ICameraServiceListener>> 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<String8> 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<CameraState>(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<CameraState> 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<std::string> 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<StatusInternal> 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<std::string> CameraProviderManager::getCameraDeviceIds() const 
    std::lock_guard<std::mutex> lock(mInterfaceMutex);
    std::vector<std::string> 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<sp<ProviderInfo>> mProviders;

//########################################################################
status_t CameraProviderManager::initialize(wp<CameraProviderManager::StatusListener> 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<StatusListener> mListener;

//########################################################################
//frameworks/av/services/camera/libcameraservice/common/CameraProviderManager.cpp
status_t CameraProviderManager::addProviderLocked(const std::string& newProvider, bool expected) 
    //...
    sp<ProviderInfo> 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博客

        也就是说代码会调用到CameraProvidergetCameraIdList

被动:这里注意ProviderInfo::initialize这里会调用setCallbackProviderInfo作为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;
    //...
    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> status = mInterface->setCallback(this);
    //...
    std::vector<std::string> devices;
    hardware::Return<void> ret = mInterface->getCameraIdList([&status, &devices](
            Status idStatus,
            const hardware::hidl_vec<hardware::hidl_string>& cameraDeviceNames) 
        status = idStatus;
        if (status == Status::OK) 
            for (size_t i = 0; i < cameraDeviceNames.size(); i++) 
                //将返回的设备填装到devices中
                devices.push_back(cameraDeviceNames[i]);
            
         );
    ...
 
    sp<StatusListener> 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<void> CameraProviderManager::ProviderInfo::cameraDeviceStatusChange(
        const hardware::hidl_string& cameraDeviceName,
        CameraDeviceStatus newStatus) 
    sp<StatusListener> listener;
    std::string id;
    bool initialized = false;
    
        std::lock_guard<std::mutex> 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<void> CameraProvider::getCameraIdList(getCameraIdList_cb _hidl_cb)  
    std::vector<hidl_string> deviceNameList;
    for (auto const& deviceNamePair : mCameraDeviceNames) 
        if (mCameraStatusMap[deviceNamePair.first] == CAMERA_DEVICE_STATUS_PRESENT) 
            deviceNameList.push_back(deviceNamePair.second);
        
    
    hidl_vec<hidl_string> hidlDeviceNameList(deviceNameList);
    _hidl_cb(Status::OK, hidlDeviceNameList);
    return Void();


//#####################################################################
//hardware/interfaces/camera/provider/2.4/default/CameraProvider.h
SortedVector<std::pair<std::string, std::string>> mCameraDeviceNames;

//#####################################################################
Return<Status> CameraProvider::setCallback(const sp<ICameraProviderCallback>& 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环节中会调用mCallbackscameraDeviceStatusChange进行回调,由于CameraProvider是继承自结构体camera_module_callbacks_t的,所以可以向so中提供sCameraDeviceStatusChange指针提其在挂载变动时调用。在sCameraDeviceStatusChange函数中会调用mCallbackscameraDeviceStatusChange进行回调流程。

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<CameraProvider*>(
            static_cast<const CameraProvider*>(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;

以上是关于Android Camera getCameraIdList流程 (android P)的主要内容,如果未能解决你的问题,请参考以下文章

android中的camera和camera2权限

问题支持Android相机的API和camera2 API问题,怎么解决

Android Camera2 拍照入门学习

android camera:camera模组CMM介绍

每次“Camera camera = Camera.open();”时,Android都会抛出错误叫做

Android Camera2 教程 · 第一章 · 概览