android Camera API1+HAL1 open camera流程 & Android M

Camera API2从android 5.0就已经支持了,API1早已经被谷歌标记为过时了,谷歌也一直在推camera API2,并且前不久伴随着Android 10的发布,谷歌推出了CameraX 库,为了更方便的使用API2。但目前仍然有很多camera相关的应用因为一开始使用的就是API1,业务框架流程都已经稳定,不会耗费人力去迁移camera API2。所以在很长一段时间内,camera API1还是会有应用在使用,当然后续API2也会分析的,毕竟这是大趋势。

本文是基于android 6.0源码,搭配camera HAL1进行分析,这对Android 8.0之前的系统来说都是通用的。android 8.0以后加入了Treble机制,cameraService层和HAL层之间加入了一层Camera HIDL层,流程和结构上发生了些变化,但核心没变,后续有时间会分析下。android 9.0以后的新设备都必须升级到HAL3,后续也会分析HAL3,这也是大势所趋。

尽管camera api1的的相关流程都已经被写烂了,之所以还写,一是想作为一个自己学习的记录,慢慢培养写东西的习惯;二是只有自己真正的去理一遍代码流程,才能真正的搞清楚代码逻辑,印象也更加深刻,就好比只看代码是永远也学不会编程的,必须要实操。

0 创建camera framework层实例

camera API1的接口简单易用,现在依然有很多人喜欢使用这套接口快捷的编写camera apk。本文应用相关的代码来源于android develop 官方示例。

// 官方示例
/** A safe way to get an instance of the Camera object. */
public static Camera getCameraInstance(){
    Camera c = null;
    try {
        c = Camera.open(); // attempt to get a Camera instance
    }
    catch (Exception e){
        // Camera is not available (in use or does not exist)
    }
    return c; // returns null if camera is unavailable
}
  • frameworks/base/core/java/android/hardware/Camera.java
  • 获取当前设备挂载的camera个数,查询后置摄像头并创建camera实例
    public static Camera open() {
        int numberOfCameras = getNumberOfCameras();
        CameraInfo cameraInfo = new CameraInfo();
        for (int i = 0; i < numberOfCameras; i++) {
            getCameraInfo(i, cameraInfo);
            if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
                return new Camera(i);
            }
        }
        return null;
    }
    /** used by Camera#open, Camera#open(int) */
    Camera(int cameraId) {
        int err = cameraInitNormal(cameraId);
        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");
        }
    }
    private int cameraInitNormal(int cameraId) {
        return cameraInitVersion(cameraId, CAMERA_HAL_API_VERSION_NORMAL_CONNECT);
    }
  • 注意上面的实参是CAMERA_HAL_API_VERSION_NORMAL_CONNECT,后面会用到
  • native_setup 是本地函数调用,函数实现在JNI层
    private int cameraInitVersion(int cameraId, int halVersion) {
		....
        return native_setup(new WeakReference<Camera>(this), cameraId, halVersion,
                ActivityThread.currentOpPackageName());
    }

1 camera 本地设置

  • frameworks/base/core/jni/android_hardware_Camera.cpp
  { "native_setup",
    "(Ljava/lang/Object;IILjava/lang/String;)I",
    (void*)android_hardware_Camera_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)
{
  ……
    sp<Camera> camera;
    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);   1-1
    } else {
        jint status = Camera::connectLegacy(cameraId, halVersion, clientName,
                Camera::USE_CALLING_UID, camera);
        if (status != NO_ERROR) {
            return status;
        }
    }
   ……
    // We use a weak reference so the Camera object can be garbage collected.
    // The reference is only used as a proxy for callbacks.
    sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera);  1-2
    context->incStrong((void*)android_hardware_Camera_native_setup);
    camera->setListener(context); 	1-3
 } 
  • 因为之前传入的API版本是CAMERA_HAL_API_VERSION_NORMAL_CONNECT,所以会调用1-1处的Camera::connect,这个函数是个静态函数,直接用类名调用
  • 1-2处的JNICameraContext继承了CameraListener,负责回调拍照、预览、录像等数据。
  • 1-3设置监听对象,供camera数据回调

