Camera HAL3的整体架构和流程

本文详细解析了MTK平台上的openCamera流程,从Android框架CameraManager出发,经过CameraService、CameraDeviceClient等多个关键组件,深入到HAL层的CameraProviderImpl、CameraDevice3Impl等,直至硬件传感器驱动。涉及的主要文件和接口逐一剖析,展示了从framework到HAL层的整合过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Camera的整体架构

上图是Google官方的Camera架构,Google封装了HAL层接口:ICameraProvider, 
ICameraDevice, ICameraDeviceSession。

这几个接口的作用如下:

ICameraProvider:用于枚举单个设备并管理其状态。
ICameraDevice:相机设备接口。
ICameraDeviceSession:活跃的相机设备会话接口。
MTK HAL3结构主要实现了这几个接口, CameraProviderImpl实现了ICameraProvider接口,
CameraDevice3Impl实现了ICameraDevice接口,CameraDevice3SessionImpl实现了
ICameraDeviceSession接口。

Google 将相机子系统塑造为一个管道(pipeline),MTK实现了一个PipelineModelImpl来管理
pipeline。

本文详细地描述了从framework到HAL层open camera的整个过程。
open Camera流程
总结MTK平台open Camera的整个流程,忽略callback过程,以下是整个过程中设计到的文件路径:
文件名所在路径
CameraManager.javaframeworks/base/core/java/android/hardware/camera2/
CameraService.cppframeworks/av/services/camera/libcameraservice/
CameraDeviceClient.cppframeworks/av/services/camera/libcameraservice/api2/
Camera2ClientBase.cppframeworks/av/services/camera/libcameraservice/common/
Camera3Device.cppframeworks/av/services/camera/libcameraservice/device3/
CameraProviderManager.cppframeworks/av/services/camera/libcameraservice/common/
CameraDevice3Impl.cppmediatek/proprietary/hardware/mtkcam3/main/hal/device/3.x/device/
CameraDevice3SessionImpl.cppmediatek/proprietary/hardware/mtkcam3/main/hal/device/3.x/device/
PipelineModelImpl.cppmediatek/proprietary/hardware/mtkcam3/pipeline/model/
HalDeviceAdapter.cppmediatek/proprietary/hardware/mtkcam3/pipeline/model/adapter/
HalSensorList.openList.cppmediatek/proprietary/hardware/mtkcam/drv/src/sensor/common/v1/
HalSensor.cppmediatek/proprietary/hardware/mtkcam/drv/src/sensor/common/v1/
imgsensor_drv.cppmediatek/proprietary/hardware/mtkcam/drv/src/sensor/common/v1/
IHalSensor.h/mediatek/proprietary/hardware/mtkcam/include/mtkcam/drv/
 MTK 代码路径说明

下图是整个open camera的流程,可以结合下面的具体步骤一起看。

由Google的Camera框架可知open Camera从CameraManager.java开始(CameraDevice.java
负责发出capture命令,这里只讲open)

CameraManager.java
openCamera()==> openCameraForUid() ==>openCameraDeviceUserAsync()

直接看openCameraDeviceUserAsync()函数,限于篇幅,代码部分省略。
需要注意的是ICameraService cameraService = 
CameraManagerGlobal.get().getCameraService();这里通过Binder获取了CameraService实例。
再看cameraUser = cameraService.connectDevice。然后
deviceImpl.setRemoteDevice(cameraUser); device = deviceImpl; 最后return device。
由connectDevice往下,到CameraService::connectDevice(),从这里开始进入CameraService!

