Camera HAL3的整体架构和流程(二)

前言

上一篇文章大概介绍了一下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()函数,限于篇幅,代码部分省略。
需要注意的是第19行ICameraService cameraService = CameraManagerGlobal.get().getCameraService();这里通过Binder获取了CameraService实例。再看第25行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();//19行
                    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()函数,需要注意第14行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(),需要注意的是第10行ret = makeClient(…, &tmp),tmp作为输出, 得到client后第22行调用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中,需要注意的是第22行 *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, …)函数,需要注意的是第15行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()函数,需要注意第14行,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()函数,需要注意第11行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()函数,需要注意的是第9行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()函数,需要注意的是第22行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()函数,需要注意的是第18行和19行,分别是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()函数,需要注意的是第4行auto pHalSensorList = MAKE_HalSensorList(); 其中MAKE_HalSensorList()在IHalSensor.h中定义。第17行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()函数,需要注意的是第18行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来防止弄混淆走错线,也可以关注我的微信公众号,里面会有Camera相关的学习记录,代码小技巧和技能分享。

在这里插入图片描述

  • 19
    点赞
  • 94
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值