2 Camera本地客户端层

2.1 Camera::connect

  • frameworks/av/camera/Camera.cpp
  • frameworks/av/camera/CameraBase.cpp
// Camera.cpp
sp<Camera> Camera::connect(int cameraId, const String16& clientPackageName,
        int clientUid, int clientPid)
{
    return CameraBaseT::connect(cameraId, clientPackageName, clientUid, clientPid);
}

// CameraBase.cpp
template <typename TCam, typename TCamTraits>
sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId,
                                               const String16& clientPackageName,
                                               int clientUid)
{
    ALOGV("%s: connect", __FUNCTION__);
    sp<TCam> c = new TCam(cameraId);
    sp<TCamCallbacks> cl = c;
    status_t status = NO_ERROR;
    const sp<ICameraService>& cs = getCameraService();	2-1

    if (cs != 0) {
        TCamConnectService fnConnectService = TCamTraits::fnConnectService;
        status = (cs.get()->connect)(cl, cameraId, clientPackageName, clientUid,   /*out*/ c->mCamera); 	2-2
    }
    if (status == OK && c->mCamera != 0) {
        IInterface::asBinder(c->mCamera)->linkToDeath(c);
        c->mStatus = NO_ERROR;
    } else {
        ALOGW("An error occurred while connecting to camera: %d", cameraId);
        c.clear();
    }
    return c;
}
  • CameraBase是Camera的基类,CameraBase是个模板类,参数TCam是Camera,其实我觉得CameraBase没必要定义成模板,因为目前只有Camera一个类使用了这个基类,搞得有点累赘
  • 2-1处是获取CameraService服务的代理BpCameraService,这个可以参看罗升阳的Android系统进程间通信(IPC)机制Binder中的Client获得Server远程接口过程源代码分析;当然前提是CameraService服务已经在Service Manager中注册了,CameraService启动过程可以参见NULL___的这篇Android 7.0 Camera架构源码分析1 - CameraService启动和罗升阳的这篇Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析。
  • 2-2处我修改了下,直接调用ICameraService的connect函数就好了,更加明了;因为在Camera.cpp里就是给fnConnectService赋值了ICameraService的connect函数指针。
CameraTraits<Camera>::TCamConnectService CameraTraits<Camera>::fnConnectService =
        &::android::hardware::ICameraService::connect;

2-2这里涉及到一个Binder通信,具体可以参看罗升阳、袁辉辉的相关博文,以及《Android框架揭秘》的第八章。cs.get()获取到的是一个BpCameraService指针,通过Binder RPC调用到CameraService::connect函数。

Camera继承BnCameraClient,里面含有一个ICamera类型的变量mCamera。2-2是通过CameraService这个实名service的Binder RPC通信传递BnCameraClien对象(Camera),Camera其实是一个匿名service,匿名service需要依托实名service的传递才能和服务代理端建立联系。ICameraService.cpp中包含了一个典型的Binder RPC通信机制。

2.2 BpCameraService::connect

  • ICameraService.cpp
   // connect to camera service (android.hardware.Camera)
    virtual status_t connect(const sp<ICameraClient>& cameraClient, int cameraId,
                             const String16 &clientPackageName, int clientUid,
                             /*out*/
                             sp<ICamera>& device)
    {
        Parcel data, reply;
        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
        data.writeStrongBinder(IInterface::asBinder(cameraClient)); 		2-3
        data.writeInt32(cameraId);
        data.writeString16(clientPackageName);
        data.writeInt32(clientUid);

        status_t status;
        status = remote()->transact(BnCameraService::CONNECT, data, &reply);		2-4
        if (status != OK) return status;

        if (readExceptionCode(reply)) return -EPROTO;
        status = reply.readInt32();
        if (reply.readInt32() != 0) {
            device = interface_cast<ICamera>(reply.readStrongBinder());		2-5
        }
        return status;
    }

