目录
其实很简单,纸老虎,一捅就破。
相机预览时,app 应用会调用 framework 的 java 接口,framework 又会调用 native camera service,然后 camera service 再调用 camera hal 的接口,最后对 driver 发指令。层层调用,service 只是中间透传环节,关键在于开始的 framework 流程与最后的 hal 接口实现,那么我们就从头看起,更好理解。

一般来说,camera service (c++ 代码) 也在 framework 目录下,但 service 是起到中间传递的作用,所以这里主要讲的是 java 类。camera service 后续根据需要发表博客。
Camera Framework 核心类如下:

文件目录及每个类的作用已注明。这里参数的获取与传递依靠 MetaData,关于 MetaData 的定义、内存分布以及在 native 侧的使用方式见本人写的另一篇博客。
Camera MetaData介绍_独家原创_alibli的博客-CSDN博客
在 framework 层分析的好处就是现在可以更加具体到实际的 Metadata。
CameraCharacteristics 类里定义了大量元数据类似,我们会在 Camera open 之前获取这些元数据,简单点说,获取参数的可设置值或范围。那么常用的 key 有哪些呢?如下:

当然这里只举常用的一类,比如 SENSOR_INFO_PIXEL_ARRAY_SIZE,相关的还有 SENSOR_INFO_ACTIVE_ARRAY_SIZE、SCALER_CROP_REGION 等等。
核心流程:open camera 之前我们获取到了可以各属性可设置的范围,在有效范围内,创建 session 发 request 就可以传入我们实际要设置的值,设置结果则是查询 CaptureResult 的 key。那么你可能有疑惑,整个流程是啥样的呢?下面来打消你的疑惑。

关键接口入参与返回值罗列:
- // 以下接口只列举入参最多的一个
-
- public CameraCharacteristics getCameraCharacteristics(@NonNull String cameraId)
- throws CameraAccessException
-
- public void openCamera(@NonNull String cameraId,
- int oomScoreOffset,
- @NonNull @CallbackExecutor Executor executor,
- @NonNull final CameraDevice.StateCallback callback)
- throws CameraAccessException
-
- // 旧版已废弃
- @Deprecated
- public abstract void createCaptureSession(@NonNull List
outputs, - @NonNull CameraCaptureSession.StateCallback callback,
- @Nullable Handler handler)
- throws CameraAccessException;
-
- // 新版一个接口一统江湖
- public void createCaptureSession(SessionConfiguration config)
- throws CameraAccessException
-
- // SessionConfiguration构造函数
- public SessionConfiguration(@SessionMode int sessionType,
- @NonNull List
outputs, - @NonNull @CallbackExecutor Executor executor,
- @NonNull CameraCaptureSession.StateCallback cb)
-
- public CaptureRequest.Builder createCaptureRequest(@RequestTemplate int templateType,
- Set
physicalCameraIdSet) - throws CameraAccessException
-
- public abstract int setRepeatingRequest(@NonNull CaptureRequest request,
- @Nullable CaptureCallback listener,
- @Nullable Handler handler)
- throws CameraAccessException
应用层调用 getSystemService 即可获取 CameraManager,CameraManger 是 framework 中总体管理者,通过他的 openCamera(...) 接口创建 CameraDevice 示例,因为 openCamera(...) 入参传入了 cameraId 以及 StateCallback 实例。注意,在 openCamera(...) 之前会调用 manager.getCameraCharacteristics(cameraId) 方法,这样就获取了 Camera 设备支持的参数设置范围。