private CameraDevice openCameraDeviceUserAsync(String cameraId, 
CameraDevice.StateCallback callback, Executor executor, final int uid)throws 
CameraAccessException {
        CameraCharacteristics characteristics = 
getCameraCharacteristics(cameraId);
        CameraDevice device = null;
        
        synchronized (mLock) {
            ICameraDeviceUser cameraUser = null;
            android.hardware.camera2.impl.CameraDeviceImpl deviceImpl =
                    new android.hardware.camera2.impl.CameraDeviceImpl(
                        cameraId,
                        callback,
                        executor,
                        characteristics,
                        mContext.getApplicationInfo().targetSdkVersion);

            ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks();
            try {
                if (supportsCamera2ApiLocked(cameraId)) {
                    // Use cameraservice's cameradeviceclient implementation for 
HAL3.2+ devices
                    ICameraService cameraService = 
CameraManagerGlobal.get().getCameraService();
                    if (cameraService == null) {
                        throw new ServiceSpecificException(
                            ICameraService.ERROR_DISCONNECTED,
                            "Camera service is currently unavailable");
                    }
                    cameraUser = cameraService.connectDevice(callbacks, cameraId,
                            mContext.getOpPackageName(), uid);
                } else {
                    // Use legacy camera implementation for HAL1 devices
                    int id;
                    try {
                        id = Integer.parseInt(cameraId);
                    } catch (NumberFormatException e) {
                        throw new IllegalArgumentException("Expected cameraId to 
be numeric, but it was: "
                                + cameraId);
                    }

                    Log.i(TAG, "Using legacy camera HAL.");
                    cameraUser = CameraDeviceUserShim.connectBinderShim(callbacks,
 id,
                            getDisplaySize());
                }
            } 
            ...
                
            // TODO: factor out callback to be non-nested, then move setter to 
constructor
            // For now, calling setRemoteDevice will fire initial
            // onOpened/onUnconfigured callbacks.
            // This function call may post onDisconnected and throw 
CAMERA_DISCONNECTED if
            // cameraUser dies during setup.
            deviceImpl.setRemoteDevice(cameraUser);
            device = deviceImpl;
        }

        return device;
    }
CameraService.cpp
看connectDevice()函数,需要注意ret = connectHelper(…,client),
其最后一个参数client作为输出。
Status CameraService::connectDevice(
        const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb,
        const String16& cameraId,
        const String16& clientPackageName,
        int clientUid,
        /*out*/
        sp<hardware::camera2::ICameraDeviceUser>* device) {

    ATRACE_CALL();
    Status ret = Status::ok();
    String8 id = String8(cameraId);
    sp<CameraDeviceClient> client = nullptr;

    ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks,CameraDeviceClient>
(cameraCb, id,
            /*api1CameraId*/-1,
            CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName,
            clientUid, USE_CALLING_PID, API_2, /*shimUpdateOnly*/ false, 
/*out*/client);
    *device = client;
    return ret;
}
直接看connectHelper(),需要注意的是ret = makeClient(…, &tmp),tmp作为输出, 
得到client后调用client->initialize().那么这个client是谁的实例呢,沿着makeClient
函数跟下去。
Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const 
String8& cameraId,
        int api1CameraId, int halVersion, const String16& clientPackageName, 