这段代码的2-3是将BnCameraClinet转换为IBinder,然后2-4是通过Binder通信机制传递到BnCameraService中,2-5是通过Binder应答机制从BnCameraService中返回的BpCamera实例的指针,后续会讲到这一步的BpCamera是怎么获得的。

下面分析下2-4中的逻辑

2.3 BnCameraService::onTransact

  • frameworks/av/camera/ICameraService.cpp
status_t BnCameraService::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    switch(code) {
        case CONNECT: {
            CHECK_INTERFACE(ICameraService, data, reply);
            sp<ICameraClient> cameraClient =
                    interface_cast<ICameraClient>(data.readStrongBinder());		2-6
            int32_t cameraId = data.readInt32();
            const String16 clientName = data.readString16();
            int32_t clientUid = data.readInt32();
            sp<ICamera> camera;
            status_t status = connect(cameraClient, cameraId,
                    clientName, clientUid, /*out*/camera);		2-7
            reply->writeNoException();
            reply->writeInt32(status);
            if (camera != NULL) {
                reply->writeInt32(1);
                reply->writeStrongBinder(IInterface::asBinder(camera));		2-8
            } else {
                reply->writeInt32(0);
            }
            return NO_ERROR;
        } break;
  • 2-6处首先获取BnCameraClient 这个匿名service的BpBinder对象,BpBinder里含有这个service对应的handle;再通过 interface_cast转换为BpCameraClient实例。
  • 因为CameraService继承了BnCameraService,所以2-7处会调用CameraService的connect函数;通过2-7调用获取到的camera其实是一个BnCamera,然后通过2-8返回给2.2节的2-5,这个过程和前面传递BnCameraClient的过程是相反的,最终2.2节的2-5会获取到一个BpCamera实例指针。

下面分析CameraService::connect调用过程

3 CameraService 服务层

3.1 CameraService::connect

  • frameworks/av/services/camera/libcameraservice/CameraService.cpp
  • frameworks/av/services/camera/libcameraservice/CameraService.h
status_t CameraService::connect(
        const sp<ICameraClient>& cameraClient,
        int cameraId,
        const String16& clientPackageName,
        int clientUid,
        /*out*/
        sp<ICamera>& device) {

    ATRACE_CALL();
    status_t ret = NO_ERROR;
    String8 id = String8::format("%d", cameraId);
    sp<Client> client = nullptr;
    ret = connectHelper<ICameraClient,Client>(cameraClient, id, CAMERA_HAL_API_VERSION_UNSPECIFIED,
            clientPackageName, clientUid, API_1, false, false, /*out*/client);		3-1
……
    device = client;		3-2
    return NO_ERROR;
}
  • 3-1处调用CameraService.h中定义的函数connectHelper
  • 3-2将新建的BnCamera实例指针赋值给前面的调用

template<class CALLBACK, class CLIENT>
status_t CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
        int halVersion, const String16& clientPackageName, int clientUid,
        apiLevel effectiveApiLevel, bool legacyMode, bool shimUpdateOnly,
        /*out*/sp<CLIENT>& device) {
        ……
        int facing = -1;
        int deviceVersion = getDeviceVersion(id, /*out*/&facing);
        sp<BasicClient> tmp = nullptr;
        if((ret = makeClient(this, cameraCb, clientPackageName, cameraId, facing, clientPid,			3-3
                clientUid, getpid(), legacyMode, halVersion, deviceVersion, effectiveApiLevel,
                /*out*/&tmp)) != NO_ERROR) {
            return ret;
        }
        client = static_cast<CLIENT*>(tmp.get());		
        if ((ret = client->initialize(mModule)) != OK) {		3-4
            ALOGE("%s: Could not initialize client from HAL module.", __FUNCTION__);
            return ret;
        }
        ……
  }
  • connectHelper是一个模板函数,CALLBACK赋值为ICameraClient, CLIENT赋值为Client,Client是CameraService的内部类,其继承了BnCamera;Client还是一个抽象类,不能实例化,CameraClient类继承Client并实现了所有的纯虚函数。
  • 3-3 处调用makeClient函数,获取到BasicClient对象指针,BasicClient是Client的基类,也是CameraClient类的基类;将上层传过来的BpCameraClient实例指针继续往下传递;
  • 3-4 处调用CameraClient的初始化函数initialize

