Android中Camera的调用流程可分为以下几个层次:
Package->Framework->JNI->Camera(cpp)--(binder)-->CameraService->Camera HAL->Camera Driver
以拍照流程为例:
1. 各个参数设置完成,对焦完成后,位于Package的Camera.java会调用Framework中Camera.java的takePicture函数,如下:
此函数保存Package层传下的callback函数,同时调用JNI层的native_takePicture
2. JNI层的native_takePicture自己并没有做太多事情,仅仅是通过./base/core/jni/android_hardware_Camera.cpp中的android_hardware_Camera_takePicture,简单地调用./av/camera/Camera.cpp中的takePicture函数。此前已经把JNI中的一个对象注册成了Camera.cpp的listener
3. 位于frameworks/base/libs/camera是向CameraService请求服务的客户端,但它本身也继承了一个BnCameraClient类,用于CameraService回调自己。
从上面的接口定义可以看到,这个类就是用于回调。
Camera.cpp的takePicture函数是利用open Camera时得到的ICamera对象来继续调用takePicture
4. 接下来通过binder转到另一个进程CameraService中的处理。CameraService中之前已经实例化了一个HAL层的 CameraHardware,并把自己的data callback传递给了CameraHardware,这些工作都是由CameraService的内部类Client来完成的,这个Client类继承自BnCamera,是真正提供Camera操作API的类
5. 然后自然是调用HAL层CameraHardware的takePicture函数。从HAL层向下就不是Android的标准代码了,各个厂商有自己不同的实现。但思路应该都是相同的:Camera遵循V4L2架构,利用ioctl发送VIDIOC_DQBUF命令得到有效的图像数据,接着回调HAL层的data callback接口以通知CameraService,CameraService会通过binder通知Camera.cpp,如下:
6. Camera.cpp会继续通知它的listener:
7. 而这个listener就是我们的JNI层的JNICameraContext对象了:
8. 可以看到JNI层最终都会调用来自java层的函数postEventFromNative,这个函数会发送对应的消息给自己的 eventhandler,收到消息后就会根据消息的类型回调Package层Camera.java最初传下来的callback函数。至此,我们就在最上层拿到了图像数据。
Package->Framework->JNI->Camera(cpp)--(binder)-->CameraService->Camera HAL->Camera Driver
以拍照流程为例:
1. 各个参数设置完成,对焦完成后,位于Package的Camera.java会调用Framework中Camera.java的takePicture函数,如下:
1 |
public final void takePicture(ShutterCallback
shutter, PictureCallback raw, |
2 |
PictureCallback
postview, PictureCallback jpeg) { |
3 |
mShutterCallback
= shutter; |
4 |
mRawImageCallback
= raw; |
5 |
mPostviewCallback
= postview; |
6 |
mJpegCallback
= jpeg; |
7 |
native_takePicture(); |
8 |
} |
此函数保存Package层传下的callback函数,同时调用JNI层的native_takePicture
2. JNI层的native_takePicture自己并没有做太多事情,仅仅是通过./base/core/jni/android_hardware_Camera.cpp中的android_hardware_Camera_takePicture,简单地调用./av/camera/Camera.cpp中的takePicture函数。此前已经把JNI中的一个对象注册成了Camera.cpp的listener
3. 位于frameworks/base/libs/camera是向CameraService请求服务的客户端,但它本身也继承了一个BnCameraClient类,用于CameraService回调自己。
1 |
class ICameraClient: public IInterface |
2 |
{ |
3 |
public : |
4 |
DECLARE_META_INTERFACE(CameraClient); |
5 |
6 |
virtual void notifyCallback(int32_t
msgType, int32_t ext1, int32_t ext2) = 0 ; |
7 |
virtual void dataCallback(int32_t
msgType, const sp<IMemory>&
data) = 0 ; |
8 |
virtual void dataCallbackTimestamp(nsecs_t
timestamp, int32_t msgType, const sp<IMemory>&
data) = 0 ; |
9 |
}; |
从上面的接口定义可以看到,这个类就是用于回调。
Camera.cpp的takePicture函数是利用open Camera时得到的ICamera对象来继续调用takePicture
4. 接下来通过binder转到另一个进程CameraService中的处理。CameraService中之前已经实例化了一个HAL层的 CameraHardware,并把自己的data callback传递给了CameraHardware,这些工作都是由CameraService的内部类Client来完成的,这个Client类继承自BnCamera,是真正提供Camera操作API的类
5. 然后自然是调用HAL层CameraHardware的takePicture函数。从HAL层向下就不是Android的标准代码了,各个厂商有自己不同的实现。但思路应该都是相同的:Camera遵循V4L2架构,利用ioctl发送VIDIOC_DQBUF命令得到有效的图像数据,接着回调HAL层的data callback接口以通知CameraService,CameraService会通过binder通知Camera.cpp,如下:
01 |
void CameraService::Client::dataCallback(int32_t
msgType, |
02 |
const sp<IMemory>&
dataPtr, void *
user) { |
03 |
LOG2( "dataCallback(%d)" ,
msgType); |
04 |
05 |
sp<Client>
client = getClientFromCookie(user); |
06 |
if (client
== 0) return ; |
07 |
if (!client->lockIfMessageWanted(msgType)) return ; |
08 |
09 |
if (dataPtr
== 0) { |
10 |
LOGE( "Null
data returned in data callback" ); |
11 |
client->handleGenericNotify(CAMERA_MSG_ERROR,
UNKNOWN_ERROR, 0); |
12 |
return ; |
13 |
} |
14 |
15 |
switch (msgType)
{ |
16 |
case CAMERA_MSG_PREVIEW_FRAME: |
17 |
client->handlePreviewData(dataPtr); |
18 |
break ; |
19 |
case CAMERA_MSG_POSTVIEW_FRAME: |
20 |
client->handlePostview(dataPtr); |
21 |
break ; |
22 |
case CAMERA_MSG_RAW_IMAGE: |
23 |
client->handleRawPicture(dataPtr); |
24 |
break ; |
25 |
case CAMERA_MSG_COMPRESSED_IMAGE: |
26 |
client->handleCompressedPicture(dataPtr); |
27 |
break ; |
28 |
default : |
29 |
client->handleGenericData(msgType,
dataPtr); |
30 |
break ; |
31 |
} |
32 |
} |
33 |
//
picture callback - compressed picture ready |
34 |
void CameraService::Client::handleCompressedPicture( const sp<IMemory>&
mem) { |
35 |
int restPictures
= mHardware->getPictureRestCount(); |
36 |
if (!restPictures) |
37 |
{ |
38 |
disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE); |
39 |
} |
40 |
41 |
sp<ICameraClient>
c = mCameraClient; |
42 |
mLock.unlock(); |
43 |
if (c
!= 0) { |
44 |
c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE,
mem); |
45 |
} |
46 |
} |
6. Camera.cpp会继续通知它的listener:
01 |
//
callback from camera service when frame or image is ready |
02 |
void Camera::dataCallback(int32_t
msgType, const sp<IMemory>&
dataPtr) |
03 |
{ |
04 |
sp<CameraListener>
listener; |
05 |
{ |
06 |
Mutex::Autolock
_l(mLock); |
07 |
listener
= mListener; |
08 |
} |
09 |
if (listener
!= NULL) { |
10 |
listener->postData(msgType,
dataPtr); |
11 |
} |
12 |
} |
7. 而这个listener就是我们的JNI层的JNICameraContext对象了:
01 |
void JNICameraContext::postData(int32_t
msgType, const sp<IMemory>&
dataPtr) |
02 |
{ |
03 |
//
VM pointer will be NULL if object is released |
04 |
Mutex::Autolock
_l(mLock); |
05 |
JNIEnv
*env = AndroidRuntime::getJNIEnv(); |
06 |
if (mCameraJObjectWeak
== NULL) { |
07 |
LOGW( "callback
on dead camera object" ); |
08 |
return ; |
09 |
} |
10 |
11 |
//
return data based on callback type |
12 |
switch (msgType)
{ |
13 |
case CAMERA_MSG_VIDEO_FRAME: |
14 |
//
should never happen |
15 |
break ; |
16 |
//
don't return raw data to Java |
17 |
case CAMERA_MSG_RAW_IMAGE: |
18 |
LOGV( "rawCallback" ); |
19 |
env->CallStaticVoidMethod(mCameraJClass,
fields.post_event, |
20 |
mCameraJObjectWeak,
msgType, 0, 0, NULL); |
21 |
break ; |
22 |
default : |
23 |
//
TODO: Change to LOGV |
24 |
LOGV( "dataCallback(%d,
%p)" ,
msgType, dataPtr.get()); |
25 |
copyAndPost(env,
dataPtr, msgType); |
26 |
break ; |
27 |
} |
28 |
} |
8. 可以看到JNI层最终都会调用来自java层的函数postEventFromNative,这个函数会发送对应的消息给自己的 eventhandler,收到消息后就会根据消息的类型回调Package层Camera.java最初传下来的callback函数。至此,我们就在最上层拿到了图像数据。