Android 8.1 MTK Camera(api1+hal1.0)源码框架分析之Camera open流程

之前已经写过一篇关于camera框架的文章,现在开始写camera相关的功能流程,总结一下常用的camera流程,算是对camera开发的一个回顾。

Android 8.1 MTK Camera(api1)源码框架分析

首先先看下camera open流程,基于mtk release代码,使用camera api1+hal1.0的组合。

1.应用层的open方式

api中定义的有两种open方式,分别是:

return Camera.open(cameraId);  //指定打开某一个摄像头

return Camera.open();  //默认打开后置摄像头

open函数的参数cameraID,表示要访问的是哪一个硬件摄像头:介于0和getNumberOfCameras()-1之间。

而mtk的release代码中,新增了一种open方式,增加了指定hal版本的参数:

//指定hal api版本以及指定打开某个摄像头,如果当前设备不支持指定的hal版本,则抛出RuntimeException。
return Camera.openLegacy(cameraId, halVersion);  

这三种方式实际都是去new Camera(),只是构造函数中的参数不一样。都返回Camera句柄。

2.Camera.java api中的open函数

frameworks/base/core/java/android/hardware/Camera.java 中的open函数定义:
方式一:

    public static Camera open(int cameraId) {
        return new Camera(cameraId);
    }

方式二:

    public static Camera open() {
        int numberOfCameras = getNumberOfCameras();
        CameraInfo cameraInfo = new CameraInfo();
        for (int i = 0; i < numberOfCameras; i++) {
            getCameraInfo(i, cameraInfo);
            //这里通过遍历到back camera时,就new Camera(i)
            if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
                return new Camera(i);
            }
        }
        return null;
    }

方式三:

    public static Camera openLegacy(int cameraId, int halVersion) {
        if (halVersion < CAMERA_HAL_API_VERSION_1_0) {
            throw new IllegalArgumentException("Invalid HAL version " + halVersion);
        }
        //new camera时,传入hal版本的参数
        return new Camera(cameraId, halVersion);
    }

三种方式都是去new Camera,所以看到Camera同名不同参的两个构造函数。
构造函数一:

    /** used by Camera#open, Camera#open(int) */
    Camera(int cameraId) {
        int err = cameraInitNormal(cameraId); //init
        if (checkInitErrors(err)) {
            if (err == -EACCES) {
                throw new RuntimeException("Fail to connect to camera service");
            } else if (err == -ENODEV) {
                throw new RuntimeException("Camera initialization failed");
            }
            // Should never hit this.
            throw new RuntimeException("Unknown camera error");
        }
    }

构造函数二:

    /**
     * Create a legacy camera object.
     *
     * @param cameraId The hardware camera to access, between 0 and
     * {@link #getNumberOfCameras()}-1.
     * @param halVersion The HAL API version this camera device to be opened as.
     */
    private Camera(int cameraId, int halVersion) {
        int err = cameraInitVersion(cameraId, halVersion);//init
        if (checkInitErrors(err)) {
            if (err == -EACCES) {
                throw new RuntimeException("Fail to connect to camera service");
            } else if (err == -ENODEV) {
                throw new RuntimeException("Camera initialization failed");
            } else if (err == -ENOSYS) {
                throw new RuntimeException("Camera initialization failed because some methods"
                        + " are not implemented");
            } else if (err == -EOPNOTSUPP) {
                throw new RuntimeException("Camera initialization failed because the hal"
                        + " version is not supported by this device");
            } else if (err == -EINVAL) {
                throw new RuntimeException("Camera initialization failed because the input"
                        + " arugments are invalid");
            } else if (err == -EBUSY) {
                throw new RuntimeException("Camera initialization failed because the camera"
                        + " device was already opened");
            } else if (err == -EUSERS) {
                throw new RuntimeException("Camera initialization failed because the max"
                        + " number of camera devices were already opened");
            }
            // Should never hit this.
            throw new RuntimeException("Unknown camera error");
        }
    }

构造函数中,都通过cameraInit函数的返回值来判断camera是否打开成功,如失败则抛出异常。真正的去执行open操作也是在cameraInit函数中调用jni函数native_setup。

-----cameraInitNormal中的参数指定为CAMERA_HAL_API_VERSION_NORMAL_CONNECT = -2;这个代表的是使用当前系统底层默认的hal版本。

    private int cameraInitNormal(int cameraId) {
        return cameraInitVersion(cameraId, CAMERA_HAL_API_VERSION_NORMAL_CONNECT);
    }

-----而cameraInitVersion中参数是由调用者设置的。一般设置CAMERA_HAL_API_VERSION_1_0 = 0x100; 表明Camera HAL device API version 1.0。

    private int cameraInitVersion(int cameraId, int halVersion) {
        mShutterCallback = null;
        mRawImageCallback = null;
        mJpegCallback = null;
        mPreviewCallback = null;
        mPostviewCallback = null;
        mUsingPreviewAllocation = false;
        mZoomListener = null;

        Looper looper;
        if ((looper = Looper.myLooper()) != null) {
            mEventHandler = new EventHandler(this, looper);
        } else if ((looper = Looper.getMainLooper()) != null) {
            mEventHandler = new EventHandler(this, looper);
        } else {
            mEventHandler = null;
        }

        return native_setup(new WeakReference<Camera>(this), cameraId, halVersion,
                ActivityThread.currentOpPackageName());
    }

3.JNI函数

根据jni函数命名规则,可找到native_setup函数所在文件目录:frameworks\base\core\jni\android_hardware_Camera.cpp。

native_setup()被动态注册到JNI,指向android_hardware_Camera_native_setup()方法。

static const JNINativeMethod camMethods[] = {
  ......
  { "native_setup",
    "(Ljava/lang/Object;IILjava/lang/String;)I",
    (void*)android_hardware_Camera_native_setup },
  ......

android_hardware_Camera_native_setup函数自带了两个原生参数JNIEnv *env, jobject thiz,而后面4个参数就是从camera.java中native_setup函数传下来的。

// connect to camera service
static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
    jobject weak_this, jint cameraId, jint halVersion, jstring clientPackageName)
{
    // Convert jstring to String16
    const char16_t *rawClientName = reinterpret_cast<const char16_t*>(
        env->GetStringChars(clientPackageName, NULL));
    jsize rawClientNameLen = env->GetStringLength(clientPackageName);
    String16 clientName(rawClientName, rawClientNameLen);
    env->ReleaseStringChars(clientPackageName,
                            reinterpret_cast<const jchar*>(rawClientName));

    //根据halVersion来决定走哪一个connect函数
    sp<Camera> camera; //这里是指向Camera.cpp/Camera.h
    if (halVersion == CAMERA_HAL_API_VERSION_NORMAL_CONNECT) {
        // Default path: hal version is don't care, do normal camera connect.
        camera = Camera::connect(cameraId, clientName,
                Camera::USE_CALLING_UID, Camera::USE_CALLING_PID);
    } else {
        jint status = Camera::connectLegacy(cameraId, halVersion, clientName,
                Camera::USE_CALLING_UID, camera);
        if (status != NO_ERROR) {
            return status;
        }
    }
    //判断camera的相关状态,返回相关error信息
    if (camera == NULL) {
        return -EACCES;
    }

    // make sure camera hardware is alive
    if (camera->getStatus() != NO_ERROR) {
        return NO_INIT;
    }

    jclass clazz = env->GetObjectClass(thiz);
    if (clazz == NULL) {
        // This should never happen
        jniThrowRuntimeException(env, "Can't find android/hardware/Camera");
        return INVALID_OPERATION;
    }
    ......
    return NO_ERROR;
}

通过将clientPackageName从jstring转换为String16格式得到clientName。
函数中根据halVersion来决定走哪一个connect函数,如是CAMERA_HAL_API_VERSION_NORMAL_CONNECT,则走的默认的;否则走指定的hal版本。
调用Camera::connect()/connectLegacy()方法去请求连接CameraService服务,这个camera指向的就是Camera.h/Camera.cpp了,有此进入到了camera client端。

4.Camera client

Camera.h头文件路径:\frameworks\av\camera\include\camera,函数声明:

    static  sp<Camera>  connect(int cameraId,
                                const String16& clientPackageName,
                                int clientUid, int clientPid);

    static  status_t  connectLegacy(int cameraId, int halVersion,
                                     const String16& clientPackageName,
                                     int clientUid, sp<Camera>& camera);