int clientUid,
        int clientPid, apiLevel effectiveApiLevel, bool shimUpdateOnly,
        /*out*/sp<CLIENT>& device) {
    ...
    sp<CLIENT> client = nullptr;
    {
    ...
        sp<BasicClient> tmp = nullptr;
        if(!(ret = makeClient(this, cameraCb, clientPackageName,
                cameraId, api1CameraId, facing,
                clientPid, clientUid, getpid(),
                halVersion, deviceVersion, effectiveApiLevel,
                /*out*/&tmp)).isOk()) {
            return ret;
        }
        client = static_cast<CLIENT*>(tmp.get());

        LOG_ALWAYS_FATAL_IF(client.get() == nullptr, "%s: CameraService in 
invalid state",
                __FUNCTION__);
                
        err = client->initialize(mCameraProviderManager, mMonitorTags);
        if (err != OK) {
            ...
        }
        ...
    } // lock is destroyed, allow further connect calls
    // Important: release the mutex here so the client can call back into the 
service from its
    // destructor (can be at the end of the call)
    device = client;
    return ret;
}
makeClient函数也在CameraService.cpp中,需要注意的是 *client = new 
CameraDeviceClient,因为本文是HAL3+API2,所以走CameraDeviceClient构造函数.
Status CameraService::makeClient(const sp<CameraService>& cameraService,
        const sp<IInterface>& cameraCb, const String16& packageName, const 
String8& cameraId,
        int api1CameraId, int facing, int clientPid, uid_t clientUid, int 
servicePid,
        int halVersion, int deviceVersion, apiLevel effectiveApiLevel,
        /*out*/sp<BasicClient>* client) {
		...
          case CAMERA_DEVICE_API_VERSION_3_0:
          case CAMERA_DEVICE_API_VERSION_3_1:
          case CAMERA_DEVICE_API_VERSION_3_2:
          case CAMERA_DEVICE_API_VERSION_3_3:
          case CAMERA_DEVICE_API_VERSION_3_4:
          case CAMERA_DEVICE_API_VERSION_3_5:
            if (effectiveApiLevel == API_1) { // Camera1 API route
                sp<ICameraClient> tmp = static_cast<ICameraClient*>
(cameraCb.get());
                *client = new Camera2Client(cameraService, tmp, packageName,
                        cameraId, api1CameraId,
                        facing, clientPid, clientUid,
                        servicePid);
            } else { // Camera2 API route
                sp<hardware::camera2::ICameraDeviceCallbacks> tmp =
                        static_cast<hardware::camera2::ICameraDeviceCallbacks*>
(cameraCb.get());
                *client = new CameraDeviceClient(cameraService, tmp, packageName,
 cameraId,
                        facing, clientPid, clientUid, servicePid);
            }
            break;
          default:
            // Should not be reachable
            ALOGE("Unknown camera device HAL version: %d", deviceVersion);
            return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
                    "Camera device \"%s\" has unknown HAL version %d",
                    cameraId.string(), deviceVersion);
        }
    } 
    ...
    return Status::ok();
}
CameraDeviceClient.cpp
调用CameraDeviceClient的构造函数,其继承于Camera2ClientBase。
继续到Camera2ClientBase.cpp
CameraDeviceClient::CameraDeviceClient(...) : Camera2ClientBase(...),
    mInputStream(),
    mStreamingRequestId(REQUEST_ID_NONE),
    mRequestIdCounter(0) {

    ATRACE_CALL();
    ALOGI("CameraDeviceClient %s: Opened", cameraId.string());
}
Camera2ClientBase.cpp
调用Camera2ClientBase构造函数,可以看到其继承了mDevice(new Camera3Device),
Camera3Device正是我们需要的!
Camera2ClientBase<TClientBase>::Camera2ClientBase(...):
        ...
        mDevice(new Camera3Device(cameraId)),
        mDeviceActive(false), mApi1CameraId(api1CameraId)
{
    ALOGI("Camera %s: Opened. Client: %s (PID %d, UID %d)", cameraId.string(),
            String8(clientPackageName).string(), clientPid, clientUid);

    mInitialClientPid = clientPid;
    LOG_ALWAYS_FATAL_IF(mDevice == 0, "Device should never be NULL here.");
}
Camera3Device.cpp
最后调用了Camera3Device的构造方法,到这makeClient最后输出的client找到了!
它就是Camera3Device的实例!所以client->initialize等同于Camera3Device::initialize。

