sc7731 Android 5.1 Camera 学习之二 framework 到 HAL接口整理
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sc7731 Android 5.1 Camera 学习之二 framework 到 HAL接口整理相关的知识,希望对你有一定的参考价值。
前面已经分析过,Client端发起远程调用,而实际完成处理任务的,是Server端的 CameraClient 实例。远程client 和 server是两个不同的进程,它们使用binder作为通信工具,完成进程间的通信。
注:CameraClient定义如下:
1 class CameraClient : public CameraService::Client 2 { 3 //... 4 };
App需要对Camera进行各种操作,framework-java 和framework-c++ 都有对应的操作接口。而JNI是framework-java 和framework-c++ 中间的通信桥梁。
在framework-c++ 这边,或者说在 CameraClient 实例里面,会和 HAL层进行沟通。
本篇笔记将就 framework-java、framework-c++ 、HAL相关接口作一个简要笔记。App层属于摄像头应用功能逻辑部分,尚未研究。
一、JNI 封装接口
1. JNI method 表注册
framework-c++ 为 framework-java实现了对应的接口,具体在 android_hardware_Camera.cpp 文件中:
1 static JNINativeMethod camMethods[] = { 2 { "getNumberOfCameras", 3 "()I", 4 (void *)android_hardware_Camera_getNumberOfCameras }, 5 { "_getCameraInfo", 6 "(ILandroid/hardware/Camera$CameraInfo;)V", 7 (void*)android_hardware_Camera_getCameraInfo }, 8 { "native_setup", 9 "(Ljava/lang/Object;IILjava/lang/String;)I", 10 (void*)android_hardware_Camera_native_setup }, 11 { "native_release", 12 "()V", 13 (void*)android_hardware_Camera_release }, 14 { "setPreviewSurface", 15 "(Landroid/view/Surface;)V", 16 (void *)android_hardware_Camera_setPreviewSurface }, 17 { "setPreviewTexture", 18 "(Landroid/graphics/SurfaceTexture;)V", 19 (void *)android_hardware_Camera_setPreviewTexture }, 20 { "setPreviewCallbackSurface", 21 "(Landroid/view/Surface;)V", 22 (void *)android_hardware_Camera_setPreviewCallbackSurface }, 23 { "startPreview", 24 "()V", 25 (void *)android_hardware_Camera_startPreview }, 26 { "_stopPreview", 27 "()V", 28 (void *)android_hardware_Camera_stopPreview }, 29 { "previewEnabled", 30 "()Z", 31 (void *)android_hardware_Camera_previewEnabled }, 32 { "setHasPreviewCallback", 33 "(ZZ)V", 34 (void *)android_hardware_Camera_setHasPreviewCallback }, 35 { "_addCallbackBuffer", 36 "([BI)V", 37 (void *)android_hardware_Camera_addCallbackBuffer }, 38 { "native_autoFocus", 39 "()V", 40 (void *)android_hardware_Camera_autoFocus }, 41 { "native_cancelAutoFocus", 42 "()V", 43 (void *)android_hardware_Camera_cancelAutoFocus }, 44 { "native_takePicture", 45 "(I)V", 46 (void *)android_hardware_Camera_takePicture }, 47 { "native_setParameters", 48 "(Ljava/lang/String;)V", 49 (void *)android_hardware_Camera_setParameters }, 50 { "native_getParameters", 51 "()Ljava/lang/String;", 52 (void *)android_hardware_Camera_getParameters }, 53 { "reconnect", 54 "()V", 55 (void*)android_hardware_Camera_reconnect }, 56 { "lock", 57 "()V", 58 (void*)android_hardware_Camera_lock }, 59 { "unlock", 60 "()V", 61 (void*)android_hardware_Camera_unlock }, 62 { "startSmoothZoom", 63 "(I)V", 64 (void *)android_hardware_Camera_startSmoothZoom }, 65 { "stopSmoothZoom", 66 "()V", 67 (void *)android_hardware_Camera_stopSmoothZoom }, 68 { "setDisplayOrientation", 69 "(I)V", 70 (void *)android_hardware_Camera_setDisplayOrientation }, 71 { "_enableShutterSound", 72 "(Z)Z", 73 (void *)android_hardware_Camera_enableShutterSound }, 74 { "_startFaceDetection", 75 "(I)V", 76 (void *)android_hardware_Camera_startFaceDetection }, 77 { "_stopFaceDetection", 78 "()V", 79 (void *)android_hardware_Camera_stopFaceDetection}, 80 { "enableFocusMoveCallback", 81 "(I)V", 82 (void *)android_hardware_Camera_enableFocusMoveCallback}, 83 };
其中,双引号里的名字,对应着 framework-java 层Camera.java 文件中相关的API;以 "android_hardware_Camera_"为前缀的名字,代表着 framework-c++ 中的实现。至于其中返回值和参数类型的表示,此处略去。
可以看出,一个java API 就对应着一个 C++ API实现。
camMethods[] 这个表会被注册到 const RegJNIRec gRegJNI[] 这个表中,而这个表将会被系统进行native注册,大致如下:
(1).在android_hardware_Camera.cpp文件中:
1 int register_android_hardware_Camera(JNIEnv *env) 2 { 3 //... 4 // Register native functions 5 return AndroidRuntime::registerNativeMethods(env, "android/hardware/Camera", 6 camMethods, NELEM(camMethods)); 7 };
(2).在AndroidRuntime.cpp 文件中:
1 extern int register_android_hardware_Camera(JNIEnv *env); 2 3 static const RegJNIRec gRegJNI[] = { 4 REG_JNI(register_android_hardware_Camera), 5 }; 6 7 /* 8 * Register android native functions with the VM. 9 */ 10 /*static*/ int AndroidRuntime::startReg(JNIEnv* env) 11 { 12 //... 13 if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) { 14 env->PopLocalFrame(NULL); 15 return -1; 16 } 17 //... 18 } 19 20 21 void AndroidRuntime::start(const char* className, const Vector<String8>& options) 22 { 23 //... 24 /* 25 * Register android functions. 26 */ 27 if (startReg(env) < 0) { 28 ALOGE("Unable to register all android natives\n"); 29 return; 30 } 31 //... 32 }
此处注册流程,大致这样,不再赘述jvm native注册细节。
2. JNI method 表中c++接口的实现
在 android_hardware_Camera.cpp 文件中,这些c++ 接口只是一层空壳,可以简单的看成是一些环境变量、字符串类型的转换而已。
(此处截取部分接口的封装实现进行展示)
1 static jint android_hardware_Camera_getNumberOfCameras(JNIEnv *env, jobject thiz) 2 { 3 //调用了 Camera.cpp 文件中的接口。 4 return Camera::getNumberOfCameras(); 5 } 6 7 // connect to camera service 8 static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, 9 jobject weak_this, jint cameraId, jint halVersion, jstring clientPackageName) 10 { 11 sp<Camera> camera; 12 //调用了 Camera.cpp 文件中的接口 13 camera = Camera::connect(cameraId, clientName,Camera::USE_CALLING_UID); 14 } 15 16 static void android_hardware_Camera_startPreview(JNIEnv *env, jobject thiz) 17 { 18 ALOGV("startPreview"); 19 sp<Camera> camera = get_native_camera(env, thiz, NULL); //获取一个Camera 实例 20 if (camera == 0) return; 21 22 //调用了 Camera.cpp 文件中 Camera::startPreview() 23 if (camera->startPreview() != NO_ERROR) { 24 jniThrowRuntimeException(env, "startPreview failed"); 25 return; 26 } 27 } 28 ....
而真正的封装,在 Camera.cpp 文件中实现。
二、远端 Camera client
在Camera.cpp文件中,部分接口如下:
1 sp<Camera> Camera::connect(int cameraId, const String16& clientPackageName,int clientUid); 2 status_t Camera::reconnect(); 3 status_t Camera::lock(); 4 status_t Camera::unlock(); 5 // pass the buffered IGraphicBufferProducer to the camera service 6 status_t Camera::setPreviewTarget(const sp<IGraphicBufferProducer>& bufferProducer); 7 // start preview mode 8 status_t Camera::startPreview(); 9 status_t Camera::storeMetaDataInBuffers(bool enabled); 10 // start recording mode, must call setPreviewTarget first 11 status_t Camera::startRecording(); 12 // stop preview mode 13 void Camera::stopPreview(); 14 // stop recording mode 15 void Camera::stopRecording(); 16 // release a recording frame 17 void Camera::releaseRecordingFrame(const sp<IMemory>& mem); 18 // get preview state 19 bool Camera::previewEnabled(); 20 // get recording state 21 bool Camera::recordingEnabled(); 22 status_t Camera::autoFocus(); 23 status_t Camera::cancelAutoFocus(); 24 // take a picture 25 status_t Camera::takePicture(int msgType); 26 // set preview/capture parameters - key/value pairs 27 status_t Camera::setParameters(const String8& params); 28 // send command to camera driver 29 status_t Camera::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2); 30 .....
上面的这些接口,会被android_hardware_Camera.cpp 文件中的对应名字的接口进行调用,以完成jni的封装。
三、server 端 CameraClient 的实例接口
在前一篇笔记里已经分析过, Camera Client远端的操作,其实质是通过binder,然后调用到了Camera server端对应的接口。而具体就落实到了 CameraService::Client 内部类的 继承类 CameraClient 的实例上去了。
在CameraClient.cpp文件中,server端为远程client端实现了对应的接口:
1 status_t CameraClient::lock(); 2 status_t CameraClient::unlock(); 3 4 // connect a new client to the camera 5 status_t CameraClient::connect(); 6 void CameraClient::disconnect() ; 7 8 status_t CameraClient::setPreviewWindow(const sp<IBinder>& binder,const sp<ANativeWindow>& window); 9 // set the buffer consumer that the preview will use 10 status_t CameraClient::setPreviewTarget(const sp<IGraphicBufferProducer>& bufferProducer); 11 12 // start preview mode 13 status_t CameraClient::startPreview() ; 14 // start recording mode 15 status_t CameraClient::startRecording(); 16 // start preview or recording 17 status_t CameraClient::startCameraMode(camera_mode mode); 18 status_t CameraClient::startPreviewMode(); 19 status_t CameraClient::startRecordingMode() ; 20 // stop preview mode 21 void CameraClient::stopPreview(); 22 // stop recording mode 23 void CameraClient::stopRecording(); 24 25 bool CameraClient::previewEnabled(); 26 27 status_t CameraClient::initialize(camera_module_t *module); 28 29 .....
以上仅贴出部分常见的接口。
在上面贴出来的接口中,CameraClient::initialize() 是最重要的。在 CameraService::connect() 对 CameraClient::connect() 完成调用后,会立即对CameraClient::initialize() 进行调用,去操作HAL层,已完成一个Camera实例的最终创建。
(CameraClient::initialize()被调用流程,在上篇笔记已经分析过,此处不赘述)
CameraClient::initialize()被调用后,将会去调用 HAL 层的 open 函数。换句话说,它会打开HAL模块。
1 status_t CameraClient::initialize(camera_module_t *module) 2 { 3 //... 4 mHardware = new CameraHardwareInterface(camera_device_name); 5 res = mHardware->initialize(&module->common); 6 //.... 7 }
mHardware->initialize() 的实现在 CameraHardwareInterface.h 文件中:
1 class CameraHardwareInterface : public virtual RefBase { 2 public: 3 status_t initialize(hw_module_t *module) 4 { 5 6 camera_module_t *cameraModule = reinterpret_cast<camera_module_t *>(module); 7 8 9 int rc = OK; 10 if (module->module_api_version >= CAMERA_MODULE_API_VERSION_2_3 && info.device_version > CAMERA_DEVICE_API_VERSION_1_0) 11 //.... 12 } else { 13 rc = CameraService::filterOpenErrorCode(module->methods->open( 14 module, mName.string(), (hw_device_t **)&mDevice)); 15 } 16 //... 17 } 18 };
这其中的 module->methods->open(module, mName.string(), (hw_device_t **)&mDevice) ; 就是HAL模块的入口处了。
那么,camera_module_t *module 这个参数是怎么传进来的呢?或者说,Camera HAL模块式怎么加载到内存的呢?
对代码稍作回朔,可以知道,在 CameraService::onFirstRef() 这个接口里面,有加载Camera HAL的操作,在 CameraService.cpp 文件中:
1 void CameraService::onFirstRef() 2 { 3 //.. 4 BnCameraService::onFirstRef(); 5 //.. 6 if (hw_get_module(CAMERA_HARDWARE_MODULE_ID,(const hw_module_t **)&mModule) < 0) { 7 }else { 8 //... 9 } 10 }
大名鼎鼎的 hw_get_module() 接口在这里现身了。那么,CameraService::onFirstRef()又是在什么时候被调用的呢?
简而言之,在远端client发起连接的时候,在文件 CameraBase.cpp 中:
1 template <typename TCam, typename TCamTraits> 2 sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId, 3 const String16& clientPackageName, 4 int clientUid) 5 { 6 sp<TCam> c = new TCam(cameraId); 7 8 //通过SM获取CameraService在本地的一个引用。调用connect函数后最终调用CameraService侧的connect()函数 9 const sp<ICameraService>& cs = getCameraService(); 10 //... 11 }
这里, const sp<ICameraService>& cs = getCameraService(); 这行代码其实可以被分解成两行代码:
1 ICameraService *A = getCameraService(); //不考虑c++ 实际语法 2 const sp<ICameraService>& cs = A; //不考虑c++ 实际语法
在第二行代码执行的时候,在构造强指针的过程中,最终会调用到 CameraService::onFirstRef() 这个玩意. 其具体调用处,在 RefBase.cpp 文件中:
1 void RefBase::incStrong(const void* id) const 2 { 3 //... 4 refs->mBase->onFirstRef(); 5 }
其具体调用流程略掉了。(这里涉及到Android 中sp wp 所谓的强指针弱指针构造的过程)
啰嗦了一长段,回头看看 CameraClient::initialize() 会为其他接口提供什么样的帮助:
1 status_t CameraClient::initialize(camera_module_t *module) 2 { 3 //... 4 mHardware = new CameraHardwareInterface(camera_device_name); 5 //.... 6 }
mHardware 是 CameraClient 的一个成员,在CameraClient.h文件中:
1 class CameraClient : public CameraService::Client 2 { 3 private: 4 // these are initialized in the constructor. 5 sp<CameraHardwareInterface> mHardware; 6 };
根据定义可以看见, mHardware 就是一个 CameraHardwareInterface 的 sp 对象----也就是HAL层的东西了。
而CameraClient中的大部分成员函数,都会借助 mHardware 成员,操作HAL层。(什么叫操作?!总是很邪恶的感觉到,它们是在推卸责任,把责任一层层的推卸,最后就到了HAL,HAL又会推到最终的driver上)
贴停止预览和照相的代码做为一个展示:
1 // take a picture - image is returned in callback 2 status_t CameraClient::takePicture(int msgType) { 3 //... 4 return mHardware->takePicture(); //告诉HAL层,进行拍照操作 5 } 6 7 // stop preview mode 8 void CameraClient::stopPreview() { 9 //... 10 mHardware->stopPreview(); //告诉HAL层,停止预览 11 }
四、HAL 接口
在 CameraClient::initialize()中,会产生一个 HAL 的 sp 对象:
1 mHardware = new CameraHardwareInterface(camera_device_name);
这里, CameraHardwareInterface 类,就对HAL层做了一个接口抽象,其定义在 CameraHardwareInterface.h 文件中。
1 class CameraHardwareInterface : public virtual RefBase { 2 public: 3 CameraHardwareInterface(const char *name) 4 { 5 mDevice = 0; 6 mName = name; 7 } 8 9 status_t initialize(hw_module_t *module) 10 { 11 rc = CameraService::filterOpenErrorCode(module->methods->open( 12 module, mName.string(), (hw_device_t **)&mDevice)); 13 } 14 15 /** 16 * Start preview mode. 17 */ 18 status_t startPreview() 19 { 20 ALOGV("%s(%s)", __FUNCTION__, mName.string()); 21 if (mDevice->ops->start_preview) 22 return mDevice->ops->start_preview(mDevice); 23 return INVALID_OPERATION; 24 } 25 26 /** 27 * Stop a previously started preview. 28 */ 29 void stopPreview() 30 { 31 ALOGV("%s(%s)", __FUNCTION__, mName.string()); 32 if (mDevice->ops->stop_preview) 33 mDevice->ops->stop_preview(mDevice); 34 } 35 36 //.....省略 37 38 private: 39 camera_device_t *mDevice; 40 String8 mName; 41 //... 省略 42 };
显而易见,这里是对 Camera HAL 的一个抽象封装,毕竟,各种厂商的Camera HAL 具体模块,其实现细节可能不同。于是这里就再抽了一层。
其扮演的角色,其实和 android_hardware_Camera.cpp 文件中,jni那部分接口一样。为了好看(更清晰),包装了一层而已。
只要CameraService::onFirstRef()中对Camera HAL模块加载成功,这里就可以开始告诉Camera HAL 做什么。至于怎么做,那将是HAL层的事---话说,这是面向对象的基本原理吧:只能告诉别人做什么,具体怎么做,就管不了了。
全文总结:
App ---> framework-java ---> jni ---> framework-c++(Camera) ---> binder ---> framework-c++(CameraService) --> framework-c++(CameraService::Client) ---> framework-c++(CameraClient) --->(CameraHardwareInterface) ---> HAL
由于未对 framework-java 以上的东西进行分析,笔记中直接从 jni 开始的。
(over)
2016-1-22
以上是关于sc7731 Android 5.1 Camera 学习之二 framework 到 HAL接口整理的主要内容,如果未能解决你的问题,请参考以下文章
Android Camera:尝试在空对象引用上调用 android.hardware.Camera.getParameters()' 上的虚拟方法 Android Camera Parameters