Camera子系統採用C/S架構,客戶端和服務端在兩個不一樣的進程當中,它們使用android中的binder機制進行通訊,本系列文章將從Android Camera應用程序到硬件抽象的實現一步一步對照相機系統進行分析,首先從CameraService初始化過程着手,而後從上層APP打開照相機->進行preview->拍照以及聚焦等功能的實現全面的學習照相機子系統 java
1 CameraService初始化過程 android
frameworks/av/media/mediaserverMain_mediaserver.cpp, api
CameraService在MediaServer中初始化,下面代碼是MediaServer的main函數,在該函數中初始化照相機服務 數組
int main(int argc, char** argv) { sp<ProcessState> proc(ProcessState::self()); sp<IServiceManager> sm = defaultServiceManager(); ................. CameraService::instantiate(); ............ IPCThreadState::self()->joinThreadPool(); }
CameraService中的instantiate方法用來建立CameraService實例,並進行相應的初始化,這個函數定義在它的父類BinderService中:frameworks/native/include/binder/BinderService.h,替換以後見以下代碼: 架構
class BinderService { public: static status_t publish(bool allowIsolated = false) { sp<IServiceManager> sm(defaultServiceManager()); return sm->addService(String16(CameraService::getServiceName()), new CameraService(), allowIsolated); } ................... static void instantiate() { publish(); } ................... };相機服務的初始化過程首先是建立CameraService實例,而後將其註冊到ServiceManager中,關於它的啓動是發生在init.rc中,經過media_server來啓動CameraService,具體代碼以下:
system/rootdir/init.rc 框架
service servicemanager /system/bin/servicemanager class core user system group system critical onrestart restart zygote onrestart restart media onrestart restart surfaceflinger onrestart restart drm service media /system/bin/mediaserver class main user media group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc ioprio rt 4在cameraService註冊以及啓動過程當中cameraService自身會執行一些初始化的工做,主要涉及到以下工做
frameworks/av/services/camera/libcameraservice/CameraService.cpp static CameraService *gCameraService; CameraService::CameraService():mSoundRef(0), mModule(0) { ALOGI("CameraService started (pid=%d)", getpid()); gCameraService = this; } void CameraService::onFirstRef() { BnCameraService::onFirstRef(); if (hw_get_module(CAMERA_HARDWARE_MODULE_ID, (const hw_module_t **)&mModule) < 0) { ALOGE("Could not load camera HAL module"); mNumberOfCameras = 0; } else {/*最大支持兩個攝像頭*/ mNumberOfCameras = mModule->get_number_of_cameras(); if (mNumberOfCameras > MAX_CAMERAS) { ALOGE("Number of cameras(%d) > MAX_CAMERAS(%d).",mNumberOfCameras, MAX_CAMERAS); mNumberOfCameras = MAX_CAMERAS; } for (int i = 0; i < mNumberOfCameras; i++) { setCameraFree(i); } } }
在上述初始化代碼中,先經過調用HAL硬件抽象層庫,獲取支持的攝像頭個數並保存到mNumberOfCameras 函數
2 應用程序連接相機服務過程 oop
在camera應用程序啓動的時候首先會和CameraService創建鏈接,camera應用程序代碼就不分析了,下面這副圖是一個簡單的流程圖,畫得有點醜 學習
圖2-1:照相機應用程序啓動流程圖 ui
public class Camera { public static Camera open(int cameraId) { return new Camera(cameraId); } Camera(int cameraId) { ................. 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); } }
圖2-2:照相機服務請求示意圖
frameworks/base/core/jni/android_hardware_Camera.cpp static JNINativeMethod camMethods[] = { { "native_setup","(Ljava/lang/Object;I)V", (void*)android_hardware_Camera_native_setup },/*經過Camera.cpp鏈接CameraService*/ …... };
(3)native_setup函數經過JNI調用android_hardware_Camera_native_setup函數,該函數的實現以下://經過android_hardware_Camera_native_setup請求CameraService
static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,jobject weak_this, jint cameraId) { sp<Camera> camera = Camera::connect(cameraId); if (camera == NULL) { jniThrowRuntimeException(env, "Fail to connect to camera service"); return; } // make sure camera hardware is alive 還記得前面的初始化? if (camera->getStatus() != NO_ERROR) { jniThrowRuntimeException(env, "Camera initialization failed"); return; } jclass clazz = env->GetObjectClass(thiz); if (clazz == NULL) { jniThrowRuntimeException(env, "Can't find android/hardware/Camera"); return; } // We use a weak reference so the Camera object can be garbage collected. // The reference is only used as a proxy for callbacks. sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera); context->incStrong(thiz); camera->setListener(context); //將這一步驟返回的BpCameraClient返回到JAVA應用程序框架 // save context in opaque field env->SetIntField(thiz, fields.context, (int)context.get()); }
(4)android_hardware_Camera_native_setup經過調用Camera::connect(int cameraId)函數請求鏈接服務。frameworks/av/camera/camera.cpp
sp<Camera> Camera::connect(int cameraId) { ALOGV("connect"); sp<Camera> c = new Camera();//BnCameraClient const sp<ICameraService>& cs = getCameraService();//return BpCameraService if (cs != 0) {//Used for processing all kinds of events c->mCamera = cs->connect(c, cameraId);//return } if (c->mCamera != 0) { c->mCamera->asBinder()->linkToDeath(c); c->mStatus = NO_ERROR; } else { c.clear(); } return c; }
(5)Camera::connect(int cameraId)函數首先向ServiceManager獲取Camera服務信息,並生成CameraService服務代理BpCameraService,而後經過Binder通訊發送CONNECT命令,當BnCameraService收到CONNECT命令後調用CameraService的connect()成員函數來作相應的處理,接下來咱們就分析CameraService的connect()成員函數,注意在這一步驟中首先new了一個Camera本地實例,這個Camera類是BnCameraClient的子類,在調用BpCameraService::connect的時候咱們將新生成的Camera作爲參數傳遞給了CameraService.咱們先來看BpCameraService的connect函數
class BpCameraService: public BpInterface<ICameraService> { public: // connect to camera service virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int cameraId) { Parcel data, reply; data.writeInterfaceToken(ICameraService::getInterfaceDescriptor()); data.writeStrongBinder(cameraClient->asBinder());//轉換成IBinder類型 data.writeInt32(cameraId); remote()->transact(BnCameraService::CONNECT, data, &reply); return interface_cast<ICamera>(reply.readStrongBinder());//BpCamera } };首先將咱們傳遞過來的Camera對象轉換成IBinder類型,而後由BnCameraService去響應該鏈接,最後就是等待服務端返回,若是成功這裏爲咱們生成一個BpCamera實例,怎麼來的下面繼續分析,接收服務命令的代碼段以下:
status_t BnCameraService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch(code) { case CONNECT: { CHECK_INTERFACE(ICameraService, data, reply);// sp<ICameraClient> cameraClient =//(a) interface_cast<ICameraClient>(data.readStrongBinder()); //return Client 繼承BnCamera sp<ICamera> camera = connect(cameraClient, data.readInt32());//(b) reply->writeStrongBinder(camera->asBinder());//(c) return NO_ERROR; } break; default: return BBinder::onTransact(code, data, reply, flags); } }服務端接到CONNECT命令以後開始進行一系列的類型轉換,先看代碼段(a)還記得以前咱們傳遞過來的是Camera實例,Camera繼承了BnCameraClient,因此在(a)中,使用Camera的Binder對象爲咱們生成了Camera服務代理BpCameraClient實例
(b)將生成的BpCameraClient對象做爲參數打包到CameraService的connect()函數中,至於這個connect函數作了什麼,先無論.先看(c)
(c)將在(b)中返回的實例對象以IBinder的形式返回,如今再回到BpCameraService::connect函數的最後一句return interface_cast<ICamera>(reply.readStrongBinder()),是否是明白了?若是在(c)中成功建立了一個Client實例對象,(Client是BnCamera的子類),那麼在BpCameraService::connect函數中是否是會爲咱們返回一個BpCamera對象?yes!爲了驗證咱們來分析CameraService的connect()成員函數frameworks/av/services/camera/libcameraservice/CameraService.cpp
sp<ICamera> CameraService::connect( const sp<ICameraClient>& cameraClient, int cameraId) { int callingPid = getCallingPid(); LOG1("CameraService::connect E (pid %d, id %d)", callingPid, cameraId); if (!mModule) {/*在服務初始化的時候就已經得到了*/ ALOGE("Camera HAL module not loaded"); return NULL; } sp<Client> client; if (cameraId < 0 || cameraId >= mNumberOfCameras) { ALOGE("CameraService::connect X (pid %d) rejected (invalid cameraId %d).",callingPid, cameraId); return NULL; } char value[PROPERTY_VALUE_MAX]; /*策略相關*/ property_get("sys.secpolicy.camera.disabled", value, "0"); if (strcmp(value, "1") == 0) { // Camera is disabled by DevicePolicyManager. ALOGI("Camera is disabled. connect X (pid %d) rejected", callingPid); return NULL; } Mutex::Autolock lock(mServiceLock); /*這是CameraService類中的一個成員變量是用來記錄攝像頭設備的,而且 *它是一個數組wp<Client> mClient[MAX_CAMERAS];每個設備都對應一個Client */ if (mClient[cameraId] != 0) {//第一次來的是應該是爲空的,因此不會走這條分支 client = mClient[cameraId].promote(); if (client != 0) { if (cameraClient->asBinder() == client->getCameraClient()->asBinder()) { LOG1("CameraService::connect X (pid %d) (the same client)", callingPid); return client; } else { ALOGW("CameraService::connect X (pid %d) rejected (existing client).",callingPid); return NULL; } } mClient[cameraId].clear(); } if (mBusy[cameraId]) {/*若是這設備ID處於忙狀態*/ ALOGW("CameraService::connect X (pid %d) rejected" " (camera %d is still busy).", callingPid, cameraId); return NULL; } /*這個結構是硬件抽象範疇的,裏面包含了一些基本信息 * 其中facing描述前置仍是後置 * orientation 用來描述image方向 * device_version用來描述HAL的版本 */ struct camera_info info; if (mModule->get_camera_info(cameraId, &info) != OK) { ALOGE("Invalid camera id %d", cameraId); return NULL; } int deviceVersion; if (mModule->common.module_api_version == CAMERA_MODULE_API_VERSION_2_0) { deviceVersion = info.device_version; } else { deviceVersion = CAMERA_DEVICE_API_VERSION_1_0; } /*根據HAL不一樣API的版本建立不一樣的client實例,在以前版本中不是這樣的,這是4.2的變化*/ switch(deviceVersion) { case CAMERA_DEVICE_API_VERSION_1_0: client = new CameraClient(this, cameraClient, cameraId, info.facing, callingPid, getpid()); break; case CAMERA_DEVICE_API_VERSION_2_0://for 4.2 client = new Camera2Client(this, cameraClient, cameraId, info.facing, callingPid, getpid()); break; default: ALOGE("Unknown camera device HAL version: %d", deviceVersion); return NULL; } /*初始化camera_module_t *module*/ if (client->initialize(mModule) != OK) { return NULL; } cameraClient->asBinder()->linkToDeath(this); //最後將建立的CameraClient或Camera2Client實例保存到mClient[MAX_CAMERAS]數組當中去 //mClient[MAX_CAMERAS]數組是CameraService類中的成員變量 mClient[cameraId] = client;//every camera is a Client class LOG1("CameraService::connect X (id %d, this pid is %d)", cameraId, getpid()); return client;/*最後返回*/ }
首先經過該函數咱們能夠驗證上面的(c)觀點,經過CameraService生成CameraService::Client服務代理BpCamera,下面看看Client類之間的關係圖
圖2-2:照相機服務請求示意圖2