前面已經分析過,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