看initialize(sp <CameraProviderManager> manager, …)函数,需要注意的是res = 
manager->openSession(mId.string(), this,/*out*/ &session);其中输出是sp 
<ICameraDeviceSession> session。这里调用了CameraProviderManager::openSession
status_t Camera3Device::initialize(sp<CameraProviderManager> manager, 
const String8& monitorTags) {
    ATRACE_CALL();
    Mutex::Autolock il(mInterfaceLock);
    Mutex::Autolock l(mLock);

    ALOGV("%s: Initializing HIDL device for camera %s", __FUNCTION__, 
mId.string());
    if (mStatus != STATUS_UNINITIALIZED) {
        CLOGE("Already initialized!");
        return INVALID_OPERATION;
    }
    if (manager == nullptr) return INVALID_OPERATION;

    sp<ICameraDeviceSession> session;
    ATRACE_BEGIN("CameraHal::openSession");
    status_t res = manager->openSession(mId.string(), this,
            /*out*/ &session);
    ATRACE_END();
  ...
}
CameraProviderManager.cpp
看openSession()函数,需要注意,ret = interface->open(),
其中interface=deviceInfo3->startDeviceInterface,实际上是调用
CameraProviderManager::ProviderInfo::DeviceInfo3::startDeviceInterface,
这个函数最终会调用ICameraProvider接口的getCameraDeviceInterface_V3_x来
获取ICameraDevice的实例。从这就开始进入HAL层了!
status_t CameraProviderManager::openSession(const std::string &id,
        const sp<device::V3_2::ICameraDeviceCallback>& callback,
        /*out*/
        sp<device::V3_2::ICameraDeviceSession> *session) {
	...
    auto *deviceInfo3 = static_cast<ProviderInfo::DeviceInfo3*>(deviceInfo);
	...
    auto interface = deviceInfo3->startDeviceInterface<
            CameraProviderManager::ProviderInfo::DeviceInfo3::InterfaceT>();
    if (interface == nullptr) {
        return DEAD_OBJECT;
    }

    ret = interface->open(callback, [&status, &session]
            (Status s, const sp<device::V3_2::ICameraDeviceSession>& cameraSession) 
{
                status = s;
                if (status == Status::OK) {
                    *session = cameraSession;
                }
            });
    ...
    return mapToStatusT(status);
}
CameraDevice3Impl.cpp
前面说过CameraDevice3Impl.cpp是MTK对Google HAL接口ICameraDevice的实现,
所以上一步的interface->open, 实际上是CameraDevice3Impl::open

