1. 概述
Camera应用接口分为API1/API2,HAL层分为HAL1/HAL3。本文的目的旨在分析 API1/API2如何与HAL1/HAL3对接。
代码可参考cs.android.com进行查阅。
2. Camera API简介
2.1 Camera API1
Camera API1在API Level21时已经被弃用了,新的应用推荐使用API2实现,但由于历史代码原因,很多应用仍然采用API1实现。
2.1.1 API1拍照须知
- 调用open(int)接口获取Camera实例。
- 调用getParameters()获取默认参数。
- 需要时,先通getParameters获取对象并使用setParameters进行修改。
- 调用setDisplayOrientation(int)保证正确的预览方向。
- 开始预览前,需要传递一个初始化后的SurfaceHolder到setPreviewDisplay(android.view.SurfaceHolder)。
- 调用startPreview()开启预览surface,且必须要先于拍照动作前完成。
- 调用takePicture()进行拍照,等待回调返回获取真实的拍照数据。
- 拍照后,预览显示会停止,为了继续拍照,需要再次调用startPreview。
- 调用stopPreview()来停止预览surface的更新。
- 调用release()去释放Camera资源,以及时让其他Camear应用使用。应用需要在Activity.onPause()调用时释放Camera,在Activity.onResume()时重新打开。
2.1.2 API1录像须知
- 如2.1.1所述对Camear进行初始化并开启预览。
- 调用unlock()允许多媒体进程访问Camera。
- 传递Camera实例给MediaRecorder.setCamera(Camera),具体可参考MediaRecorder关于录像的流程。
- 当结束录像时,调用reconnect()重新获取以及重新上锁该Camera。
- 如果需要的话,重新启动预览以拍照和录像。
- 最后如2.1.1所述调用StopPreview()以及release()。
2.1.3 Camera API1公共方法
返回值 | 方法名 | 描述 |
---|---|---|
final void | addCallbackBuffer(byte[] callbackBuffer) | 添加一个预分配的buffer到预览回调buffer队列(preview callback buffer queue) |
final void | autoFocus(Camera.AutoFocusCallback cb) | 开启自对焦并注册回调函数,在对焦时调用 |
final void | cancelAutoFocus() | 取消自动对焦 |
final boolean | enableShutterSound(boolean enabled) | 启动或者禁用快门声 |
static void | getCameraInfo(int cameraId, Camera.CameraInfo cameraInfo) | 返回指定cameraId的Camera信息 |
static int | getNumberOfCameras() | 返回在本设备的摄像头数量 |
Camera.Parameters | getParameters() | 返回Camera服务的当前设定值 |
final void lock() | 重新锁定camera以防其他进程访问 | |
static Camera | open() | 创建一个新的Camera对象并第一次访问后置摄像头 |
static Camera | open(int cameraId) | 创建一个新的Camera对象以访问特定的Camera |
final void | reconnect() | 在其他进程使用完该Camera后,重新连接到Camera服务 |
final void | release() | 断开连接并释放Camera对象资源 |
void | setAutoFocusMoveCallback(Camera.AutoFocusMoveCallback cb) | 设置自动对焦时移动的回调函数,会在自动对焦开始或者停止时调用回调函数 |
final void | setDisplayOrientation(int degrees) | 设置预览时显示的顺时针方向角度 |
final void | setErrorCallback(Camera.ErrorCallback cb) | 注册当错误发生时的回调 |
final void | setFaceDetectionListener(Camera.FaceDetectionListener listener) | 注册监听人脸识别被检测到时的监听器 |
final void | setOneShotPreviewCallback(Camera.PreviewCallback cb) | 设定在下一预览帧在屏幕显示时被调用的回调 |
void | setParameters(Camera.Parameters params) | 修改当前Camera服务的设置 |
final void | setPreviewCallback(Camera.PreviewCallback cb) | 设置在每一个预览帧在屏幕上显示时被调用的回调 |
final void | setPreviewCallbackWithBuffer(Camera.PreviewCallback cb) | 设置每一个使用了addCallbackBuffer(byte[])的buffers的预览帧在屏幕上显示时被调用的回调 |
final void | setPreviewDisplay(SurfaceHolder holder) | 设置用于预览的Surface |
final void | setPreviewTexture(SurfaceTexture surfaceTexture) | 设置用于预览的SurfaceTexture |
final void | setZoomChangeListener(Camera.OnZoomChangeListener listener) | 注册一个监听camera驱动进行平滑的放大缩小时的监听器 |
final void | startFaceDetection() | 开启人脸识别 |
final void | startPreview() | 开启捕捉并将预览帧绘于屏幕上,即开启预览 |
final void | startSmoothZoom(int value) | 根据指定值进行平滑的放大缩小 |
final void | stopFaceDetection() | 停止人脸识别 |
final void | stopPreview() | 停止预览,如需再次启动,需要调用startPreview() |
final void | stopSmoothZoom() | 停止平滑放大缩小 |
final void | takePicture(Camera.ShutterCallback shutter, Camera.PictureCallback raw, Camera.PictureCallback postview, Camera.PictureCallback jpeg) | Triggers an asynchronous image capture.触发一次异步的图片捕捉 |
final void | takePicture(Camera.ShutterCallback shutter, Camera.PictureCallback raw, Camera.PictureCallback jpeg) | 和takePicture(Shutter, raw, null, jpeg)相同 |
final void | unlock() | 解锁Camera以允许其他进程进行访问 |
2.2 Camera API2
从API Level 21起,Google推荐使用Camera2接口与相机进行交互,与API1相比,API2能够实现更为细腻的控制。
2.2.1 Camera API2须知
android.hardware.camera2包提供了一个interface接口,用于多个独立的Camera设备与Android设备进行连接。Camera2将Camera设备设计成一个流水线模型(pipeline),它通过输入请求(input requests),来拍摄单帧画面,并且每一个请求只拍摄一个图像。当处理完毕后,会对应输入请求随之输出一个拍摄结果(capture result)元数据包,称之为metadata packet以及一系列的输出图像数据。这些请求是按输入的顺序进行排列的,多个请求发出时,可能会同时处于传输中,称为in flight。考虑到Camera设备设计成一个具有多个阶段的流水线模型,当有多个请求传输时,需要严格保证帧率达到最大。 当需要遍历,访问以及打开一个有效的Camera设备,用户需要获取一个CameraManager实例。每一个Camera设备都会提供一系列的静态属性用于描述该硬件设备,可用选项以及输出参数。这些参数可以通过getCameraCharacteristics(String)接口获取并将信息保存到CameraCharacteristics对象中。 当需要开始拍照时,应用必须要首先创建一个捕获会话(capture session),并且需要一系列的输出Surfaces提供给Camera设备,对应的方法是createCaptureSession(SessionConfiguration)。每个Surface必须要经过预先配置,比如适当的大小和格式,并且要和Camera设备对应。目标Surface能够被多个类获取,包括SurfaceView, SurfaceTexture, MediaCodec, MediaRecorder, Allocation以及 ImageReader。 一般来说,Camera的预览图像会被发送到SurfaceView或者TextureView, 为DngCreator捕获的Jpeg图片或者RAW数据能够通过支持Jpeg或者RAW Sensor格式的ImageReader获得。对于RenderScript,OpenGL Es, Native代码,Camera数据最好能够以YUV格式进行分配,而SurfaceTexture和ImageReader可以使用YUV_420_888格式保存。 应用此后需要创建一个CaptureRequest,通过定义拍照参数来决定Camera设备的图片质量。CaptureRequest还会列举本次拍照应当输出到的目标Surface。CameraDevice拥有一个工厂方法用以在特的情形下创建合适的Request builder。当CaptureRequest成设置后,它就能够被传到只拍一张照片或者连续拍照Capture Session中处理,两种方法都能够接受一连串的Reuqests,但连续的请求会比单个请求权限低。所以如果这两者同时发生时,单个拍照会在连续拍照之前进行处理。当处理完一个请求时,Camera设备会创建一个TotalCaptureResult对象,它包括在拍照时刻Camera设备的状态信息以及最终使用的设置。如果参数之间需要舍入或者有冲突无法避免的时候,Camera设备将发送一帧图像信息到输出Surfaces,这些行为是异步的,有时候会延迟。
2.2.2 Camera API2公共方法
返回值 | 方法名 | 描述 |
---|---|---|
CameraCharacteristics | getCameraCharacteristics(String cameraId) | 访问camera设备的属性 |
String[] | getCameraIdList() | 返回当前连接的camera设备id |
Set<Set<String>> |
getConcurrentCameraIds() | 返回能同时使用的camera设备id |
boolean | isConcurrentSessionConfigurationSupported(Map<String, SessionConfiguration> cameraIdAndSessionConfig) |
检查提供的camera设备集合和对应的会话配置是否能够同时配置 |
void | openCamera(String cameraId, CameraDevice.StateCallback callback, Handler handler) | 打开指定Id的camera设备 |
void | openCamera(String cameraId, Executor executor, CameraDevice.StateCallback callback) | 打开指定Id的camera设备 |
void | registerAvailabilityCallback(Executor executor, CameraManager.AvailabilityCallback callback) | 注册当Camera设备有效时的回调 |
void | registerAvailabilityCallback(CameraManager.AvailabilityCallback callback, Handler handler) | 注册当Camera设备有效时的回调 |
void | registerTorchCallback(Executor executor, CameraManager.TorchCallback callback) | Register a callback to be notified about torch mode status.注册通知闪光灯模式状态的回调 |
void | registerTorchCallback(CameraManager.TorchCallback callback, Handler handler) | 注册通知闪光灯模式状态的回调 |
void | setTorchMode(String cameraId, boolean enabled) | 设置指定camera ID的闪光灯模式且不打开该设备 |
void | unregisterAvailabilityCallback(CameraManager.AvailabilityCallback callback) | 去除最近添加的回调,该回调不再接受连接或者断开回调 |
void | unregisterTorchCallback(CameraManager.TorchCallback callback) | 去除最近添加的闪光灯模式回调 |
2.3 CameraAgent
一个Camera应用可以使用API1或者API2实现,为了兼容这两种实现,且以一种更简洁的方式帮助应用进行切换,Android提供了CameraAgent(Camera代理)来提供这样的实现。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# frameworks/ex/camera2/portability/src/com/android/ex/camera2/portability/CameraAgentFactory.java
/*
* CameraAgentFactory使用了简单工厂模式,通过传参选择类型
*/
public static synchronized CameraAgent getAndroidCameraAgent(Context context, CameraApi api) {
api = validateApiChoice(api);
if (api == CameraApi.API_1) {
if (sAndroidCameraAgent == null) {
sAndroidCameraAgent = new AndroidCameraAgentImpl();
sAndroidCameraAgentClientCount = 1;
} else {
++sAndroidCameraAgentClientCount;
}
return sAndroidCameraAgent;
} else { // API_2
if (highestSupportedApi() == CameraApi.API_1) {
throw new UnsupportedOperationException("Camera API_2 unavailable on this device");
}
if (sAndroidCamera2Agent == null) {
sAndroidCamera2Agent = new AndroidCamera2AgentImpl(context);
sAndroidCamera2AgentClientCount = 1;
} else {
++sAndroidCamera2AgentClientCount;
}
return sAndroidCamera2Agent;
}
}
从上述代码可知,当传参CameraApi.API_1时,使用AndroidCameraAgentImpl,否则使用API2,AndroidCamera2AgentImpl。
CameraAgent将常用的操作集成起来,通过CameraAgent以及内部类CameraAgent.CameraProxy可以发送请求和信息处理线,包括如:
CameraAgent:
- openCamera
- closeCamera
- reconnect
CameraAgent.CameraProxy:
- setPreviewTexture
- setPreviewTextureSync
- setPreviewDisplay
- startPreview
- startPreviewWithCallback
- stopPreview
- addCallBackBuffer
- cancelAutoFocus
- setDisplayOrientation
- setJpegOrientation
- enableShutterSound
CameraAgent并没有实现这些具体实现,而是交给AndroidCameraAgentImpl实现(API1对应AndroidCameraAgentImpl, API2对应AndroidCamera2AgentImpl)。每个具体实现会启动HandlerThread线程,专门用于处理这些信息。以AndroidCameraAgentImpl的openCamera为例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# frameworks/ex/camera2/portability/src/com/android/ex/camera2/portability/CameraAgent.java
/*
* CameraAgent
*/
public void openCamera(final Handler handler, final int cameraId,
final CameraOpenCallback callback) {
try {
getDispatchThread().runJob(new Runnable() {
@Override
public void run() {
//发送类型为OPEN_CAMERA的消息
getCameraHandler().obtainMessage(CameraActions.OPEN_CAMERA, cameraId, 0,
CameraOpenCallbackForward.getNewInstance(handler, callback)).sendToTarget();
}
});
} catch (final RuntimeException ex) {
getCameraExceptionHandler().onDispatchThreadException(ex);
}
}
# frameworks/ex/camera2/portability/src/com/android/ex/camera2/portability/AndroidCameraAgentImpl.java
@Override
public void handleMessage(final Message msg) {
super.handleMessage(msg);
....
int cameraAction = msg.what;
try {
switch (cameraAction) {
case CameraActions.OPEN_CAMERA: {
final CameraOpenCallback openCallback = (CameraOpenCallback) msg.obj;
final int cameraId = msg.arg1;
if (mCameraState.getState() != AndroidCameraStateHolder.CAMERA_UNOPENED) {
openCallback.onDeviceOpenedAlready(cameraId, generateHistoryString(cameraId));
break;
}
Log.i(TAG, "Opening camera " + cameraId + " with camera1 API");
//使用Camera API1的方式打开camera
mCamera = android.hardware.Camera.open(cameraId);
if (mCamera != null) {
mCameraId = cameraId;
mParameterCache = new ParametersCache(mCamera);
mCharacteristics = AndroidCameraDeviceInfo.create().getCharacteristics(cameraId);
mCapabilities = new AndroidCameraCapabilities(
mParameterCache.getBlocking());
mCamera.setErrorCallback(this);
mCameraState.setState(AndroidCameraStateHolder.CAMERA_IDLE);
if (openCallback != null) {
CameraProxy cameraProxy = new AndroidCameraProxyImpl(
mAgent, cameraId, mCamera, mCharacteristics, mCapabilities);
openCallback.onCameraOpened(cameraProxy);
}
} else {
if (openCallback != null) {
openCallback.onDeviceOpenFailure(cameraId, generateHistoryString(cameraId));
}
}
break;
}
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# frameworks/ex/camera2/portability/src/com/android/ex/camera2/portability/AndroidCamera2AgentImpl.java
@Override
public void handleMessage(final Message msg) {
super.handleMessage(msg);
Log.v(TAG, "handleMessage - action = '" + CameraActions.stringify(msg.what) + "'");
int cameraAction = msg.what;
try {
switch (cameraAction) {
case CameraActions.OPEN_CAMERA:
case CameraActions.RECONNECT: {
CameraOpenCallback openCallback = (CameraOpenCallback) msg.obj;
int cameraIndex = msg.arg1;
if (mCameraState.getState() > AndroidCamera2StateHolder.CAMERA_UNOPENED) {
openCallback.onDeviceOpenedAlready(cameraIndex,
generateHistoryString(cameraIndex));
break;
}
mOpenCallback = openCallback;
mCameraIndex = cameraIndex;
mCameraId = mCameraDevices.get(mCameraIndex);
Log.i(TAG, String.format("Opening camera index %d (id %s) with camera2 API",
cameraIndex, mCameraId));
if (mCameraId == null) {
mOpenCallback.onCameraDisabled(msg.arg1);
break;
}
//使用Camera API2打开摄像头
mCameraManager.openCamera(mCameraId, mCameraDeviceStateCallback, this);
break;
}
3. API与HAL层对接
3.1 HAL1
HAL1最开始的设计是对接API1,而后续产生的API2虽然对标HAL3,但也需要兼容HAL1。最方便的方法是将API2和API1进行一个转换来支持HAL1。以打开Camera的操作为例,API1调用HAL1示意图如下:
API2在使用HAL1前,进行了转换。层层调用后,最终调用到Camera API1的接口。因此只绘出转换部分:
3.2 HAL3
HAL3通过makeClient来分辨使用的是哪一套API接口,流程图如下所示:
以API1调用HAL3的流程如下:
以API2调用HAL3的流程如下:
HAL3的调用流程较为类似,应用调用打开Camera的操作,经历了Apk,CameraService以及HAL层Camera服务的流程。图中省去了进程间的Binder通信流程,可以看出,主要的几个关键点在于:
3.2.1 getDevcieVersion
在调用关键的makeClient前,connectHelper中调用getDeviceVersion来判断到底是使用哪一套HAL接口,关键代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# frameworks/av/services/camera/libcameraservice/CameraService.cpp
# inside Function ConnectHelper
...
int facing = -1;
//获取设备HAL版本
int deviceVersion = getDeviceVersion(cameraId, /*out*/&facing);
if (facing == -1) {
ALOGE("%s: Unable to get camera device \"%s\" facing", __FUNCTION__, cameraId.string());
return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
"Unable to get camera device \"%s\" facing", cameraId.string());
}
sp<BasicClient> tmp = nullptr;
//关键分水岭,初始化halVersion为-1
if(!(ret = makeClient(this, cameraCb, clientPackageName, clientFeatureId,
cameraId, api1CameraId, facing,
clientPid, clientUid, getpid(),
halVersion, deviceVersion, effectiveApiLevel,
/*out*/&tmp)).isOk()) {
return ret;
}
client = static_cast<CLIENT*>(tmp.get());
...
# getDeviceVersion
int CameraService::getDeviceVersion(const String8& cameraId, int* facing) {
ATRACE_CALL();
int deviceVersion = 0;
status_t res;
hardware::hidl_version maxVersion{0,0};
//获取HAL支持最高版本
res = mCameraProviderManager->getHighestSupportedVersion(cameraId.string(),
&maxVersion);
if (res != OK) return -1;
deviceVersion = HARDWARE_DEVICE_API_VERSION(maxVersion.get_major(), maxVersion.get_minor());
hardware::CameraInfo info;
if (facing) {
res = mCameraProviderManager->getCameraInfo(cameraId.string(), &info);
if (res != OK) return -1;
*facing = info.facing;
}
return deviceVersion;
}
3.2.2 makeClient
deviceVersion与API的版将决定Client的类型。HAL1与API1的配置会新建CameraClient(HAL1和API2组合实质进行了转换,只走HAL1+API1),HAL3与API1的组合会新建Camera2Client,HAL3和API2的组合则新建CameraDeviceClient。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
Status CameraService::makeClient(const sp<CameraService>& cameraService,
const sp<IInterface>& cameraCb, const String16& packageName,
const std::optional<String16>& featureId, const String8& cameraId, int api1CameraId,
int facing, int clientPid, uid_t clientUid, int servicePid, int halVersion,
int deviceVersion, apiLevel effectiveApiLevel,
/*out*/sp<BasicClient>* client) {
//初始化halVersion小于0
if (halVersion < 0 || halVersion == deviceVersion) {
/*
* 此处通过deviceVersion类型创建client。
* HAL1: CameraClient
* HAL3: Camera2Client
*/
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, featureId,
api1CameraId, facing, clientPid, clientUid,
getpid());
} 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:
case CAMERA_DEVICE_API_VERSION_3_5:
case CAMERA_DEVICE_API_VERSION_3_6:
if (effectiveApiLevel == API_1) { // Camera1 API route
sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
*client = new Camera2Client(cameraService, tmp, packageName, featureId,
cameraId, api1CameraId,
facing, clientPid, clientUid,
servicePid);
} else { // Camera2 API route
sp<hardware::camera2::ICameraDeviceCallbacks> tmp =
static_cast<hardware::camera2::ICameraDeviceCallbacks*>(cameraCb.get());
*client = new CameraDeviceClient(cameraService, tmp, packageName, featureId,
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 {
// A particular HAL version is requested by caller. Create CameraClient
// based on the requested HAL version.
if (deviceVersion > CAMERA_DEVICE_API_VERSION_1_0 &&
halVersion == CAMERA_DEVICE_API_VERSION_1_0) {
// Only support higher HAL version device opened as HAL1.0 device.
sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
*client = new CameraClient(cameraService, tmp, packageName, featureId,
api1CameraId, facing, clientPid, clientUid,
servicePid);
} else {
// Other combinations (e.g. HAL3.x open as HAL2.x) are not supported yet.
ALOGE("Invalid camera HAL version %x: HAL %x device can only be"
" opened as HAL %x device", halVersion, deviceVersion,
CAMERA_DEVICE_API_VERSION_1_0);
return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
"Camera device \"%s\" (HAL version %d) cannot be opened as HAL version %d",
cameraId.string(), deviceVersion, halVersion);
}
}
return Status::ok();
}
3.2.3 CameraClient
由上述可得,HAL1对应CameraClient,HAL3对应Camera2Client或者CameraDeviceClient。Camera2Client以及CameraDeviceClient都继承了Camear2ClientBase,而这个父类使用的是Camera3Device,表明这是HAL3。Camera3Device实现了一个内部类名为HalInterface,与HAL层的交互均依靠该类实现。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
template <typename TClientBase>
Camera2ClientBase<TClientBase>::Camera2ClientBase(
const sp<CameraService>& cameraService,
const sp<TCamCallbacks>& remoteCallback,
const String16& clientPackageName,
const std::optional<String16>& clientFeatureId,
const String8& cameraId,
int api1CameraId,
int cameraFacing,
int clientPid,
uid_t clientUid,
int servicePid):
TClientBase(cameraService, remoteCallback, clientPackageName, clientFeatureId,
cameraId, api1CameraId, cameraFacing, clientPid, clientUid, servicePid),
mSharedCameraCallbacks(remoteCallback),
mDeviceVersion(cameraService->getDeviceVersion(TClientBase::mCameraIdStr)),
mDevice(new Camera3Device(cameraId)),//此处使用Camera3Device。
mDeviceActive(false), mApi1CameraId(api1CameraId)
{
ALOGI("Camera %s: Opened. Client: %s (PID %d, UID %d)", cameraId.string(),
String8(clientPackageName).string(), clientPid, clientUid);
mInitialClientPid = clientPid;
LOG_ALWAYS_FATAL_IF(mDevice == 0, "Device should never be NULL here.");
}
而HAL1的CameraClient则是通过CameraHardwareInterface去实现的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# frameworks/av/services/camera/libcameraservice/api1/CameraClient.cpp
status_t CameraClient::initialize(sp<CameraProviderManager> manager,
const String8& /*monitorTags*/) {
int callingPid = CameraThreadState::getCallingPid();
status_t res;
LOG1("CameraClient::initialize E (pid %d, id %d)", callingPid, mCameraId);
// Verify ops permissions
res = startCameraOps();
if (res != OK) {
return res;
}
char camera_device_name[10];
snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId);
//新建CamearHardwareInterface,其实现可参考hardware/interfaces/camera/device/1.0/default/CameraDevice.cpp
mHardware = new CameraHardwareInterface(camera_device_name);
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;
}
mHardware->setCallbacks(notifyCallback,
dataCallback,
dataCallbackTimestamp,
handleCallbackTimestampBatch,
(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;
}