以下先分析3-3makeClient的调用流程

status_t 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) {
          case CAMERA_DEVICE_API_VERSION_1_0:
            if (effectiveApiLevel == API_1) {  // Camera1 API route
                sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
                *client = new CameraClient(cameraService, tmp, packageName, id, facing,		3-5
                        clientPid, clientUid, getpid(), legacyMode);
            } else { // Camera2 API route
		……
    } 
  • 因为本文针对的是camera API1 & HAL1,所以此处会走到3-5处,CameraClient类是继承并实现了Client类的,此处创建一个CameraClient实例赋值给前面传递过来的参数client,然后通过Binder通信机制传递,层层回调,最终返回给CameraBase类的mCamera变量;因为mCamera变量类型是protect修饰的,所以CameraBase类的派生类Camera内部可以访问该变量,mCamera变量保存的其实是一个BpCamera实例指针。

接下来继续跟踪3-5CameraClient的构造函数的调用流程

CameraClient::CameraClient(const sp<CameraService>& cameraService,
        const sp<ICameraClient>& cameraClient,
        const String16& clientPackageName,
        int cameraId, int cameraFacing,
        int clientPid, int clientUid,
        int servicePid, bool legacyMode):
        Client(cameraService, cameraClient, clientPackageName,
                cameraId, cameraFacing, clientPid, clientUid, servicePid)
{
    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;
}

构造函数里主要是一些变量的初始化操作,继续跟踪其基类Client的构造函数

CameraService::Client::Client(const sp<CameraService>& cameraService,
        const sp<ICameraClient>& cameraClient,
        const String16& clientPackageName,
        int cameraId, int cameraFacing,
        int clientPid, uid_t clientUid,
        int servicePid) :
        CameraService::BasicClient(cameraService,
                IInterface::asBinder(cameraClient),
                clientPackageName,
                cameraId, cameraFacing,
                clientPid, clientUid,
                servicePid)
{
    int callingPid = getCallingPid();
    LOG1("Client::Client E (pid %d, id %d)", callingPid, cameraId);

    mRemoteCallback = cameraClient;

    cameraService->loadSound();

    LOG1("Client::Client X (pid %d, id %d)", callingPid, cameraId);
}

主要是把上层传递下来的BpCameraClient实例指针赋值给Client类的sp mRemoteCallback,这个变量是protected修饰,所以Client的派生类CameraClient内部可以直接访问该变量。

至此,就完成了native层Camera类和cameraservice层的CameraClient类的关联。Camera类的实例持有CameraClient类实例对应的BpCamera指针,CameraClient实例持有Camera类实例对应的BpCameraClient指针,后续这两个类之间的函数调用,借助Binder通信机制可以实现类似本地调用一样跨进程调用。


继续分析上面的流程3-4的client->initialize

3.2 CameraClient::initialize

  • frameworks/av/services/camera/libcameraservice/api1/CameraClient.cpp
  • frameworks/av/services/camera/libcameraservice/device1/CameraHardwareInterface.h
status_t CameraClient::initialize(CameraModule *module) {
	.....
    char camera_device_name[10];
    snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId);
    mHardware = new CameraHardwareInterface(camera_device_name);
    res = mHardware->initialize(module);  3-6
    if (res != OK) {
        ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
                __FUNCTION__, mCameraId, strerror(-res), res);
        mHardware.clear();
        return res;
    }
    mHardware->setCallbacks(notifyCallback,  3-7
            dataCallback,
            dataCallbackTimestamp,
            (void *)(uintptr_t)mCameraId);
    // Enable zoom, error, focus, and metadata messages by default
    enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS |
                  CAMERA_MSG_PREVIEW_METADATA | CAMERA_MSG_FOCUS_MOVE);
    LOG1("CameraClient::initialize X (pid %d, id %d)", callingPid, mCameraId);
    return OK;
}
  • 3-6新建一个CameraHardwareInterface对象后,进行初始化;3-7设置通知回调(播放拍照快门声音)、数据回调(拍照的图片数据)、带时间戳的数据(录像的帧数据)的回调函数到HAL层。