当 StateCallback 的 onOpened(...) 回调被调用时,说明相机开启完成,这时候创建 CameraCaptureSession 实例。然后创建 CaptureRequest 实例,session 调用 setRepeatingRequest(...) 将 CaptureRequest 实例下发到 hal 层。
最后 CaptureCallback 会返回获取到的数据与状态。
来看 camera framework(java) 与 camera service (c++) 之间的联系。CameraManager 的 openCamera 接口最终调用自己的 openCameraDeviceUserAsync(...) 方法:
- /**
- * Helper for opening a connection to a camera with the given ID.
- *
- * @param cameraId The unique identifier of the camera device to open
- * @param callback The callback for the camera. Must not be null.
- * @param executor The executor to invoke the callback with. Must not be null.
- * @param uid The UID of the application actually opening the camera.
- * Must be USE_CALLING_UID unless the caller is a service
- * that is trusted to open the device on behalf of an
- * application and to forward the real UID.
- *
- * @throws CameraAccessException if the camera is disabled by device policy,
- * too many camera devices are already open, or the cameraId does not match
- * any currently available camera device.
- *
- * @throws SecurityException if the application does not have permission to
- * access the camera
- * @throws IllegalArgumentException if callback or handler is null.
- * @return A handle to the newly-created camera device.
- *
- * @see #getCameraIdList
- * @see android.app.admin.DevicePolicyManager#setCameraDisabled
- */
- private CameraDevice openCameraDeviceUserAsync(String cameraId,
- CameraDevice.StateCallback callback, Executor executor, final int uid,
- final int oomScoreOffset) throws CameraAccessException {
- CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
- CameraDevice device = null;
- Map
physicalIdsToChars = - getPhysicalIdToCharsMap(characteristics);
- synchronized (mLock) {
-
- ICameraDeviceUser cameraUser = null;
- android.hardware.camera2.impl.CameraDeviceImpl deviceImpl =
- new android.hardware.camera2.impl.CameraDeviceImpl(
- cameraId,
- callback,
- executor,
- characteristics,
- physicalIdsToChars,
- mContext.getApplicationInfo().targetSdkVersion,
- mContext);
-
- ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks();
-
- try {
- ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
- if (cameraService == null) {
- throw new ServiceSpecificException(
- ICameraService.ERROR_DISCONNECTED,
- "Camera service is currently unavailable");
- }
- cameraUser = cameraService.connectDevice(callbacks, cameraId,
- mContext.getOpPackageName(), mContext.getAttributionTag(), uid,
- oomScoreOffset, mContext.getApplicationInfo().targetSdkVersion);
- } catch (ServiceSpecificException e) {
- if (e.errorCode == ICameraService.ERROR_DEPRECATED_HAL) {
- throw new AssertionError("Should've gone down the shim path");
- } else if (e.errorCode == ICameraService.ERROR_CAMERA_IN_USE ||
- e.errorCode == ICameraService.ERROR_MAX_CAMERAS_IN_USE ||
- e.errorCode == ICameraService.ERROR_DISABLED ||
- e.errorCode == ICameraService.ERROR_DISCONNECTED ||
- e.errorCode == ICameraService.ERROR_INVALID_OPERATION) {
- // Received one of the known connection errors
- // The remote camera device cannot be connected to, so
- // set the local camera to the startup error state
- deviceImpl.setRemoteFailure(e);
-
- if (e.errorCode == ICameraService.ERROR_DISABLED ||
- e.errorCode == ICameraService.ERROR_DISCONNECTED ||
- e.errorCode == ICameraService.ERROR_CAMERA_IN_USE) {
- // Per API docs, these failures call onError and throw
- throwAsPublicException(e);
- }
- } else {
- // Unexpected failure - rethrow
- throwAsPublicException(e);
- }
- } catch (RemoteException e) {
- // Camera service died - act as if it's a CAMERA_DISCONNECTED case
- ServiceSpecificException sse = new ServiceSpecificException(
- ICameraService.ERROR_DISCONNECTED,
- "Camera service is currently unavailable");
- deviceImpl.setRemoteFailure(sse);
- throwAsPublicException(sse);
- }
-
- // TODO: factor out callback to be non-nested, then move setter to constructor
- // For now, calling setRemoteDevice will fire initial
- // onOpened/onUnconfigured callbacks.
- // This function call may post onDisconnected and throw CAMERA_DISCONNECTED if
- // cameraUser dies during setup.
- deviceImpl.setRemoteDevice(cameraUser);
- device = deviceImpl;
- }
-
- return device;
- }
来看核心的部分:
ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
这行即获取到 ICameraService 对象,这个类是什么呢?在 camera framework 中以 I 开头的基本都是 aidl 文件,这个文件就在 framework/av/camera/aidl/android/hardware/ICameraService.aidl。aidl 声明了接口,具体实现就对应在 camera service 中,这样就跟 native 层联系起来了。
接下来调用 connetDevice,里面传入了 callbacks,cameraId 等,返回 cameraUser:
- cameraUser = cameraService.connectDevice(callbacks, cameraId,
- mContext.getOpPackageName(), mContext.getAttributionTag(), uid,
- oomScoreOffset, mContext.getApplicationInfo().targetSdkVersion);
cameraUser 又是 ICameraDeviceUser 对象的实例,I 打头又是 aidl 类,对应实现是在 camera service 侧的 BnCameraDeviceUser,这个类最终被 CameraDeviceClient 继承。传入的 callback 则是 ICameraDeviceCallbacks 类型,这个对应 service 侧的 BnCameraDeviceCallbacks,被 ServiceCallback 继承。
- deviceImpl.setRemoteDevice(cameraUser);
- device = deviceImpl;
deviceImpl 是 CameraDeviceImpl 实例,CameraDeviceImpl 是抽象类 CameraDevice 的具体实现类。setRemoteDevice 传入 cameraUser 会被用于创建 ICameraDeviceUserWrapper 对象,Wrapper 代表是 ICameraDeviceUser 的包装类。这里 mRemoteDevice 即是 framework 与 service 之间沟通的关键桥梁。
- // CameraDeviceImpl.java setRemoteDevice(...)方法中
- mRemoteDevice = new ICameraDeviceUserWrapper(remoteDevice);
欢迎交流~