Andriod Camera之Open Camera

前言
打开相机的第一步便是在APP里去调用openCamera(),去打开指定的Camera设备(通过Device id指定),并建立起连接。APP通过openCamera()调用成功后,可以获取到一个已经初始化过的CameraDeviceImp,它表示一个已经打开的Camera设备,后续APP便可以通过CameraDeviceImp去执行各种操作,以控制相机的各种行为。

主要流程
下面简单地介绍一些openCamera的流程,希望可以对整个的过程有一个大概的了解, openCamera()的主要flow如下图所示

Andriod Camera之Open Camera_第1张图片
可以将这个过程划分为3个部分来看,分别是App、native framework、Hal层,接下来也将从这三个部分去分析openCamera()这个过程
一、App部分:
对应上图中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()里做的事情:

1、利用获取的相机设备信息创建CameraDeviceImpl实例

android.hardware.camera2.impl.CameraDeviceImpl deviceImpl =
                    new android.hardware.camera2.impl.CameraDeviceImpl(
                        cameraId,
                        callback,
                        executor,
                        characteristics,
                        physicalIdsToChars,
                        mContext.getApplicationInfo().targetSdkVersion,
                        mContext)

但是这个deviceImpl里还有一个重要的成员-------->mRemoteDevice 没有初始化,它是这个deviceImpl的远端服务,其实后续APP对deviceImpl的操作都会转化为对这个远端服务mRemoteDevice的操作,而这个远端服务需要通过CameraService这个系统服务去获取到。
2、调用远程CameraService获取当前相机的远程服务

cameraUser=CameraService.connectDevice(
              callbacks, 		  
              cameraId,
               mContext.getOpPackageName(),  
               mContext.getAttributionTag(), 
               uid,
               oomScoreOffset, 
               mContext.getApplicationInfo().targetSdkVersion);

3、将获取到的远程服务设置到CameraDeviceImpl实例中
----------> deviceImpl.setRemoteDevice(cameraUser)
这里面最终会通过前面APP传下来的回调函数—> callback.onCameraOpened() ,返回这个CameraDeviceImpl

4、返回CameraDeviceImpl实例,即deviceImpl,它代表一个已经打开的相机设备。
所以是App调用的CameraManager的openCamera()方法,调用成功后,在回调函数里可以得到一个CameraDeviceImpl的实例,这个实例里包含其对应的远端服务。
接下来看一看这其中所说的“调用远程CameraService获取当前相机的远程服务”是在做什么。

二、native framework
在App部分其中有一步叫做:调用远程CameraService获取当前相机的远程服务。
这一步其实是通过AIDL调用到了CameraService::connectDevice(),这里就进入了native framework层,这个过程对应于图中CameraService.cpp到CameraProviderManager.cpp这一部分 ,接下来看看这个过程中经历的事情。这里面有涉及到几个class:CameraService、CameraDeviceClient、Camera2ClientBase、Camera3Device、CameraProviderManager,它们之间的关系如下:

Andriod Camera之Open Camera_第2张图片
通过这部分的flow,我们可以看到在native framework里面做的事情大概可以总结如下:

1、handleEvictionsEvicted
处理相机的抢占机制:
https://blog.csdn.net/wk314061331/article/details/125783531?spm=1001.2014.3001.5502

2、创建CameraDeviceClient对象,并初始化
即CameraDeviceClient::initialize()。
这里面会调用到Camera2ClientBase::initialize(),而Camera3Device继承自Camera2ClientBase,从前面关系图里可以看出,其实可以看出来Camera3Device就是CameraDeviceClient的成员变量。所以这里面其实是会调用到Camera3Device::initialize()。

3、初始化Camera3Device
即Camera3Device::initialize()。这里面最重要的一步便是CameraProviderManager::openSession(),接下来看看这个openSession()里面做的事情:
findDeviceInfoLocked():
根据CameraDevice的版本,从所有Provider中,找到对应的DeviceInfo。这些信息是在CameraService起来时已经保存好的,可以参考Android Camera之CameraServer的启动过程
startProviderInterface():
根据刚刚deviceInfo中对应的provider的信息,获取到对应CameraProvider服务。
startDeviceInterface():
通过CameraProvider的getCameraDeviceInterface_V3_x()实例化一个CameraDevice。这一步是通过HIDL调用到了Hal层,这个CameraDevice是Hal层实作的,和前面APP部分的CameraDevice有所不同,也有所联系
interface->open()
这个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

4 、创建FrameProcessor
即创建CameraDeviceClient::mFrameProcessor,并将CameraDeviceClient注册进mRangeListener中,因为CameraDeviceClient继承自FilteredListener。关于这个FrameProcessor的作用会在后面的文章中介绍,这里暂时就先跳过了。只需要知道CameraDeviceClient在初始化的时候有建立一个FrameProcessor线程就好了。

5、返回CameraDeviceClient对象给CameraManager.
所以到这里后,可以看出App openCamera()中,CameraDeviceImpl的RemoteDevice其实就是CameraService的CameraDeviceClient,后面App里对CameraDeviceImpl的操作,会通过AIDL调用到CameraService里的CameraDeviceClient。

三 、Hal层
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的这张图更全面一些,也更清晰明了
Andriod Camera之Open Camera_第3张图片

你可能感兴趣的:(camera,android)