3-6的流程如下,在CameraHardwareInterface.h中

    status_t initialize(CameraModule *module)
    {
        ALOGI("Opening camera %s", mName.string());
        camera_info info;
        status_t res = module->getCameraInfo(atoi(mName.string()), &info);
        if (res != OK) return res;
        int rc = OK;
        if (module->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 = module->openLegacy(mName.string(),
                                     CAMERA_DEVICE_API_VERSION_1_0,
                                     (hw_device_t **)&mDevice);
        } else {
            rc = module->open(mName.string(), (hw_device_t **)&mDevice); 3-8
        }
        if (rc != OK) {
            ALOGE("Could not open camera %s: %d", mName.string(), rc);
            return rc;
        }
        initHalPreviewWindow();  3-9
        return rc;
    }

参数CameraModule指针对应的实例是在CameraService::onFirstRef里创建的,OnFirstRef函数是在CameraService启动时被调用的。参见前面提到的文章Android 7.0 Camera架构源码分析1 - CameraService启动。

void CameraService::onFirstRef()
{
    ALOGI("CameraService process starting");
    BnCameraService::onFirstRef();
    // Update battery life tracking if service is restarting
    BatteryNotifier& notifier(BatteryNotifier::getInstance());
    notifier.noteResetCamera();
    notifier.noteResetFlashlight();
    camera_module_t *rawModule;
    int err = hw_get_module(CAMERA_HARDWARE_MODULE_ID,	3-10
            (const hw_module_t **)&rawModule);
    if (err < 0) {
        ALOGE("Could not load camera HAL module: %d (%s)", err, strerror(-err));
        logServiceError("Could not load camera HAL module", err);
        mNumberOfCameras = 0;
        return;
    }
    mModule = new CameraModule(rawModule);	3-11
    err = mModule->init();
    ........
 }

3-10调用hw_get_module后,获取到的rawModule实际是一个camera_module_t类型的指针,camera_module_t结构体的第一个成员固定为hw_module_t类型,所以camera_module_t对象的地址和其成员hw_module_t的地址是一致的。hw_get_module函数是通用函数,可以为各个模块所调用,其第二个参数的类型设计成通用的const hw_module_t **也是为了兼容不同的module。hw_get_module函数会调用到cameraHAL层,在此以ti cameraHal层的代码为例,目录为hardware/ti/omap4xxx/camera,rawModule最终就指向了camera_module_t 类型的HAL_MODULE_INFO_SYM 变量 。

  • hardware/ti/omap4xxx/camera/CameraHal_Module.cpp
static struct hw_module_methods_t camera_module_methods = {
        .open = camera_device_open
};
camera_module_t HAL_MODULE_INFO_SYM = {
    .common = {
         .tag = HARDWARE_MODULE_TAG,
         .version_major = 1,
         .version_minor = 0,
         .id = CAMERA_HARDWARE_MODULE_ID,
         .name = "TI OMAP CameraHal Module",
         .author = "TI",
         .methods = &camera_module_methods,
         .dso = NULL, /* remove compilation warnings */
         .reserved = {0}, /* remove compilation warnings */
    },
    .get_number_of_cameras = camera_get_number_of_cameras,
    .get_camera_info = camera_get_camera_info,
};