由于mtk在Android P之前hal层基本使用的hal1.0,所以这里就看connectLegacy函数。
在frameworks\av\camera\Camera.cpp文件中:

status_t Camera::connectLegacy(int cameraId, int halVersion,
        const String16& clientPackageName,
        int clientUid,
        sp<Camera>& camera)
{
    ALOGV("%s: connect legacy camera device", __FUNCTION__);
    sp<Camera> c = new Camera(cameraId); //拿到已经被打开的camera的,ICamera接口
    sp<::android::hardware::ICameraClient> cl = c; //拿到ICameraClient接口
    status_t status = NO_ERROR;
    //通过CameraBaseT::getCameraService()拿到ICameraService接口
    const sp<::android::hardware::ICameraService>& cs = CameraBaseT::getCameraService();

    binder::Status ret;
    if (cs != nullptr) {
        //这里cs.get是拿到CameraService,并调用connectLegacy,传入参数
        ret = cs.get()->connectLegacy(cl, cameraId, halVersion, clientPackageName,
                clientUid, /*out*/&(c->mCamera)); //c->mCamera指向的就是ICamera
    }
    if (ret.isOk() && c->mCamera != nullptr) {
        IInterface::asBinder(c->mCamera)->linkToDeath(c); //binder间通讯
        c->mStatus = NO_ERROR;
        camera = c;
    } else {
        switch(ret.serviceSpecificErrorCode()) {//遍历error code,赋值status
            case hardware::ICameraService::ERROR_DISCONNECTED:
                status = -ENODEV;
                break;
            case hardware::ICameraService::ERROR_CAMERA_IN_USE:
                status = -EBUSY;
                break;
            case hardware::ICameraService::ERROR_INVALID_OPERATION:
                status = -EINVAL;
                break;
            case hardware::ICameraService::ERROR_MAX_CAMERAS_IN_USE:
                status = -EUSERS;
                break;
            case hardware::ICameraService::ERROR_ILLEGAL_ARGUMENT:
                status = BAD_VALUE;
                break;
            case hardware::ICameraService::ERROR_DEPRECATED_HAL:
                status = -EOPNOTSUPP;
                break;
            case hardware::ICameraService::ERROR_DISABLED:
                status = -EACCES;
                break;
            case hardware::ICameraService::ERROR_PERMISSION_DENIED:
                status = PERMISSION_DENIED;
                break;
            default:
                status = -EINVAL;
                ALOGW("An error occurred while connecting to camera %d: %s", cameraId,
                        (cs != nullptr) ? "Service not available" : ret.toString8().string());
                break;
        }
        c.clear();
    }
    return status;
}

connectLegacy函数中,先是拿到已经被打开的camera的ICamera接口,再获取ICameraClient接口,通过CameraBaseT::getCameraService()再拿到ICameraService接口,通过cs.get是拿到CameraService,并调用connectLegacy,传入ICameraClient cl、ICamera /out/&(c->mCamera)等参数。

CameraBaseT是CameraBase的模板类,CameraBaseT是定义在CameraBase.h中的变量。

 typedef CameraBase<TCam>         CameraBaseT;

所以可以在CameraBase.cpp中看下CameraBaseT::getCameraService()函数,通过binder方式拿到ICameraService。

// establish binder interface to camera service
template <typename TCam, typename TCamTraits>
const sp<::android::hardware::ICameraService> CameraBase<TCam, TCamTraits>::getCameraService()
{
    Mutex::Autolock _l(gLock);
    if (gCameraService.get() == 0) {
        char value[PROPERTY_VALUE_MAX];
        property_get("config.disable_cameraservice", value, "0");
        if (strncmp(value, "0", 2) != 0 && strncasecmp(value, "false", 6) != 0) {
            return gCameraService;
        }

        sp<IServiceManager> sm = defaultServiceManager();
        sp<IBinder> binder;
        do {
            binder = sm->getService(String16(kCameraServiceName));
            if (binder != 0) {
                break;
            }
            ALOGW("CameraService not published, waiting...");
            usleep(kCameraServicePollDelay);
        } while(true);
        if (gDeathNotifier == NULL) {
            gDeathNotifier = new DeathNotifier();
        }
        binder->linkToDeath(gDeathNotifier);
        gCameraService = interface_cast<::android::hardware::ICameraService>(binder);
    }
    ALOGE_IF(gCameraService == 0, "no CameraService!?");
    return gCameraService;
}

5.Camera service

文件路径:frameworks\av\services\camera\libcameraservice。
cs.get()->connectLegacy指向到CameraSerive中,看到CameraService.h头文件中声明:

    virtual binder::Status     connectLegacy(const sp<hardware::ICameraClient>& cameraClient,
            int32_t cameraId, int32_t halVersion,
            const String16& clientPackageName, int32_t clientUid,
            /*out*/
            sp<hardware::ICamera>* device);

到具体的实现,在CameraService.cpp中:

Status CameraService::connectLegacy(
        const sp<ICameraClient>& cameraClient,
        int cameraId, int halVersion,
        const String16& clientPackageName,
        int clientUid,
        /*out*/
        sp<ICamera>* device) {

    ATRACE_CALL();
    String8 id = String8::format("%d", cameraId);

    Status ret = Status::ok();
    sp<Client> client = nullptr;
    //调用封装的函数connectHelper,默认指定API_1
    ret = connectHelper<ICameraClient,Client>(cameraClient, id, halVersion,
            clientPackageName, clientUid, USE_CALLING_PID, API_1,
            /*legacyMode*/ true, /*shimUpdateOnly*/ false,
            /*out*/client);

    if(!ret.isOk()) {
        logRejected(id, getCallingPid(), String8(clientPackageName),
                ret.toString8());
        return ret;
    }

    *device = client;
    return ret;
}

封装的函数connectHelper:

template<class CALLBACK, class CLIENT>
Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
        int halVersion, const String16& clientPackageName, int clientUid, int clientPid,
        apiLevel effectiveApiLevel, bool legacyMode, bool shimUpdateOnly,
        /*out*/sp<CLIENT>& device) {
    binder::Status ret = binder::Status::ok();

    String8 clientName8(clientPackageName);//将string16转换为String8
    int originalClientPid = 0;

    ALOGI("CameraService::connect call (PID %d \"%s\", camera ID %s) for HAL version %s and "
            "Camera API version %d", clientPid, clientName8.string(), cameraId.string(),
            (halVersion == -1) ? "default" : std::to_string(halVersion).c_str(),
            static_cast<int>(effectiveApiLevel)); //打印连接信息

    sp<CLIENT> client = nullptr;
    {
        ......
        sp<BasicClient> tmp = nullptr;
        if(!(ret = makeClient(this, cameraCb, clientPackageName, cameraId, facing, clientPid,
                clientUid, getpid(), legacyMode, halVersion, deviceVersion, effectiveApiLevel,
                /*out*/&tmp)).isOk()) { //调用makeClient去拿到Client
            return ret;
        }
        client = static_cast<CLIENT*>(tmp.get());

        LOG_ALWAYS_FATAL_IF(client.get() == nullptr, "%s: CameraService in invalid state",
                __FUNCTION__);
                
        //调用client->initialize去初始化CameraClient
        err = client->initialize(mCameraProviderManager);
        if (err != OK) { //error信息判断
            ALOGE("%s: Could not initialize client from HAL.", __FUNCTION__);
            // Errors could be from the HAL module open call or from AppOpsManager
            switch(err) {
                case BAD_VALUE:
                    return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
                            "Illegal argument to HAL module for camera \"%s\"", cameraId.string());
                ......
                default:
                    return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
                            "Failed to initialize camera \"%s\": %s (%d)", cameraId.string(),
                            strerror(-err), err);
            }
        }
        ......
    } // 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去拿到Client,并调用client->initialize去初始化CameraClient。