看open()函数,需要注意status = mSession->open,其中mSession在
CameraDevice3Impl.h中定义::android::sp <ICameraDevice3Session> mSession = nullptr;,
也就是调用了CameraDevice3Session::open
Return<void>
CameraDevice3Impl::
open(const ::android::sp<V3_2::ICameraDeviceCallback>& callback, open_cb _hidl_cb)
{
    int systraceLevel = ::property_get_int32("vendor.debug.mtkcam.systrace.level", 
MTKCAM_SYSTRACE_LEVEL_DEFAULT);
    MY_LOGI("open camera3 device (%s) systraceLevel(%d) instanceId(%d) vid(%d)",
                        mStaticDeviceInfo->mInstanceName.c_str(),
                        systraceLevel,
                        mStaticDeviceInfo->mInstanceId,
                        mStaticDeviceInfo->mVirtualInstanceId);
    ::android::status_t status = mSession-
>open(V3_5::ICameraDeviceCallback::castFrom(callback));
    if  ( ::android::OK != status ) {
        _hidl_cb(mapToHidlCameraStatus(status), nullptr);
    }
    else {
        _hidl_cb(mapToHidlCameraStatus(status), mSession);
    }

    return Void();
}
CameraDevice3SessionImpl.cpp
看open()函数,需要注意的是err = onOpenLocked(callback); onOpenLocked定义在
CameraDevice3SessionImpl.cpp
auto ThisNamespace::open(
    const ::android::sp<V3_5::ICameraDeviceCallback>& callback
) -> ::android::status_t
{
    ...
            //------------------------------------------------------------------
            int err = NO_INIT;
            status = tryRunCommandLocked(getWaitCommandTimeout(), "onOpenLocked", 
[&, this](){
                err = onOpenLocked(callback);
            });
            if ( status == OK ) {
                status = err;
       ...
    return status;
}
继续看onOpenLocked()函数,需要注意的是err = pPipelineModel->open();
也就是调用了PipelineModelImpl::open, 从这里开始进入pipeline!
auto ThisNamespace::onOpenLocked(
    const ::android::sp<V3_4::ICameraDeviceCallback>& callback
) -> ::android::status_t
{
    ...
    //--------------------------------------------------------------------------
    {
        Mutex::Autolock _l(mPipelineModelLock);
        auto pPipelineModelMgr = IPipelineModelManager::get();
        if  ( CC_UNLIKELY(pPipelineModelMgr == nullptr) ) {
            MY_LOGE("IPipelineModelManager::get() is null object!");
            return NO_INIT;
        }
        //
        auto pPipelineModel = pPipelineModelMgr->getPipelineModel( getInstanceId() 
);
        if ( CC_UNLIKELY(pPipelineModel == nullptr) ) {
            MY_LOGE("IPipelineModelManager::getPipelineModel(%d) is null object!", 
getInstanceId());
            return NO_INIT;
        }
        //
        ::android::status_t err = OK;
        err = pPipelineModel->open(getInstanceName().c_str(), this);
        if  ( CC_UNLIKELY(OK != err) ) {
            MY_LOGE( "fail to IPipelinemodel->open() status:%d(%s)", -err, 
::strerror(-err) );
            return NO_INIT;
        }
        mPipelineModel = pPipelineModel;
        mConfigTimestamp = (uint64_t)::systemTime();
        MY_LOGD("timestamp(%" PRIu64 ")", mConfigTimestamp);
    }
    //--------------------------------------------------------------------------
    return OK;
}
PipelineModelImpl.cpp
看open()函数,需要注意的是mHalDeviceAdapter->open(),
mHalDeviceAdapter->powerOn()。接下来看HalDeviceAdapter.cpp
auto PipelineModelImpl::open(
    std::string const& userName,
    android::wp<IPipelineModelCallback> const& callback
) -> int
{
    MY_LOGD1("+");
    //
    {
        std::lock_guard<std::timed_mutex> _l(mLock);

        mUserName = userName;
        mCallback = callback;

        mvOpenFutures.push_back(
            std::async(std::launch::async,
                [this]() {
                    return CC_LIKELY( mHalDeviceAdapter!=nullptr )
                        && CC_LIKELY( mHalDeviceAdapter->open() )
                        && CC_LIKELY( mHalDeviceAdapter->powerOn() );
                }
            )
        );
    }
    //
    MY_LOGD1("-");
    return OK;
}
HalDeviceAdapter.cpp
先看open()函数,需要注意的是auto pHalSensorList = MAKE_HalSensorList();
其中MAKE_HalSensorList()在IHalSensor.h中定义。auto pSensor = pHalSensorList-
>createSensor ,实际是调用了HalSensorList::createSensor(),这在
HalSensorList.openList.cpp中定义
virtual auto    open() -> bool override
                    {
                        CAM_TRACE_NAME("Sensor creation");
                        auto pHalSensorList = MAKE_HalSensorList();
                        if  ( CC_UNLIKELY(pHalSensorList == nullptr) ) {
                            MY_LOGE("Bad HalSensorList");
                            return false;
                        }

                        if ( CC_UNLIKELY(mvPhySensorId.size() == 0) ) {
                            MY_LOGE("No physical sensor");
                            return false;
                        }
                        //
                        bool ret = true;
                        for (size_t i = 0; i < mvPhySensorId.size(); i++) {
                            auto pSensor = pHalSensorList-
>createSensor(mName.c_str(), mvPhySensorId[i]);
                            mvHalSensor.push_back(pSensor);
                            if ( CC_UNLIKELY(pSensor == nullptr) ) {
                                ret = false;
                                MY_LOGE("Bad HalSensor - mvPhySensorId[%zu]=%d", 
i, mvPhySensorId[i]);
                            }
                        }

                        if  (CC_UNLIKELY(!ret)) {
                            MY_LOGE("Fail on open(). [TODO] let's clean up 
resources");
                        }
                        mIsOpen = ret;
                        return ret;
                    }

再看powerOn()函数,需要注意的是mvHalSensor[i]->powerOn,它调用
了HalSensor::powerOn。
virtual auto    powerOn() -> bool override
                    {
                        ...
                        // create thread to power on sensors
                        std::future<bool> future_initSensor =
                            std::async(std::launch::async,
                                [ this ]() {
                                    CAM_TRACE_NAME("Sensors powerOn");
                                    ::prctl(PR_SET_NAME, (unsigned 
long)"LogicalDevPoweron", 0, 0, 0);
                                    //
                                    for (size_t i = 0; i < mvPhySensorId.size(); 
i++)
                                    {
                                        MUINT const sensorIndex = 
mvPhySensorId[i];
                                        if (CC_UNLIKELY( mvHalSensor[i] == nullptr
 ))
                                        {
                                            return false;
                                        }
                                        if (CC_UNLIKELY( !mvHalSensor[i]-
>powerOn(mName.c_str(), 1, &sensorIndex) ))
                                        {
                                            #if (MTKCAM_HAVE_AEE_FEATURE == 1)
                                            aee_system_exception(
                                                LOG_TAG,
                                                NULL,
                                                DB_OPT_DEFAULT,
                                                android::String8::format(
                                                    "[%zu] sensorIndex:%d powerOn 
failed"
                                                    "\nCRDISPATCH_KEY:MtkCam/Cam1Device:Sensor power on failed"
                                                    , i, sensorIndex).c_str()
                                            );
                                            #endif
                                            return false;
                                        }
                                    }
                                    //
                                    return true;
                                }
                            );
                        // init 3A and poweron 3A
                        ...
                        return  ( success_init3A && success_sensorPowerOn );
                    }
HalSensorList.openList.cpp
由刚刚的pHalSensorList->createSensor函数可知,调用了
HalSensorList::createSensor()==>openSensor,直接看openSensor函数,
其中有一行pHalSensor = new HalSensor();

HalSensor.cpp
由上面步骤可知,mHalDeviceAdapter->open(),最终调用了HalSensor的构造函数,
mHalDeviceAdapter->powerOn()最终调用了HalSensor::powerOn()函数。
先看HalSensor的构造函数,它继承于IHalSensor,这定义在IHalSensor.h中。IHalSensor.h
里面包括了所有sensor的信息(包括sensor id,name,address等等)。

imgsensor_drv.cpp
上个步骤中HalSensor::powerOn会循环调用三次SenDrv->open,也就是ImgSensorDrv::open,
最终调用到ImgSensorDrv::featureControl
MINT32
ImgSensorDrv::open(IMGSENSOR_SENSOR_IDX sensorIdx)
{
    MUINT32                           featureParaLen = sizeof(MUINT32);
    MUINT32                           featurePara;

    return featureControl(sensorIdx, SENSOR_FEATURE_OPEN, (MUINT8 *)&featurePara, 
&featureParaLen);
}
看featureControl()函数
MINT32
ImgSensorDrv::featureControl(
    IMGSENSOR_SENSOR_IDX sensorIdx,
    ACDK_SENSOR_FEATURE_ENUM FeatureId,
    MUINT8 *pFeaturePara,
    MUINT32 *pFeatureParaLen
)
{
    ACDK_SENSOR_FEATURECONTROL_STRUCT featureCtrl;

    if (m_fdSensor == -1) {
        LOG_ERR("[sendCommand]m_fdSensor fail, sendCommand must be called after 
init()!");
        return SENSOR_UNKNOWN_ERROR;
    }

    if (pFeaturePara == NULL || pFeatureParaLen == NULL) {
        return SENSOR_INVALID_PARA;
    }

    featureCtrl.InvokeCamera = sensorIdx;
    featureCtrl.FeatureId = FeatureId;
    featureCtrl.pFeaturePara = pFeaturePara;
    featureCtrl.pFeatureParaLen = pFeatureParaLen;

    if (ioctl(m_fdSensor, KDIMGSENSORIOC_X_FEATURECONCTROL , &featureCtrl) < 0) {
        LOG_ERR("[featureControl] Err-ctrlCode (%s)", strerror(errno));
        return -errno;
    }
	...
    return SENSOR_NO_ERROR;
}//halSensorFeatureControl

最终调用ioctl函数进入kernel层!

总结
至此整个open Camera的流程已经通了,虽然中间忽略了非常多细节(比如很多callback,
创建Session等等等等),但是这篇文章只讨论open流程,要抓住事情的主要矛盾!要是同时跟很多
条线路,大脑内存会溢出的!

整个open流程涉及了14个文件,从framework到HAL的文件都有,如何从一个层到另外一个层的过程
很容易弄错,可以在代码中加一些自己的log来防止弄混淆走错线

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值