上层获取到了HAL层的三个函数指针,分别为camera_device_open,camera_get_number_of_cameras,camera_get_camera_info,其中的open函数尤为重要,方便后续获取HAL层的一些其他功能函数指针,供上层调用。

3-11创建CameraModule实例并将获取到的HAL层的camera_module_t 实例指针保存在内部,init初始化时会调用前面获取到的camera_get_number_of_cameras函数指针,获取当前设备挂载的camera设备个数。

  • frameworks/av/services/camera/libcameraservice/common/CameraModule.cpp
int CameraModule::init() {
    ATRACE_CALL();
    int res = OK;
    if (getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4 &&
            mModule->init != NULL) {
        ATRACE_BEGIN("camera_module->init");
        res = mModule->init();
        ATRACE_END();
    }
    mCameraInfoMap.setCapacity(getNumberOfCameras());
    return res;
}
int CameraModule::getNumberOfCameras() {
    int numCameras;
    ATRACE_BEGIN("camera_module->get_number_of_cameras");
    numCameras = mModule->get_number_of_cameras();
    ATRACE_END();
    return numCameras;
}

继续分析代码3-8module->open(mName.string(), (hw_device_t **)&mDevice)
此处的mDevice类型是camera_device,而结构体camera_device的第一个成员固定为hw_device_t,这里做了一个类型的强制转换,此处的原理和上面调用hw_get_module函数是做的转换类似的。

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;
}

此处调用之前获取到的open函数指针,即调用HAL层CameraHal_Module.cpp中的camera_device_open函数。

  • hardware/ti/omap4xxx/camera/CameraHal_Module.cpp