BaseClient声明在CameraService.h头文件中的类:

 class BasicClient : public virtual RefBase {

再看makeClient函数,通过判断hal版本,走不同的client创建,如判断走api1,new CameraClient返回给sp BasicClient* client,connectHelper中拿到了new CameraClient的返回值后,通过该返回值来调用init函数,也就是上面说到的client->initialize。

Status CameraService::makeClient(const sp<CameraService>& cameraService,
        const sp<IInterface>& cameraCb, const String16& packageName, const String8& cameraId,
        int facing, int clientPid, uid_t clientUid, int servicePid, bool legacyMode,
        int halVersion, int deviceVersion, apiLevel effectiveApiLevel,
        /*out*/sp<BasicClient>* client) {

    if (halVersion < 0 || halVersion == deviceVersion) {
        // Default path: HAL version is unspecified by caller, create CameraClient
        // based on device version reported by the HAL.
        switch(deviceVersion) { //判断hal版本,走不同的client创建
          case CAMERA_DEVICE_API_VERSION_1_0:
            if (effectiveApiLevel == API_1) {  // Camera1 API route
                //判断走api1,new CameraClient返回给sp<BasicClient>* client
                sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
                *client = new CameraClient(cameraService, tmp, packageName, cameraIdToInt(cameraId),
                        facing, clientPid, clientUid, getpid(), legacyMode);
            } else { // Camera2 API route
                ALOGW("Camera using old HAL version: %d", deviceVersion);
                return STATUS_ERROR_FMT(ERROR_DEPRECATED_HAL,
                        "Camera device \"%s\" HAL version %d does not support camera2 API",
                        cameraId.string(), deviceVersion);
            }
            break;
          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:
            if (effectiveApiLevel == API_1) { // Camera1 API route
                sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
                *client = new Camera2Client(cameraService, tmp, packageName, cameraIdToInt(cameraId),
                        facing, clientPid, clientUid, servicePid, legacyMode);
            } 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);
        }
    } else {
        ......
    }
    return Status::ok();
}

makeClient函数中new CameraClient,CameraClient文件路径在:frameworks\av\services\camera\libcameraservice\api1
CameraClient.cpp构造:

CameraClient::CameraClient(const sp<CameraService>& cameraService,
        const sp<hardware::ICameraClient>& cameraClient,
        const String16& clientPackageName,
        int cameraId, int cameraFacing,
        int clientPid, int clientUid,
        int servicePid, bool legacyMode):
        Client(cameraService, cameraClient, clientPackageName,
                String8::format("%d", cameraId), cameraFacing, clientPid,
                clientUid, servicePid)
{
    int callingPid = getCallingPid();
    LOG1("CameraClient::CameraClient E (pid %d, id %d)", callingPid, cameraId);

    mHardware = NULL;
    mMsgEnabled = 0;
    mSurface = 0;
    mPreviewWindow = 0;
    mDestructionStarted = false;

    // Callback is disabled by default
    mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP;
    mOrientation = getOrientation(0, mCameraFacing == CAMERA_FACING_FRONT);
    mLegacyMode = legacyMode;
    mPlayShutterSound = true;
    LOG1("CameraClient::CameraClient X (pid %d, id %d)", callingPid, cameraId);
}

再看connectHelper中client->initialize:

status_t CameraClient::initialize(sp<CameraProviderManager> manager) {
    int callingPid = getCallingPid();
    status_t res;

    LOG1("CameraClient::initialize E (pid %d, id %d)", callingPid, mCameraId);

    // Verify ops permissions
    res = startCameraOps();
    if (res != OK) {
        return res;
    }

    //通过传入的cameraId来获取将要指定打开的camera设备名称
    char camera_device_name[10];
    snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId);
    
    //创建一个Camera硬件接口对象
    mHardware = new CameraHardwareInterface(camera_device_name);
    //调用mHardware->initialize底层硬件初始化函数
    res = mHardware->initialize(manager);
    if (res != OK) {
        ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
                __FUNCTION__, mCameraId, strerror(-res), res);
        mHardware.clear();
        return res;
    }
    //将cameraservice中的消息回调、数据回调等回调注册到hal层
    mHardware->setCallbacks(notifyCallback,
            dataCallback,
            dataCallbackTimestamp,
            handleCallbackTimestampBatch,
            (void *)(uintptr_t)mCameraId);
    ......
    LOG1("CameraClient::initialize X (pid %d, id %d)", callingPid, mCameraId);
    return OK;
}

CameraClient中的init函数主要是通过传入的cameraId来获取将要指定打开的camera设备名称,再通过设备名称创建一个Camera硬件接口对象,调用mHardware->initialize去实现底层硬件初始化,再将cameraservice中的消息回调、数据回调等回调注册到hal层,方便hal层与cameraService及时通信。
到这里基本就调用到了CameraHardwareInterface中,也就是调用到CameraHardwareInterface.h通往hal的接口。

6.camera硬件接口CameraHardwareInterface.h

文件路径:\frameworks\av\services\camera\libcameraservice\device1
CameraHardwareInterface.h头文件声明:

    ......
    status_t initialize(sp<CameraProviderManager> manager);

    /** Set the notification and data callbacks */
    void setCallbacks(notify_callback notify_cb,
                      data_callback data_cb,
                      data_callback_timestamp data_cb_timestamp,
                      data_callback_timestamp_batch data_cb_timestamp_batch,
                      void* user);
    ......

CameraHardwareInterface.cpp实现:

status_t CameraHardwareInterface::initialize(sp<CameraProviderManager> manager) {
    ALOGI("Opening camera %s", mName.string());

    status_t ret = manager->openSession(mName.string(), this, &mHidlDevice);
    if (ret != OK) {
        ALOGE("%s: openSession failed! %s (%d)", __FUNCTION__, strerror(-ret), ret);
    }
    return ret;
}

可以看到initialize函数中,主要就是调用了CameraProviderManager.cpp的openSession函数。CameraProviderManager manager是有cameraService.cpp中的connect中传过来的参数。
文件路径:\frameworks\av\services\camera\libcameraservice\common\CameraProviderManager.cpp。

由于hal版本可能不一致,所以openSession的参数也区分了,主要是device的不同:
函数一:

status_t CameraProviderManager::openSession(const std::string &id,
        const sp<hardware::camera::device::V3_2::ICameraDeviceCallback>& callback,
        /*out*/
        sp<hardware::camera::device::V3_2::ICameraDeviceSession> *session) {

函数二:

status_t CameraProviderManager::openSession(const std::string &id,
        const sp<hardware::camera::device::V1_0::ICameraDeviceCallback>& callback,
        /*out*/
        sp<hardware::camera::device::V1_0::ICameraDevice> *session) {

这里就看函数二。

status_t CameraProviderManager::openSession(const std::string &id,
        const sp<hardware::camera::device::V1_0::ICameraDeviceCallback>& callback,
        /*out*/
        sp<hardware::camera::device::V1_0::ICameraDevice> *session) {

    std::lock_guard<std::mutex> lock(mInterfaceMutex);

    //获取设备信息
    auto deviceInfo = findDeviceInfoLocked(id,
            /*minVersion*/ {1,0}, /*maxVersion*/ {2,0});
    if (deviceInfo == nullptr) return NAME_NOT_FOUND;

    auto *deviceInfo1 = static_cast<ProviderInfo::DeviceInfo1*>(deviceInfo);

    //调用hal设备节点接口去open函数,并将callback传下去
    hardware::Return<Status> status = deviceInfo1->mInterface->open(callback);
    if (!status.isOk()) {
        ALOGE("%s: Transaction error opening a session for camera device %s: %s",
                __FUNCTION__, id.c_str(), status.description().c_str());
        return DEAD_OBJECT;
    }
    if (status == Status::OK) {
        *session = deviceInfo1->mInterface;
    }
    return mapToStatusT(status);
}

openSession主要就是调用底层camera设备节点接口去open函数,并将service注册的callback传下去。这样hal层和service层就能通过回调,接收相关消息,再来通知client端。

而deviceInfo的获取,是通过findDeviceInfoLocked函数,里面是遍历了mProviders。

CameraProviderManager::ProviderInfo::DeviceInfo* CameraProviderManager::findDeviceInfoLocked(
        const std::string& id,
        hardware::hidl_version minVersion, hardware::hidl_version maxVersion) const {
    for (auto& provider : mProviders) {
        for (auto& deviceInfo : provider->mDevices) {
            if (deviceInfo->mId == id &&
                    minVersion <= deviceInfo->mVersion && maxVersion >= deviceInfo->mVersion) {
                return deviceInfo.get();
            }
        }
    }
    return nullptr;
}

mProviders的生成是在CameraService被初始化启动的时候,再CameraProviderManager初始化逻辑中,通过调用addProviderLocked函数生成具体的DeviceInfo对象,再添加到mProviders成员变量中。可以看下函数:

status_t CameraProviderManager::addProviderLocked(const std::string& newProvider, bool expected) {
    for (const auto& providerInfo : mProviders) {
        if (providerInfo->mProviderName == newProvider) {
            ALOGW("%s: Camera provider HAL with name '%s' already registered", __FUNCTION__,
                    newProvider.c_str());
            return ALREADY_EXISTS;
        }
    }

    sp<provider::V2_4::ICameraProvider> interface;
    interface = mServiceProxy->getService(newProvider);

    if (interface == nullptr) {
        if (expected) {
            ALOGE("%s: Camera provider HAL '%s' is not actually available", __FUNCTION__,
                    newProvider.c_str());
            return BAD_VALUE;
        } else {
            return OK;
        }
    }

    sp<ProviderInfo> providerInfo =
            new ProviderInfo(newProvider, interface, this);
    status_t res = providerInfo->initialize();
    if (res != OK) {
        return res;
    }

    mProviders.push_back(providerInfo);

    return OK;
}

回到openSession方法,deviceInfo1->mInterface->open,mInterface就是在构造ProviderInfo时获取到的binder对象。实际是\hardware\interfaces\camera\device\1.0\default\CameraDevice.cpp对象。这里接着往下走,就又是binder进程间通信机制了。
\hardware\interfaces\camera\device里面有1.0、3.2、3.3等多个文件,具体哪一个就看openSession函数的第二个、第三参数了。

7. hardware层

在看\hardware\interfaces\camera\device\1.0\default\CameraDevice.cpp对象,这里实际已经调用到hardware层了,看open方法源码:

Return<Status> CameraDevice::open(const sp<ICameraDeviceCallback>& callback) {
    ALOGI("Opening camera %s", mCameraId.c_str());
    Mutex::Autolock _l(mLock);

    camera_info info;
    status_t res = mModule->getCameraInfo(mCameraIdInt, &info);
    if (res != OK) {
        ALOGE("Could not get camera info: %s: %d", mCameraId.c_str(), res);
        return getHidlStatus(res);
    }

    int rc = OK;
    if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_3 &&
        info.device_version > CAMERA_DEVICE_API_VERSION_1_0) {
        // Open higher version camera device as HAL1.0 device.
        rc = mModule->openLegacy(mCameraId.c_str(),
                                 CAMERA_DEVICE_API_VERSION_1_0,
                                 (hw_device_t **)&mDevice);
    } else { //调用mModule->open,传入hw_device_t 
        rc = mModule->open(mCameraId.c_str(), (hw_device_t **)&mDevice);
    }
    if (rc != OK) {
        mDevice = nullptr;
        ALOGE("Could not open camera %s: %d", mCameraId.c_str(), rc);
        return getHidlStatus(rc);
    }

    initHalPreviewWindow(); //初始化预览窗口
    mDeviceCallback = callback;

    if (mDevice->ops->set_callbacks) {//设置callback给device
        mDevice->ops->set_callbacks(mDevice,
                sNotifyCb, sDataCb, sDataCbTimestamp, sGetMemory, this);
    }

    return getHidlStatus(rc);
}

该open函数中rc = mModule->open(mCameraId.c_str(), (hw_device_t **)&mDevice);是实际来操作打开相机的。mModule是CameraDevice::CameraDevice构造中初始化的。再看CameraDevice::CameraDevice类的实例化,找到了位置是在\hardware\interfaces\camera\provider\2.4\default\CameraProvider.cpp,看到这个文件里面函数CameraProvider::getCameraDeviceInterface_V1_x,这个从名称看出来是针对api1 + hal1.0的,当然还有另一个函数是getCameraDeviceInterface_V3_x针对hal3.0的。

Return<void> CameraProvider::getCameraDeviceInterface_V1_x(
        const hidl_string& cameraDeviceName, getCameraDeviceInterface_V1_x_cb _hidl_cb)  {
    std::string cameraId, deviceVersion;
    bool match = matchDeviceName(cameraDeviceName, &deviceVersion, &cameraId);
    if (!match) {
        _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
        return Void();
    }

    std::string deviceName(cameraDeviceName.c_str());
    ssize_t index = mCameraDeviceNames.indexOf(std::make_pair(cameraId, deviceName));
    if (index == NAME_NOT_FOUND) { // Either an illegal name or a device version mismatch
        Status status = Status::OK;
        ssize_t idx = mCameraIds.indexOf(cameraId);
        if (idx == NAME_NOT_FOUND) {
            ALOGE("%s: cannot find camera %s!", __FUNCTION__, cameraId.c_str());
            status = Status::ILLEGAL_ARGUMENT;
        } else { // invalid version
            ALOGE("%s: camera device %s does not support version %s!",
                    __FUNCTION__, cameraId.c_str(), deviceVersion.c_str());
            status = Status::OPERATION_NOT_SUPPORTED;
        }
        _hidl_cb(status, nullptr);
        return Void();
    }

    if (mCameraStatusMap.count(cameraId) == 0 ||
            mCameraStatusMap[cameraId] != CAMERA_DEVICE_STATUS_PRESENT) {
        _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
        return Void();
    }
    //实例化CameraDevice,传入了这个CameraModule对象mModule
    sp<android::hardware::camera::device::V1_0::implementation::CameraDevice> device =
            new android::hardware::camera::device::V1_0::implementation::CameraDevice(
                    mModule, cameraId, mCameraDeviceNames);

    if (device == nullptr) {
        ALOGE("%s: cannot allocate camera device for id %s", __FUNCTION__, cameraId.c_str());
        _hidl_cb(Status::INTERNAL_ERROR, nullptr);
        return Void();
    }

    if (device->isInitFailed()) {
        ALOGE("%s: camera device %s init failed!", __FUNCTION__, cameraId.c_str());
        device = nullptr;
        _hidl_cb(Status::INTERNAL_ERROR, nullptr);
        return Void();
    }

    _hidl_cb (Status::OK, device);
    return Void();
}

这个函数中实例化了CameraDevice,传入了这个CameraModule的对象mModule。mModule定义在了头文件\hardware\interfaces\camera\provider\2.4\default中。

using ::android::hardware::camera::common::V1_0::helper::CameraModule;
......
sp<CameraModule> mModule;

CameraModule的对象mModule,在CameraProvider.cpp中initialize()函数进行init:

bool CameraProvider::initialize() {
    camera_module_t *rawModule;
    int err = hw_get_module(CAMERA_HARDWARE_MODULE_ID,
            (const hw_module_t **)&rawModule);
    if (err < 0) {
        ALOGE("Could not load camera HAL module: %d (%s)", err, strerror(-err));
        return true;
    }

    mModule = new CameraModule(rawModule);
    err = mModule->init();
    if (err != OK) {
        ALOGE("Could not initialize camera HAL module: %d (%s)", err, strerror(-err));
        mModule.clear();
        return true;
    }
    ALOGI("Loaded \"%s\" camera module", mModule->getModuleName());
    ......

之前在\hardware\interfaces\camera\device\1.0\default\CameraDevice.cpp中,open函数中rc = mModule->open(mCameraId.c_str(), (hw_device_t **)&mDevice);,实际是调用到CameraModule.open函数。所以接着去看CameraModule.cpp文件,路径hardware\interfaces\camera\common\1.0\default\CameraModule.cpp。也是定义了open和openLegacy函数两套。核心都是使用mModul->common。只不过open函数是通过mModule->common.methods->open方式,而openLegacy是通过mModule->open_legacy方式。这里就看mModule->open_legacy函数。

int CameraModule::open(const char* id, struct hw_device_t** device) {
    int res;
    ATRACE_BEGIN("camera_module->open");
    res = filterOpenErrorCode(mModule->common.methods->open(&mModule->common, id, device));
    ATRACE_END();
    return res;
}
int CameraModule::openLegacy(
        const char* id, uint32_t halVersion, struct hw_device_t** device) {
    int res;
    ATRACE_BEGIN("camera_module->open_legacy");
    res = mModule->open_legacy(&mModule->common, id, halVersion, device);
    ATRACE_END();
    return res;
}

mModule是在构造中获得的。

CameraModule::CameraModule(camera_module_t *module) {
    if (module == NULL) {
        ALOGE("%s: camera hardware module must not be null", __FUNCTION__);
        assert(0);
    }
    mModule = module;
}

而CameraModule的实例化是在CameraProvider::initialize()中进行的,之前已经贴过源码了。

bool CameraProvider::initialize() {
    camera_module_t *rawModule;
    int err = hw_get_module(CAMERA_HARDWARE_MODULE_ID,
            (const hw_module_t **)&rawModule);
    if (err < 0) {
        ALOGE("Could not load camera HAL module: %d (%s)", err, strerror(-err));
        return true;
    }

    mModule = new CameraModule(rawModule); 

实例化mModule = new CameraModule(rawModule); ,传入的camera_module_t *rawModule参数。rawModule参数通过函数hw_get_module(CAMERA_HARDWARE_MODULE_ID,(const hw_module_t **)&rawModule)来进行获取。所以之前mModule->open_legacy,也就是调用到rawModule->open_legacy。CAMERA_HARDWARE_MODULE_ID是指的hal层定义的module,hw_get_module就是通过module来获得camera模块,在通过获得的这个模块去调用hal层数。hw_get_module获取具体的module就与产商或设备有关系了。rawModule的类型是camera_module_t,所以也就是会通过camera_module_t这个结构体的open_legacy函数来执行open操作。hw_module_t也是一个结构体,在接着往下走,就要看hw_module_t和camera_module_t结构体的具体定义了。

搜索发现hw_get_module定义在hardware\libhardware\hardware.c中:

int hw_get_module(const char *id, const struct hw_module_t **module)
{
    return hw_get_module_by_class(id, NULL, module);
}
int hw_get_module_by_class(const char *class_id, const char *inst,
                           const struct hw_module_t **module)
{
    int i = 0;
    char prop[PATH_MAX] = {0};
    char path[PATH_MAX] = {0};
    char name[PATH_MAX] = {0};
    char prop_name[PATH_MAX] = {0};


    if (inst)
        snprintf(name, PATH_MAX, "%s.%s", class_id, inst);
    else
        strlcpy(name, class_id, PATH_MAX);

    /*
     * Here we rely on the fact that calling dlopen multiple times on
     * the same .so will simply increment a refcount (and not load
     * a new copy of the library).
     * We also assume that dlopen() is thread-safe.
     */

    /* First try a property specific to the class and possibly instance */
    snprintf(prop_name, sizeof(prop_name), "ro.hardware.%s", name);
    if (property_get(prop_name, prop, NULL) > 0) {
        if (hw_module_exists(path, sizeof(path), name, prop) == 0) {
            goto found;
        }
    }

    /* Loop through the configuration variants looking for a module */
    for (i=0 ; i<HAL_VARIANT_KEYS_COUNT; i++) {
        if (property_get(variant_keys[i], prop, NULL) == 0) {
            continue;
        }
        if (hw_module_exists(path, sizeof(path), name, prop) == 0) {
            goto found;
        }
    }

    /* Nothing found, try the default */
    if (hw_module_exists(path, sizeof(path), name, "default") == 0) {
        goto found;
    }

    return -ENOENT;

found:
    /* load the module, if this fails, we're doomed, and we should not try
     * to load a different variant. */
    return load(class_id, path, module);
}

再在device中搜索camera_module_t结构体,结果如下,基本在device/huawei、device/google、device/generic、device/lge几个目录中,这几个目录是源码中提供的几个厂商的实现。

device/huawei/angler/camera/QCamera2/QCamera2Factory.cpp: *   @halVersion: Based on camera_module_t.common.module_api_version
device/huawei/angler/camera/QCamera2/QCamera2Factory.cpp: *   @halVersion: Based on camera_module_t.common.module_api_version
device/huawei/angler/camera/QCamera2/QCamera2Factory.h:extern camera_module_t HAL_MODULE_INFO_SYM;
device/huawei/angler/camera/QCamera2/QCamera2Hal.cpp:camera_module_t HAL_MODULE_INFO_SYM = {
device/google/marlin/camera/QCamera2/QCamera2Factory.cpp: *   @halVersion: Based on camera_module_t.common.module_api_version
device/google/marlin/camera/QCamera2/QCamera2Factory.cpp: *   @halVersion: Based on camera_module_t.common.module_api_version
device/google/marlin/camera/QCamera2/QCamera2Factory.h:extern camera_module_t HAL_MODULE_INFO_SYM;
device/google/marlin/camera/QCamera2/QCamera2Hal.cpp:camera_module_t HAL_MODULE_INFO_SYM = {
device/generic/goldfish/camera/EmulatedBaseCamera.h: * are common across all versions of the camera_device_t/camera_module_t
device/generic/goldfish/camera/EmulatedBaseCamera.h:     * This method is called in response to camera_module_t::get_camera_info
device/generic/goldfish/camera/EmulatedCameraFactory.h: *  - camera_module_t::get_number_of_cameras entry point
device/generic/goldfish/camera/EmulatedCameraFactory.h: *  - camera_module_t::get_camera_info entry point
device/generic/goldfish/camera/EmulatedCameraFactory.h:     * This method is called in response to camera_module_t::get_camera_info callback.
device/generic/goldfish/camera/EmulatedCameraFactory.h:     * This method is called in response to camera_module_t::set_callbacks callback.
device/generic/goldfish/camera/EmulatedCameraFactory.h:     * This method is called in response to camera_module_t::get_vendor_tag_ops callback.
device/generic/goldfish/camera/EmulatedCameraFactory.h:    /* camera_module_t::get_number_of_cameras callback entry point. */
device/generic/goldfish/camera/EmulatedCameraFactory.h:    /* camera_module_t::get_camera_info callback entry point. */
device/generic/goldfish/camera/EmulatedCameraFactory.h:    /* camera_module_t::set_callbacks callback entry point. */
device/generic/goldfish/camera/EmulatedCameraFactory.h:    /* camera_module_t::get_vendor_tag_ops callback entry point */
device/generic/goldfish/camera/EmulatedCameraFactory.h:    /* camera_module_t::open_legacy callback entry point */
device/generic/goldfish/camera/EmulatedCameraFactory.cpp:extern camera_module_t HAL_MODULE_INFO_SYM;
device/generic/goldfish/camera/EmulatedBaseCamera.cpp: * camera_device_t/camera_module_t structures.
device/generic/goldfish/camera/EmulatedCameraHal.cpp:camera_module_t HAL_MODULE_INFO_SYM = {
device/lge/bullhead/camera/QCamera2/QCamera2Factory.cpp: *   @halVersion: Based on camera_module_t.common.module_api_version
device/lge/bullhead/camera/QCamera2/QCamera2Factory.cpp: *   @halVersion: Based on camera_module_t.common.module_api_version
device/lge/bullhead/camera/QCamera2/QCamera2Factory.h:extern camera_module_t HAL_MODULE_INFO_SYM;
device/lge/bullhead/camera/QCamera2/QCamera2Hal.cpp:camera_module_t HAL_MODULE_INFO_SYM = {

这里就看一下device/google/marlin/camera/QCamera2/QCamera2Hal.cpp文件源码,定义了open_legacy和set_callbacks等函数、定义了hw_module_t 和camera_module_t 结构体。

// Camera dependencies
#include "QCamera2Factory.h"
#include "HAL3/QCamera3VendorTags.h"

static hw_module_t camera_common = {
    .tag                    = HARDWARE_MODULE_TAG,
    .module_api_version     = CAMERA_MODULE_API_VERSION_2_4,
    .hal_api_version        = HARDWARE_HAL_API_VERSION,
    .id                     = CAMERA_HARDWARE_MODULE_ID,
    .name                   = "QCamera Module",
    .author                 = "Qualcomm Innovation Center Inc",
    .methods                = &qcamera::QCamera2Factory::mModuleMethods,
    .dso                    = NULL,
    .reserved               = {0}
};

camera_module_t HAL_MODULE_INFO_SYM = {
    .common                 = camera_common,
    .get_number_of_cameras  = qcamera::QCamera2Factory::get_number_of_cameras,
    .get_camera_info        = qcamera::QCamera2Factory::get_camera_info,
    .set_callbacks          = qcamera::QCamera2Factory::set_callbacks,
    .get_vendor_tag_ops     = qcamera::QCamera3VendorTags::get_vendor_tag_ops,
    .open_legacy            = NULL,
    .set_torch_mode         = qcamera::QCamera2Factory::set_torch_mode,
    .init                   = NULL,
    .reserved               = {0}
};

我们根据之前mModule->open_legacy来找,camera_module_t结构体中定义的.open_legacy。发现这里定义的是NUll,所以接着找device/google之外的其他三个目录,发现也是一样。其实如果在\hardware\interfaces\camera\device\1.0\default\CameraDevice.cpp中如果走的是mModule->common.methods->open,那么就好找多了,直接就能找到&qcamera::QCamera2Factory::mModuleMethods再对应去找open函数。

所以还需接着在hardware中搜索一下吧。

hardware/libhardware/modules/usbcamera/CameraHAL.cpp:camera_module_t HAL_MODULE_INFO_SYM __attribute__ ((visibility("default"))) = {
hardware/libhardware/modules/camera/3_4/v4l2_camera_hal.h:extern camera_module_t HAL_MODULE_INFO_SYM;
hardware/libhardware/modules/camera/3_4/v4l2_camera_hal.cpp:camera_module_t HAL_MODULE_INFO_SYM __attribute__((visibility("default"))) = {
hardware/libhardware/modules/camera/3_0/CameraHAL.cpp:camera_module_t HAL_MODULE_INFO_SYM __attribute__ ((visibility("default"))) = {
hardware/libhardware/include/hardware/camera.h: * Camera modules that implement version 2.0 or higher of camera_module_t must

看到hardware/libhardware/modules/camera/3_4/v4l2_camera_hal.cpp文件中的定义:

camera_module_t HAL_MODULE_INFO_SYM __attribute__((visibility("default"))) = {
    .common =
        {
            .tag = HARDWARE_MODULE_TAG,
            .module_api_version = CAMERA_MODULE_API_VERSION_2_4,
            .hal_api_version = HARDWARE_HAL_API_VERSION,
            .id = CAMERA_HARDWARE_MODULE_ID,
            .name = "V4L2 Camera HAL v3",
            .author = "The Android Open Source Project",
            .methods = &v4l2_module_methods,
            .dso = nullptr,
            .reserved = {0},
        },
    .get_number_of_cameras = v4l2_camera_hal::get_number_of_cameras,
    .get_camera_info = v4l2_camera_hal::get_camera_info,
    .set_callbacks = v4l2_camera_hal::set_callbacks,
    .get_vendor_tag_ops = v4l2_camera_hal::get_vendor_tag_ops,
    .open_legacy = v4l2_camera_hal::open_legacy,
    .set_torch_mode = v4l2_camera_hal::set_torch_mode,
    .init = nullptr,
    .reserved = {nullptr, nullptr, nullptr, nullptr, nullptr}};

在看v4l2_camera_hal::open_legacy。

static int open_legacy(const hw_module_t* module,
                       const char* id,
                       uint32_t halVersion,
                       hw_device_t** device) {
  return gCameraHAL.openLegacy(module, id, halVersion, device);
}
// Default global camera hal.
static V4L2CameraHAL gCameraHAL;
int V4L2CameraHAL::openLegacy(const hw_module_t* module,
                              const char* id,
                              uint32_t halVersion,
                              hw_device_t** device) {
  HAL_LOG_ENTER();
  // Not supported.
  return -ENOSYS;
}

看到Not supported,知道又找错地方了。哎。看了这个mtk的代码实现还是有些凌乱了。
那就看下\hardware\interfaces\camera\device\1.0\default\CameraDevice.cpp中如果走的是mModule->common.methods->open的情况吧,那么就回到了device\google\marlin\camera\QCamera2\QCamera2Hal.cpp中的common的定义,指向的是&qcamera::QCamera2Factory::mModuleMethods。

.methods = &qcamera::QCamera2Factory::mModuleMethods,

看到\device\google\marlin\camera\QCamera2\QCamera2Factory.cpp文件mModuleMethods的源码:

struct hw_module_methods_t QCamera2Factory::mModuleMethods = {
    open: QCamera2Factory::camera_device_open,
};

再指向了camera_device_open:

int QCamera2Factory::camera_device_open(
    const struct hw_module_t *module, const char *id,
    struct hw_device_t **hw_device)
{
    if (module != &HAL_MODULE_INFO_SYM.common) {
        ALOGE("Invalid module. Trying to open %p, expect %p",
            module, &HAL_MODULE_INFO_SYM.common);
        return INVALID_OPERATION;
    }
    if (!id) {
        ALOGE("Invalid camera id");
        return BAD_VALUE;
    }
    return gQCamera2Factory->cameraDeviceOpen(atoi(id), hw_device);
}

再指向了cameraDeviceOpen:

int QCamera2Factory::cameraDeviceOpen(int camera_id,
                    struct hw_device_t **hw_device)
{
    int rc = NO_ERROR;
    if (camera_id < 0 || camera_id >= mNumOfCameras)
        return -ENODEV;

    if ( NULL == mHalDescriptors ) {
        ALOGE("%s : Hal descriptor table is not initialized!", __func__);
        return NO_INIT;
    }

    if ( mHalDescriptors[camera_id].device_version == CAMERA_DEVICE_API_VERSION_3_0 ) {
        QCamera3HardwareInterface *hw = new QCamera3HardwareInterface(mHalDescriptors[camera_id].cameraId,
                mCallbacks);
        if (!hw) {
            ALOGE("Allocation of hardware interface failed");
            return NO_MEMORY;
        }
        rc = hw->openCamera(hw_device);
        if (rc != 0) {
            delete hw;
        }
    } else if (mHalDescriptors[camera_id].device_version == CAMERA_DEVICE_API_VERSION_1_0) {
        QCamera2HardwareInterface *hw = new QCamera2HardwareInterface((uint32_t)camera_id);
        if (!hw) {
            ALOGE("Allocation of hardware interface failed");
            return NO_MEMORY;
        }
        rc = hw->openCamera(hw_device);
        if (rc != NO_ERROR) {
            delete hw;
        }
    } else {
        ALOGE("%s: Device version for camera id %d invalid %d",
              __func__,
              camera_id,
              mHalDescriptors[camera_id].device_version);
        return BAD_VALUE;
    }

    return rc;
}

cameraDeviceOpen函数先判断了camera id是否正常,再通过判断不同的hal版本,拿到HardwareInterface,再去调用openCamera。这里就看下CAMERA_DEVICE_API_VERSION_1_0这种情况吧,它拿到的是QCamera2HardwareInterface。路径在device\google\marlin\camera\QCamera2\HAL\QCamera2HWI.cpp中。看他的openCamera函数。

int QCamera2HardwareInterface::openCamera(struct hw_device_t **hw_device)
{
    KPI_ATRACE_CALL();
    int rc = NO_ERROR;
    if (mCameraOpened) {
        *hw_device = NULL;
        LOGE("Permission Denied");
        return PERMISSION_DENIED;
    }
    LOGI("[KPI Perf]: E PROFILE_OPEN_CAMERA camera id %d",
            mCameraId);
    m_perfLock.lock_acq_timed(CAMERA_OPEN_PERF_TIME_OUT);
    rc = openCamera();
    if (rc == NO_ERROR){
        *hw_device = &mCameraDevice.common;
        if (m_thermalAdapter.init(this) != 0) {
          LOGW("Init thermal adapter failed");
        }
    }
    else
        *hw_device = NULL;

    LOGI("[KPI Perf]: X PROFILE_OPEN_CAMERA camera id %d, rc: %d",
            mCameraId, rc);

    return rc;
}

调用到openCamera():

int QCamera2HardwareInterface::openCamera()
{
    int32_t rc = NO_ERROR;
    char value[PROPERTY_VALUE_MAX];

    if (mCameraHandle) {
        LOGE("Failure: Camera already opened");
        return ALREADY_EXISTS;
    }

    rc = QCameraFlash::getInstance().reserveFlashForCamera(mCameraId);
    if (rc < 0) {
        LOGE("Failed to reserve flash for camera id: %d",
                mCameraId);
        return UNKNOWN_ERROR;
    }

    // alloc param buffer
    DeferWorkArgs args;
    memset(&args, 0, sizeof(args));
    mParamAllocJob = queueDeferredWork(CMD_DEF_PARAM_ALLOC, args);
    if (mParamAllocJob == 0) {
        LOGE("Failed queueing PARAM_ALLOC job");
        return -ENOMEM;
    }

    if (gCamCapability[mCameraId] != NULL) {
        // allocate metadata buffers
        DeferWorkArgs args;
        DeferMetadataAllocArgs metadataAllocArgs;

        memset(&args, 0, sizeof(args));
        memset(&metadataAllocArgs, 0, sizeof(metadataAllocArgs));

        uint32_t padding =
                gCamCapability[mCameraId]->padding_info.plane_padding;
        metadataAllocArgs.size = PAD_TO_SIZE(sizeof(metadata_buffer_t),
                padding);
        metadataAllocArgs.bufferCnt = CAMERA_MIN_METADATA_BUFFERS;
        args.metadataAllocArgs = metadataAllocArgs;

        mMetadataAllocJob = queueDeferredWork(CMD_DEF_METADATA_ALLOC, args);
        if (mMetadataAllocJob == 0) {
            LOGE("Failed to allocate metadata buffer");
            rc = -ENOMEM;
            goto error_exit1;
        }

        rc = camera_open((uint8_t)mCameraId, &mCameraHandle);
        if (rc) {
            LOGE("camera_open failed. rc = %d, mCameraHandle = %p",
                     rc, mCameraHandle);
            goto error_exit2;
        }

        mCameraHandle->ops->register_event_notify(mCameraHandle->camera_handle,
                camEvtHandle,
                (void *) this);
    } else {
        LOGH("Capabilities not inited, initializing now.");

        rc = camera_open((uint8_t)mCameraId, &mCameraHandle);
        if (rc) {
            LOGE("camera_open failed. rc = %d, mCameraHandle = %p",
                     rc, mCameraHandle);
            goto error_exit2;
        }

        if(NO_ERROR != initCapabilities(mCameraId,mCameraHandle)) {
            LOGE("initCapabilities failed.");
            rc = UNKNOWN_ERROR;
            goto error_exit3;
        }

        mCameraHandle->ops->register_event_notify(mCameraHandle->camera_handle,
                camEvtHandle,
                (void *) this);
    }

    // Init params in the background
    // 1. It's safe to queue init job, even if alloc job is not yet complete.
    // It will be queued to the same thread, so the alloc is guaranteed to
    // finish first.
    // 2. However, it is not safe to begin param init until after camera is
    // open. That is why we wait until after camera open completes to schedule
    // this task.
    memset(&args, 0, sizeof(args));
    mParamInitJob = queueDeferredWork(CMD_DEF_PARAM_INIT, args);
    if (mParamInitJob == 0) {
        LOGE("Failed queuing PARAM_INIT job");
        rc = -ENOMEM;
        goto error_exit3;
    }

    mCameraOpened = true;

    //Notify display HAL that a camera session is active.
    //But avoid calling the same during bootup because camera service might open/close
    //cameras at boot time during its initialization and display service will also internally
    //wait for camera service to initialize first while calling this display API, resulting in a
    //deadlock situation. Since boot time camera open/close calls are made only to fetch
    //capabilities, no need of this display bw optimization.
    //Use "service.bootanim.exit" property to know boot status.
    property_get("service.bootanim.exit", value, "0");
    if (atoi(value) == 1) {
        pthread_mutex_lock(&gCamLock);
        if (gNumCameraSessions++ == 0) {
            setCameraLaunchStatus(true);
        }
        pthread_mutex_unlock(&gCamLock);
    }

    memset(value, 0, sizeof(value));
    property_get("persist.camera.cache.optimize", value, "1");
    m_bOptimizeCacheOps = atoi(value);

    return NO_ERROR;

error_exit3:
    if(mJpegClientHandle) {
        deinitJpegHandle();
    }
    mCameraHandle->ops->close_camera(mCameraHandle->camera_handle);
    mCameraHandle = NULL;
error_exit2:
    waitDeferredWork(mMetadataAllocJob);
error_exit1:
    waitDeferredWork(mParamAllocJob);
    return rc;

}

关键的实现rc = camera_open((uint8_t)mCameraId, &mCameraHandle);,也有error_exit处理机制。
在\device\google\marlin\camera\QCamera2\stack\mm-camera-interface\src中搜索到了camera_open函数的声明。mm_camera_interface.c中的camera_open函数。

int32_t camera_open(uint8_t camera_idx, mm_camera_vtbl_t **camera_vtbl)
{
    int32_t rc = 0;
    mm_camera_obj_t *cam_obj = NULL;

#ifdef QCAMERA_REDEFINE_LOG
    mm_camera_set_dbg_log_properties();
#endif

    LOGD("E camera_idx = %d\n", camera_idx);
    if (camera_idx >= g_cam_ctrl.num_cam) {
        LOGE("Invalid camera_idx (%d)", camera_idx);
        return -EINVAL;
    }

    pthread_mutex_lock(&g_intf_lock);
    /* opened already */
    if(NULL != g_cam_ctrl.cam_obj[camera_idx]) {
        /* Add reference */
        g_cam_ctrl.cam_obj[camera_idx]->ref_count++;
        pthread_mutex_unlock(&g_intf_lock);
        LOGD("opened alreadyn");
        *camera_vtbl = &g_cam_ctrl.cam_obj[camera_idx]->vtbl;
        return rc;
    }

    cam_obj = (mm_camera_obj_t *)malloc(sizeof(mm_camera_obj_t));
    if(NULL == cam_obj) {
        pthread_mutex_unlock(&g_intf_lock);
        LOGE("no mem");
        return -EINVAL;
    }

    /* initialize camera obj */
    memset(cam_obj, 0, sizeof(mm_camera_obj_t));
    cam_obj->ctrl_fd = -1;
    cam_obj->ds_fd = -1;
    cam_obj->ref_count++;
    cam_obj->my_hdl = mm_camera_util_generate_handler(camera_idx);
    cam_obj->vtbl.camera_handle = cam_obj->my_hdl; /* set handler */
    cam_obj->vtbl.ops = &mm_camera_ops;
    pthread_mutex_init(&cam_obj->cam_lock, NULL);
    /* unlock global interface lock, if not, in dual camera use case,
      * current open will block operation of another opened camera obj*/
    pthread_mutex_lock(&cam_obj->cam_lock);
    pthread_mutex_unlock(&g_intf_lock);

    rc = mm_camera_open(cam_obj);

    pthread_mutex_lock(&g_intf_lock);
    if (rc != 0) {
        LOGE("mm_camera_open err = %d", rc);
        pthread_mutex_destroy(&cam_obj->cam_lock);
        g_cam_ctrl.cam_obj[camera_idx] = NULL;
        free(cam_obj);
        cam_obj = NULL;
        pthread_mutex_unlock(&g_intf_lock);
        *camera_vtbl = NULL;
        return rc;
    } else {
        LOGD("Open succeded\n");
        g_cam_ctrl.cam_obj[camera_idx] = cam_obj;
        pthread_mutex_unlock(&g_intf_lock);
        *camera_vtbl = &cam_obj->vtbl;
        return 0;
    }
}

在调用mm_camera_open之前进行相关初始化操作,如调用malloc、memset进行内存分配操作。所以又到了
mm_camera_open(cam_obj)函数,定义在mm_camera.c文件中。

int32_t mm_camera_open(mm_camera_obj_t *my_obj)
{
    char dev_name[MM_CAMERA_DEV_NAME_LEN];
    int32_t rc = 0;
    int8_t n_try=MM_CAMERA_DEV_OPEN_TRIES;
    uint8_t sleep_msec=MM_CAMERA_DEV_OPEN_RETRY_SLEEP;
    int cam_idx = 0;
    const char *dev_name_value = NULL;
    int l_errno = 0;

    LOGD("begin\n");

    if (NULL == my_obj) {
        goto on_error;
    }
    dev_name_value = mm_camera_util_get_dev_name(my_obj->my_hdl);
    if (NULL == dev_name_value) {
        goto on_error;
    }
    snprintf(dev_name, sizeof(dev_name), "/dev/%s",
             dev_name_value);
    sscanf(dev_name, "/dev/video%d", &cam_idx);
    LOGD("dev name = %s, cam_idx = %d", dev_name, cam_idx);

    do{
        n_try--;
        errno = 0;
        my_obj->ctrl_fd = open(dev_name, O_RDWR | O_NONBLOCK);
        l_errno = errno;
        LOGD("ctrl_fd = %d, errno == %d", my_obj->ctrl_fd, l_errno);
        if((my_obj->ctrl_fd >= 0) || (errno != EIO && errno != ETIMEDOUT) || (n_try <= 0 )) {
            break;
        }
        LOGE("Failed with %s error, retrying after %d milli-seconds",
              strerror(errno), sleep_msec);
        usleep(sleep_msec * 1000U);
    }while (n_try > 0);

    if (my_obj->ctrl_fd < 0) {
        LOGE("cannot open control fd of '%s' (%s)\n",
                  dev_name, strerror(l_errno));
        if (l_errno == EBUSY)
            rc = -EUSERS;
        else
            rc = -1;
        goto on_error;
    } else {
        mm_camera_get_session_id(my_obj, &my_obj->sessionid);
        LOGH("Camera Opened id = %d sessionid = %d", cam_idx, my_obj->sessionid);
    }

#ifdef DAEMON_PRESENT
    /* open domain socket*/
    n_try = MM_CAMERA_DEV_OPEN_TRIES;
    do {
        n_try--;
        my_obj->ds_fd = mm_camera_socket_create(cam_idx, MM_CAMERA_SOCK_TYPE_UDP);
        l_errno = errno;
        LOGD("ds_fd = %d, errno = %d", my_obj->ds_fd, l_errno);
        if((my_obj->ds_fd >= 0) || (n_try <= 0 )) {
            LOGD("opened, break out while loop");
            break;
        }
        LOGD("failed with I/O error retrying after %d milli-seconds",
              sleep_msec);
        usleep(sleep_msec * 1000U);
    } while (n_try > 0);

    if (my_obj->ds_fd < 0) {
        LOGE("cannot open domain socket fd of '%s'(%s)\n",
                  dev_name, strerror(l_errno));
        rc = -1;
        goto on_error;
    }
#else /* DAEMON_PRESENT */
    cam_status_t cam_status;
    cam_status = mm_camera_module_open_session(my_obj->sessionid,
            mm_camera_module_event_handler);
    if (cam_status < 0) {
        LOGE("Failed to open session");
        if (cam_status == CAM_STATUS_BUSY) {
            rc = -EUSERS;
        } else {
            rc = -1;
        }
        goto on_error;
    }
#endif /* DAEMON_PRESENT */

    pthread_mutex_init(&my_obj->msg_lock, NULL);
    pthread_mutex_init(&my_obj->cb_lock, NULL);
    pthread_mutex_init(&my_obj->evt_lock, NULL);
    PTHREAD_COND_INIT(&my_obj->evt_cond);

    LOGD("Launch evt Thread in Cam Open");
    snprintf(my_obj->evt_thread.threadName, THREAD_NAME_SIZE, "CAM_Dispatch");
    mm_camera_cmd_thread_launch(&my_obj->evt_thread,
                                mm_camera_dispatch_app_event,
                                (void *)my_obj);

    /* launch event poll thread
     * we will add evt fd into event poll thread upon user first register for evt */
    LOGD("Launch evt Poll Thread in Cam Open");
    snprintf(my_obj->evt_poll_thread.threadName, THREAD_NAME_SIZE, "CAM_evntPoll");
    mm_camera_poll_thread_launch(&my_obj->evt_poll_thread,
                                 MM_CAMERA_POLL_TYPE_EVT);
    mm_camera_evt_sub(my_obj, TRUE);

    /* unlock cam_lock, we need release global intf_lock in camera_open(),
     * in order not block operation of other Camera in dual camera use case.*/
    pthread_mutex_unlock(&my_obj->cam_lock);
    LOGD("end (rc = %d)\n", rc);
    return rc;

on_error:

    if (NULL == dev_name_value) {
        LOGE("Invalid device name\n");
        rc = -1;
    }

    if (NULL == my_obj) {
        LOGE("Invalid camera object\n");
        rc = -1;
    } else {
        if (my_obj->ctrl_fd >= 0) {
            close(my_obj->ctrl_fd);
            my_obj->ctrl_fd = -1;
        }
#ifdef DAEMON_PRESENT
        if (my_obj->ds_fd >= 0) {
            mm_camera_socket_close(my_obj->ds_fd);
            my_obj->ds_fd = -1;
        }
#endif
    }

    /* unlock cam_lock, we need release global intf_lock in camera_open(),
     * in order not block operation of other Camera in dual camera use case.*/
    pthread_mutex_unlock(&my_obj->cam_lock);
    return rc;
}

这个函数首先就是获取设备名称dev_name_value = mm_camera_util_get_dev_name(my_obj->my_hdl);,然后定义了一个值n_try,意义表示的是camera open的尝试次数,定义是20。

device/google/marlin/camera/QCamera2/stack/mm-camera-interface/inc/mm_camera.h:#define MM_CAMERA_DEV_OPEN_TRIES 20

int8_t n_try=MM_CAMERA_DEV_OPEN_TRIES;

然后执行了do{my_obj->ctrl_fd = open(dev_name, O_RDWR | O_NONBLOCK); }while (n_try > 0);循环,知道n_try次数尝试完毕。my_obj->ctrl_fd = open(dev_name, O_RDWR | O_NONBLOCK);这个就是实际打开camera的操作,do逻辑代码里面,判断满足if((my_obj->ctrl_fd >= 0) || (errno != EIO && errno != ETIMEDOUT) || (n_try <= 0 ))任意条件就可以break跳出循环,其中(my_obj->ctrl_fd >= 0)表示的camera open成功,没有出现异常,error表示出现了超时连接或者IO流异常,n_try表明open尝试次数已经用完,三种跳出循环的情况。从这看底层对于openCamera也是做了多次尝试连接的保险操作的。
而my_obj->ctrl_fd = open(dev_name, O_RDWR | O_NONBLOCK)中的open就是属于系统函数的调用了,会调用到驱动内核层来实现处理。流程差不多就结束了,后面到驱动层内核层了。

再回到QCamera2Hal.cpp中,虽然camera_module_t中openLegacy定义为null,但是在QCamera2Factory.cpp里面还是定义了openLegacy函数的。

int QCamera2Factory::open_legacy(const struct hw_module_t* module,
            const char* id, uint32_t halVersion, struct hw_device_t** device)
{
    if (module != &HAL_MODULE_INFO_SYM.common) {
        ALOGE("Invalid module. Trying to open %p, expect %p",
            module, &HAL_MODULE_INFO_SYM.common);
        return INVALID_OPERATION;
    }
    if (!id) {
        ALOGE("Invalid camera id");
        return BAD_VALUE;
    }
    return gQCamera2Factory->openLegacy(atoi(id), halVersion, device);
}

然后看到,函数中,就只针对CAMERA_DEVICE_API_VERSION_1_0来了,而流程与上一段一致了调用hw->openCamera。

int QCamera2Factory::openLegacy(
        int32_t cameraId, uint32_t halVersion, struct hw_device_t** hw_device)
{
    int rc = NO_ERROR;

    ALOGI(":%s openLegacy halVersion: %d", __func__, halVersion);
    //Assumption: all cameras can support legacy API version
    if (cameraId < 0 || cameraId >= gQCamera2Factory->getNumberOfCameras())
        return -ENODEV;

    switch(halVersion)
    {
        case CAMERA_DEVICE_API_VERSION_1_0:
        {
            QCamera2HardwareInterface *hw =
                new QCamera2HardwareInterface((uint32_t)cameraId);
            if (!hw) {
                ALOGE("%s: Allocation of hardware interface failed", __func__);
                return NO_MEMORY;
            }
            rc = hw->openCamera(hw_device);
            if (rc != NO_ERROR) {
                delete hw;
            }
            break;
        }
        default:
            ALOGE("%s: Device API version: %d for camera id %d invalid",
                __func__, halVersion, cameraId);
            return BAD_VALUE;
    }

    return rc;
    }

接着往下连接到底层驱动。camera_module_t的实现还是与厂商的实现方式有很大关系了。

总的来说,openCamera的流程确实是很复杂麻烦了,不过日常工作上,从framework层到ap流程上一般不会出现问题,我们从af方向上debug了解这些基本就可以了,而driver到hal也需要专门的分析人员了。camera的流程繁杂,简单的架构我们也许可以说清楚,但是越往下走越觉得需要了解的越多,知识是无涯的,还是要不断学习啊。

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值