这一部分主要在/frameworks/base/core/java/android/hardware/Camera.java和/frameworks/base/core/jni/android_hardware_Camera.cpp中实现的。
在Camera.java中声明了很多native的方法,这些方法都是在android_hardware_Camera.cpp,通过JNI的方式来调用。
1.Camera.java分析
Camera.java主要的功能就是提供一个对Camera操作的java入口,并且定义一些回调接口。
先看一下成员变量:
private int mNativeContext; // accessed by native methods
private EventHandler mEventHandler;
private ShutterCallback mShutterCallback;
private PictureCallback mRawImageCallback;
private PictureCallback mJpegCallback;
private PreviewCallback mPreviewCallback;
private PictureCallback mPostviewCallback;
private AutoFocusCallback mAutoFocusCallback;
private OnZoomChangeListener mZoomListener;
private ErrorCallback mErrorCallback;
除了mNativeContext都是上一篇文章提到的一些回调接口。这个mNativeContext实际上是给android_hardware_Camera.cpp使用的,在JNI部分会分析到。
再看一下open方法:
public static Camera open(int cameraId) {
return new Camera(cameraId);
}
open是对Camera操作的入口方法,根据cameraID打开前置或后置摄像头。
再看看Camera的构造方法都做了什么:
Camera(int cameraId) {
mShutterCallback = null;
mRawImageCallback = null;
mJpegCallback = null;
mPreviewCallback = null;
mPostviewCallback = null;
mZoomListener = null;
Looper looper;
if ((looper = Looper.myLooper()) != null) {
mEventHandler = new EventHandler(this, looper);
} else if ((looper = Looper.getMainLooper()) != null) {
mEventHandler = new EventHandler(this, looper);
} else {
mEventHandler = null;
}
native_setup(new WeakReference<Camera>(this), cameraId);
}
也很简单,初始化关于回调接口的成员变量,然后调用native_setup(new WeakReference<Camera>(this), cameraId);,把自己和cameraID传进去,在JNI层进行初始化。
完成了以上初始化,就可以对Camera进行各种操作了,比如setPreviewDisplay, startPreview等。
2.android_hardware_Camera.cpp分析
(1)首先来看JNI的注册函数。
int register_android_hardware_Camera(JNIEnv *env)
{
field fields_to_find[] = {
{ "android/hardware/Camera", "mNativeContext", "I", &fields.context },
{ "android/view/Surface", ANDROID_VIEW_SURFACE_JNI_ID, "I", &fields.surface },
{ "android/hardware/Camera$CameraInfo", "facing", "I", &fields.facing },
{ "android/hardware/Camera$CameraInfo", "orientation", "I", &fields.orientation },
};
if (find_fields(env, fields_to_find, NELEM(fields_to_find)) < 0)
return -1;
jclass clazz = env->FindClass("android/hardware/Camera");
fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative",
"(Ljava/lang/Object;IIILjava/lang/Object;)V");
if (fields.post_event == NULL) {
LOGE("Can't find android/hardware/Camera.postEventFromNative");
return -1;
}
// Register native functions
return AndroidRuntime::registerNativeMethods(env, "android/hardware/Camera",
camMethods, NELEM(camMethods));
}
这个函数中主要做了两件事:第一,也就是JNI的基本任务,注册JNINativeMethod camMethods[]函数数组,使得java层可以调用。第二, 通过env->GetStaticMethodID获取到java层中postEventFromNative方法的ID,这样就可以将camera service的一些通知信息传递给java层。这也回答了上一篇《Camera服务之--Camera应用部分》的一个疑问,就是camera 色让vice是怎么通知上层应用的,就是通过这个postEventFromNative方法。
(2)android_hardware_Camera_native_setup分析
这个函数是java层向下调用的入口,如果需要对camera进行操作,这个是必须首先调用的。
// connect to camera service
static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
jobject weak_this, jint cameraId)
{
sp<Camera> camera = Camera::connect(cameraId);
.......
sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera);
context->incStrong(thiz);
camera->setListener(context);
// save context in opaque field
env->SetIntField(thiz, fields.context, (int)context.get());
}
首先调用camera service的connect函数,获得一个camera service的对象(代理),然后创建一个JNICameraContext对象,并把service对象保存在其中,最后再把回调接口设置到camera service中。因为JNICameraContext实现了回调接口CameraListener,所以也就是把JNICameraContext设置到camera service中。
(3)其他JNI函数分析
通过JNI注册的其他函数,都是static的函数,这些函数基本上可以总结为两种实现方式:
一个是对camera service的对象(代理)的调用,比如
static void android_hardware_Camera_stopPreview(JNIEnv *env, jobject thiz)
{
LOGV("stopPreview");
sp<Camera> c = get_native_camera(env, thiz, NULL);
if (c == 0) return;
c->stopPreview();
}
另一个是对JNICameraContext对象的调用,比如:
static void android_hardware_Camera_addCallbackBuffer(JNIEnv *env, jobject thiz, jbyteArray bytes) {
LOGV("addCallbackBuffer");
JNICameraContext* context = reinterpret_cast<JNICameraContext*>(env->GetIntField(thiz, fields.context));
if (context != NULL) {
context->addCallbackBuffer(env, bytes);
}
}
(4)JNICameraContext分析
这个类实现了CameraListener接口,也就是实现了camera service的回调接口。这个类的主要作用就是这个,对camera service回调event的一个中转站,将回调event处理后调用java层的回调实现。