int camera_device_open(const hw_module_t* module, const char* name,
                hw_device_t** device)
{
    int rv = 0;
    int num_cameras = 0;
    int cameraid;
    ti_camera_device_t* camera_device = NULL;
    camera_device_ops_t* camera_ops = NULL;
    android::CameraHal* camera = NULL;
    android::CameraProperties::Properties* properties = NULL;
    android::Mutex::Autolock lock(gCameraHalDeviceLock);
	if (name != NULL) {
		......
        camera_device = (ti_camera_device_t*)malloc(sizeof(*camera_device));
        if(!camera_device)
        {
            ALOGE("camera_device allocation fail");
            rv = -ENOMEM;
            goto fail;
        }
        camera_ops = (camera_device_ops_t*)malloc(sizeof(*camera_ops));
        if(!camera_ops)
        {
            ALOGE("camera_ops allocation fail");
            rv = -ENOMEM;
            goto fail;
        }
        memset(camera_device, 0, sizeof(*camera_device));
        memset(camera_ops, 0, sizeof(*camera_ops));
        camera_device->base.common.tag = HARDWARE_DEVICE_TAG;
        camera_device->base.common.version = 0;
        camera_device->base.common.module = (hw_module_t *)(module);
        camera_device->base.common.close = camera_device_close;
        camera_device->base.ops = camera_ops;

        camera_ops->set_preview_window = camera_set_preview_window;
        camera_ops->set_callbacks = camera_set_callbacks;
        camera_ops->enable_msg_type = camera_enable_msg_type;
        camera_ops->disable_msg_type = camera_disable_msg_type;
        camera_ops->msg_type_enabled = camera_msg_type_enabled;
        camera_ops->start_preview = camera_start_preview;
        camera_ops->stop_preview = camera_stop_preview;
        camera_ops->preview_enabled = camera_preview_enabled;
        camera_ops->store_meta_data_in_buffers = camera_store_meta_data_in_buffers;
        camera_ops->start_recording = camera_start_recording;
        camera_ops->stop_recording = camera_stop_recording;
        camera_ops->recording_enabled = camera_recording_enabled;
        camera_ops->release_recording_frame = camera_release_recording_frame;
        camera_ops->auto_focus = camera_auto_focus;
        camera_ops->cancel_auto_focus = camera_cancel_auto_focus;
        camera_ops->take_picture = camera_take_picture;
        camera_ops->cancel_picture = camera_cancel_picture;
        camera_ops->set_parameters = camera_set_parameters;
        camera_ops->get_parameters = camera_get_parameters;
        camera_ops->put_parameters = camera_put_parameters;
        camera_ops->send_command = camera_send_command;
        camera_ops->release = camera_release;
        camera_ops->dump = camera_dump;

        *device = &camera_device->base.common;	3-12
        // -------- TI specific stuff --------
        camera_device->cameraid = cameraid;
		......

3-12变量camera_device的指针类型是ti_camera_device_t,这是ti camera HAL层对camera_device_t 结构又包了一层,最终的效果就是camera_device->base.common的地址就是camera_device指针的值,将这个地址赋值给了上层的hw_device_t指针,也就是返回到了3-8。所以在CameraHardwareInterface内部通过这个指针可以获取到camera_device所有的ops函数指针,这些函数指针在上面已经赋值。

CameraHardwareInterface类是CameraService层和CameraHAL层沟通的桥梁,不管从上到下的功能指令发送,还是从底至顶的数据回调,都要经过CameraHardwareInterface这个中转枢纽。

typedef struct ti_camera_device {
    camera_device_t base;
    /* TI specific "private" data can go here (base.priv) */
    int cameraid;
} ti_camera_device_t;

// camera.h
typedef struct camera_device {
    /**
     * camera_device.common.version must be in the range
     * HARDWARE_DEVICE_API_VERSION(0,0)-(1,FF). CAMERA_DEVICE_API_VERSION_1_0 is
     * recommended.
     */
    hw_device_t common;
    camera_device_ops_t *ops;
    void *priv;
} camera_device_t;

接上继续分析3-9

    void initHalPreviewWindow()
    {
        mHalPreviewWindow.nw.cancel_buffer = __cancel_buffer;
        mHalPreviewWindow.nw.lock_buffer = __lock_buffer;
        mHalPreviewWindow.nw.dequeue_buffer = __dequeue_buffer;
        mHalPreviewWindow.nw.enqueue_buffer = __enqueue_buffer;
        mHalPreviewWindow.nw.set_buffer_count = __set_buffer_count;
        mHalPreviewWindow.nw.set_buffers_geometry = __set_buffers_geometry;
        mHalPreviewWindow.nw.set_crop = __set_crop;
        mHalPreviewWindow.nw.set_timestamp = __set_timestamp;
        mHalPreviewWindow.nw.set_usage = __set_usage;
        mHalPreviewWindow.nw.set_swap_interval = __set_swap_interval;

        mHalPreviewWindow.nw.get_min_undequeued_buffer_count =
                __get_min_undequeued_buffer_count;
    }
    
    struct camera_preview_window {
        struct preview_stream_ops nw;
        void *user;
    };
    struct camera_preview_window mHalPreviewWindow;

这里主要是对preview_stream_ops的函数指针赋值,这些函数是在CameraHardwareInterface.h里定义的,然后设置到HAL层,供cameraHAL层的显示模块回调的。


至此,基本把open camera相关的流程从java层经过JNI,native层,service层,附带一些hal层都分析了一遍。

CameraService启动流程如下:
android Camera API1+HAL1 open camera流程 & Android M_第1张图片

open camera,初始化的整个流程图如下
android Camera API1+HAL1 open camera流程 & Android M_第2张图片
connet
android Camera API1+HAL1 open camera流程 & Android M_第3张图片

走完整个流程后,就完成了CameraService、CameraClient、Camera的初始化和CameraHAL的挂载,后续会分析设置preview window和 start preview等操作。

你可能感兴趣的:(android Camera API1+HAL1 open camera流程 & Android M)