打开相机的第一步便是在APP里去调用openCamera(),去打开指定的Camera设备(通过Device id指定),并建立起连接。APP通过openCamera()调用成功后,可以获取到一个已经初始化过的CameraDeviceImp,它表示一个已经打开的Camera设备,后续APP便可以通过CameraDeviceImp去执行各种操作,以控制相机的各种行为。
下面简单地介绍一些openCamera的流程,希望可以对整个的过程有一个大概的了解, openCamera()的主要flow如下图所示
可以将这个过程划分为3个部分来看,分别是App、native framework、Hal层,接下来也将从这三个部分去分析openCamera()这个过程。
对应上图中CameraManager.java这部分。App首先要获取到CameraManager服务,然后才可以查询到某个CameraId所对应的相机设备信息,再调用openCamera(),去打开指定CameraId所对应的相机设备。前面的flow就是:
——> openCamera(String cameraId,CameraDevice.StateCallback callback,......)
——> openCameraForUid(String cameraId,CameraDevice.StateCallback callback,......)
——> openCameraDeviceUserAsync(String cameraId,CameraDevice.StateCallback callback,......)
其中的两个参数:cameraId就不必多说了^v^;这个callback参数是一个回调对象,用来接收这个CameraDevice的状态变化情况的,这个回调对象里有提供几个回调函数(onOpened()、onClosed()、onError()、onDisconnected()),APP必须要去实作这些方法,以便于底层的CameraDevice切到对应的状态后,APP能够做出对应的反应。前面两个函数的逻辑比较简单,下面主要看一下openCameraDeviceUserAsync()里做的事情:
---------> CameraDeviceImpl deviceImpl=new CameraDeviceImpl();
但是这个deviceImpl里还有一个重要的成员-------->mRemoteDevice 没有初始化,它是这个deviceImpl的远端服务,其实后续APP对deviceImpl的操作都会转化为对这个远端服务mRemoteDevice的操作,而这个远端服务需要通过CameraService这个系统服务去获取到。
----------> cameraUser=CameraService.connectDevice();
----------> deviceImpl.setRemoteDevice(cameraUser)
这里面最终会通过前面APP传下来的回调函数---> callback.onOpened() ,返回这个CameraDeviceImpl
所以是App调用的CameraManager的openCamera()方法,调用成功后,在回调函数里可以得到一个CameraDeviceImpl的实例,这个实例里包含其对应的远端服务。接下来看一看这其中所说的“调用远程CameraService获取当前相机的远程服务”是在做什么。
在App部分其中有一步叫做:调用远程CameraService获取当前相机的远程服务。这一步其实是通过AIDL调用到了CameraService::connectDevice(),这里就进入了native framework层,这个过程对应于前面流程图中CameraService.cpp到CameraProviderManager.cpp的这一部分 ,接下来看看这个过程中经历的事情。这里面有涉及到几个class:CameraService、CameraDeviceClient、Camera2ClientBase、Camera3Device、CameraProviderManager,它们之间的关系如下:
通过这部分的flow,我们可以看到在native framework里面做的事情大概可以总结如下:
处理相机的抢占机制,可以参考:Android Camera抢占机制——handleEvictionsLocked()
即CameraDeviceClient::initialize()。这里面会调用到Camera2ClientBase::initialize(),而Camera3Device继承自Camera2ClientBase,从前面关系图里可以看出,其实可以看出来Camera3Device就是CameraDeviceClient的成员变量。所以这里面其实是会调用到Camera3Device::initialize()。
即Camera3Device::initialize()。这里面最重要的一步便是CameraProviderManager::openSession(),接下来看看这个openSession()里面做的事情:
根据CameraDevice的版本,从所有Provider中,找到对应的DeviceInfo。这些信息是在CameraService起来时已经保存好的,可以参考Android Camera之CameraServer的启动过程
根据刚刚deviceInfo中对应的provider的信息,获取到对应CameraProvider服务。
通过CameraProvider的getCameraDeviceInterface_V3_x()实例化一个CameraDevice。这一步是通过HIDL调用到了Hal层,这个CameraDevice是Hal层实作的,和前面APP部分的CameraDevice有所不同,也有所联系
这个interface就是前面startDeviceInterface()得到的CameraDevice,这里是要通过CameraDevicce::open()创建一个有效的CameraDeviceSession。这一步也是通过HIDL调用到了HAL层。
需要说一下的是,这个函数有带一个参数给Hal层:即ICameraDeviceCallback。再向前追溯,可以看到是Camera3Device,调用CameraProviderManager::openSession()时传下来的,这个参数是this,其实就是Camera3Device,其实Camera3Device也是自ICameraDeviceCallback继承下来的,这个类可以看这里定义的接口:
/hardware/interfaces/camera/device/3.x/ICameraDeviceCallback.hal
里面有两个重要的方法:processCaptureResult()和notify()
再根据CameraDeviceSession构造HalInterface
将CameraDeviceSession赋值给HalInterface::mHidlSession_3_X
即创建CameraDeviceClient::mFrameProcessor,并将CameraDeviceClient注册进mRangeListener中,因为CameraDeviceClient继承自FilteredListener。关于这个FrameProcessor的作用会在后面的文章中介绍,这里暂时就先跳过了。只需要知道CameraDeviceClient在初始化的时候有建立一个FrameProcessor线程就好了。
所以到这里后,可以看出App openCamera()中,CameraDeviceImpl的RemoteDevice其实就是CameraService的CameraDeviceClient,后面App里对CameraDeviceImpl的操作,会通过AIDL调用到CameraService里的CameraDeviceClient。
Android在hardware/interfaces/camera下定义了几个hidl interface:ICameraProvider、ICameraDevice和ICameraDeviceSession。Hal层必须要去实作这些Interface, 这部分是由各个厂商(比如MTK、高通)去实作的,因此不同厂商的平台在这部分是会有差异的,这里就不细讲了。
前面在openSession()时,getCameraDeviceInterface_V3_x()和CameraDevice::open()会通过Hidl调用到由HAL层对应的实作里。
getCameraDeviceInterface_V3_x()这个接口通过HIDL调用到由Hal层实作的getCameraDeviceInterface_V3_x()函数里面去获取到一个实例化的Cameradevice;CameraDevice::open(),也会通过HIDL调用到HAL层实做的CameraDevice::open()去创建一个实例化的CameraDeviceSession
getCameraDeviceInterface_V3_x()定义在:hardware/interfaces/camera/provider/2.4/ICameraProvider.hal
CameraDevice::open()定义在:hardware/interfaces/camera/device/3.2/ICameraDevice.hal
当APP调用openCamera(),会通AIDL调用到CameraService里面,CameraService又会通过HIDL去获取到HAL层实作的CameraDevice和CameraDeviceSession,并保存在Camera3Device中;APP也会在回调函数里得到一个CameraDeviceImpl实例,这个实例中远程服务(即 RemoteDevice)其实就是CameraSevice中的CameraDeviceClient,前面所说的Camera3Device正是CameraDeviceClient的数据成员,这样就建立起了从APP、framework和HAL层之间的联系,如下图所示:
Google的这张图更全面一些,也更清晰明了