Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Andriod4.2 Camera 架構與實現

Andriod4.2 Camera 架構與實現

編輯:關於Android編程

1.Camera架構包括客戶端和服務端,他們之間的通信采用Binder機制實現。 Camera的實現主要包括本地代碼和Java代碼兩個層次: Camera本地框架: frameworks/native/include/ui frameworks/native/libs/ui frameworks/av/camera/ Camera的本地實現包含在上述目錄中,這部分內容被編譯生成庫libui.so和libcamera_client.so。 Camera服務部分: frameworks/av/services/camera/libcameraservice 這部分編譯生成libcameraservice.so。 Camera HAL: frameworks/av/camera frameworks/av/services/camera/libcameraservice/CameraHardwareInterface.h CameraHardwareInterface.h是HAL接口的定義,需要各個系統根據自己的情況實現。 2.AndroidCamera采用C/S架構,client與server兩個獨立的線程之間使用Binder通信。這裡將介紹Camera從設備開機,到進入相機應用是如何完成初始化工作的。 首先既然Camera是利用binder通信,它肯定要將它的service注冊到ServiceManager裡面,以備後續Client引用,那麼這一步是在哪裡進行的呢?在frameworks/av/media/mediaserver/main_mediaserver.cpp下有個main函數,可以用來注冊媒體服務。在這裡,CameraService完成了服務的注冊。   intmain(int argc, char** argv)   {   sp<ProcessState>proc(ProcessState::self());   sp<IServiceManager> sm= defaultServiceManager();   ALOGI("ServiceManager:%p", sm.get());   AudioFlinger::instantiate();   MediaPlayerService::instantiate();   CameraService::instantiate();   AudioPolicyService::instantiate();   ProcessState::self()->startThreadPool();   IPCThreadState::self()->joinThreadPool();   }   可是我們到CameraService文件裡面卻找不到instantiate()這個函數,它在哪?繼續追到它的一個父類BinderService template<typenameSERVICE> classBinderService { public: static status_t publish(bool allowIsolated =false) { sp<IServiceManager>sm(defaultServiceManager()); returnsm->addService(String16(SERVICE::getServiceName()), new SERVICE(),allowIsolated); }   static void publishAndJoinThreadPool(boolallowIsolated = false) { sp<IServiceManager>sm(defaultServiceManager()); sm->addService(String16(SERVICE::getServiceName()),new SERVICE(), allowIsolated); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); } staticvoid instantiate(){ publish(); } static status_t shutdown() { return NO_ERROR; } };   可以發現在publish()函數中,CameraService完成服務的注冊。這裡面有個SERVICE,源碼中有說明 template<typenameSERVICE> 這表示SERVICE是個模板,這裡是注冊CameraService,所以可以用CameraService代替 sm->addService(String16(SERVICE::getServiceName()),new SERVICE(), allowIsolated); 這樣,Camera就在ServiceManager完成服務注冊,提供給client隨時使用。 Main_MediaServer主函數由init.rc在啟動是調用,所以在設備開機的時候Camera就會注冊一個服務,用作binder通信。   servicemedia /system/bin/mediaserver   class main   user media   group audio camera inetnet_bt net_bt_admin net_bw_acct drmrpc   ioprio rt 4   Binder服務已注冊,那接下來就看看client如何連上server端,並打開camera模塊。   咱們先從testingcameraapp的源碼入手。在setUpCamera()函數中專門有一個open(mCameraId)函數進入framework層,調用frameworks/base/core/java/android/hardware/Camera.java類的open方法。   publicstatic Camera open(int cameraId) {   return newCamera(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 = newEventHandler(this, looper);   } else if ((looper =Looper.getMainLooper()) != null) {   mEventHandler = newEventHandler(this, looper);   } else {   mEventHandler = null;   }   native_setup(newWeakReference<Camera>(this), cameraId);   }     好,終於來到JNI了,繼續看camera的JNI文件frameworks/base/core/jni/android_hardware_Camera.cpp   // connect to cameraservice   static voidandroid_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 camerahardware 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 weakreference so the Camera object can be garbage collected.   // The reference isonly used as a proxy for callbacks.   sp<JNICameraContext>context = new JNICameraContext(env, weak_this, clazz, camera);   context->incStrong(thiz);   camera->setListener(context);       // save context inopaque field   env->SetIntField(thiz,fields.context, (int)context.get());   }   JNI函數裡面,我們找到CameraC/S架構的客戶端了,它調用connect函數向服務器發送連接請求。JNICameraContext這個類是一個監聽類,用於處理底層Camera回調函數傳來的數據和消息   看看客戶端的connect函數有什麼   ===>>>frameworks/av/camera/Camera.cpp   sp<Camera>Camera::connect(int cameraId)   {   ALOGV("connect");   sp<Camera> c = new Camera();   const sp<ICameraService>& cs =getCameraService();   if (cs != 0) {   c->mCamera = cs->connect(c,cameraId);   }   if (c->mCamera != 0) {   c->mCamera->asBinder()->linkToDeath(c);   c->mStatus = NO_ERROR;   } else {   c.clear();   }   return c;   }   constsp<ICameraService>& cs =getCameraService();通過getCameraService()函數獲取一個Camera服務實例。   // establish binder interface to cameraservice const sp<ICameraService>&Camera::getCameraService() { Mutex::Autolock _l(mLock); if (mCameraService.get() == 0) { sp<IServiceManager> sm =defaultServiceManager(); sp<IBinder> binder; do { binder =sm->getService(String16("media.camera")); if (binder != 0) break; ALOGW("CameraServicenot published, waiting..."); usleep(500000); // 0.5 s } while(true); if (mDeathNotifier == NULL) { mDeathNotifier = newDeathNotifier(); } binder->linkToDeath(mDeathNotifier); mCameraService= interface_cast<ICameraService>(binder); } ALOGE_IF(mCameraService==0, "noCameraService!?"); return mCameraService; }   可以看出,該CameraService實例是通過binder獲取的,由binder機制可以知道,該服務就是CameraService一個實例。   c->mCamera= cs->connect(c, cameraId);   然後執行服務端的connect()函數,並返回一個ICamera對象賦值給Camera的mCamera,服務端connect()返回的其實是它內部類client的一個實例。   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::connectX (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 byDevicePolicyManager. ALOGI("Camera is disabled.connect X (pid %d) rejected", callingPid); return NULL; }   Mutex::Autolock lock(mServiceLock); 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 (existingclient).", callingPid); return NULL; } } mClient[cameraId].clear(); } if (mBusy[cameraId]) { ALOGW("CameraService::connectX (pid %d) rejected" " (camera %d isstill busy).", callingPid, cameraId); return NULL; } 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; }   switch(deviceVersion) { caseCAMERA_DEVICE_API_VERSION_1_0: client = new CameraClient(this,cameraClient, cameraId, info.facing,callingPid, getpid()); break; caseCAMERA_DEVICE_API_VERSION_2_0: client = newCamera2Client(this, cameraClient, cameraId, info.facing,callingPid, getpid()); break; default: ALOGE("Unknown cameradevice HAL version: %d", deviceVersion); return NULL; }   if(client->initialize(mModule) != OK) { return NULL; }   cameraClient->asBinder()->linkToDeath(this);   mClient[cameraId] = client; LOG1("CameraService::connect X(id %d, this pid is %d)", cameraId, getpid()); return client; }   在函數client->initialize(mModule)中實例化CameraHal接口hardware,hardware調用initialize()進入HAL層打開Camear驅動 status_tCameraClient::initialize(camera_module_t *module) { int callingPid = getCallingPid(); LOG1("CameraClient::initialize E (pid %d, id %d)",callingPid, mCameraId);   char camera_device_name[10]; status_t res; snprintf(camera_device_name, sizeof(camera_device_name), "%d",mCameraId);   mHardware= new CameraHardwareInterface(camera_device_name); res =mHardware->initialize(&module->common); if (res != OK) { ALOGE("%s: Camera %d: unable to initialize device: %s(%d)", __FUNCTION__, mCameraId, strerror(-res), res); mHardware.clear(); return NO_INIT; }   mHardware->setCallbacks(notifyCallback, dataCallback, dataCallbackTimestamp, (void *)mCameraId);   // Enable zoom, error, focus, and metadata messages by default enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM |CAMERA_MSG_FOCUS | CAMERA_MSG_PREVIEW_METADATA |CAMERA_MSG_FOCUS_MOVE);   LOG1("CameraClient::initialize X (pid %d, id %d)",callingPid, mCameraId); return OK; }   hardware調用initialize()進入HAL層打開Camear驅動 status_t initialize(hw_module_t *module) { ALOGI("Opening camera %s", mName.string()); int rc = module->methods->open(module, mName.string(), (hw_device_t**)&mDevice); //這一句作用就是打開Camera底層驅動 if (rc != OK) { ALOGE("Could not open camera %s: %d",mName.string(), rc); return rc; } initHalPreviewWindow(); return rc; }   hardware->initialize(&mModule->common)中mModule模塊是一個結構體camera_module_t,他是怎麼初始化的呢?我們發現CameraService裡面有個函數 voidCameraService::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); } } }   CameraService調用 hw_get_module(CAMERA_HARDWARE_MODULE_ID,(const hw_module_t **)&mModule) 來裝載fakecamera HAL module:camera.duck.so inthw_get_module(const char *id, const struct hw_module_t **module) { returnhw_get_module_by_class(id, NULL, module); } inthw_get_module_by_class(const char *class_id, const char *inst, const struct hw_module_t **module) { int status; int i; const structhw_module_t *hmi = NULL; charprop[PATH_MAX]; charpath[PATH_MAX]; charname[PATH_MAX]; if (inst) snprintf(name, PATH_MAX, "%s.%s", class_id, inst); else strlcpy(name, class_id, PATH_MAX);   /* * Here werely on the fact that calling dlopen multiple times on * the same.so will simply increment a refcount (and not load * a new copyof the library). * We alsoassume that dlopen() is thread-safe. */ /* Loopthrough the configuration variants looking for a module */ for (i=0 ;i<HAL_VARIANT_KEYS_COUNT+1 ; i++) { if (i <HAL_VARIANT_KEYS_COUNT) { if(property_get(variant_keys[i], prop, NULL) == 0) { continue; } snprintf(path, sizeof(path), "%s/%s.%s.so", HAL_LIBRARY_PATH2, name, prop); if(access(path, R_OK) == 0) break; snprintf(path, sizeof(path), "%s/%s.%s.so", HAL_LIBRARY_PATH1, name, prop); if(access(path, R_OK) == 0) break; } else { snprintf(path, sizeof(path), "%s/%s.default.so", HAL_LIBRARY_PATH1, name); if(access(path, R_OK) == 0) break; } }   camera.duck.somodule 的代碼在development/tools/emulator/system/camera/ ====>development/tools/emulator/system/camera/Android.mk LOCAL_SRC_FILES :=\ EmulatedCameraHal.cpp \ EmulatedCameraFactory.cpp \ EmulatedBaseCamera.cpp \ EmulatedCamera.cpp \ EmulatedCameraDevice.cpp \ EmulatedQemuCamera.cpp \ EmulatedQemuCameraDevice.cpp \ EmulatedFakeCamera.cpp \ EmulatedFakeCameraDevice.cpp \ Converters.cpp \ PreviewWindow.cpp \ CallbackNotifier.cpp \ QemuClient.cpp \ JpegCompressor.cpp \ EmulatedCamera2.cpp \ EmulatedFakeCamera2.cpp \ EmulatedQemuCamera2.cpp \ fake-pipeline2/Scene.cpp \ fake-pipeline2/Sensor.cpp \ fake-pipeline2/JpegCompressor.cpp     ifeq($(TARGET_PRODUCT),vbox_x86) LOCAL_MODULE :=camera.vbox_x86 else LOCAL_MODULE :=camera.duck endif   了解HAL層的都知道hw_get_module函數就是用來獲取模塊的Halstub,這裡是通過CAMERA_HARDWARE_MODULE_ID獲取CameraHal層的代理stub,並賦值給mModule,後面就可通過操作mModule完成對Camera模塊的控制。那麼onFirstRef()函數又是何時調用的?   onFirstRef()屬於其父類RefBase,該函數在強引用sp新增引用計數時調用,什麼意思?就是當有sp包裝的類初始化的時候調用,那麼camera是何時調用的呢?可以發現在   客戶端發起連接時候   sp<Camera>Camera::connect(int cameraId) { LOGV("connect"); sp<Camera> c = new Camera(); constsp<ICameraService>& cs = getCameraService();   }   這個時候初始化了一個CameraService實例,且用Sp包裝,這個時候sp將新增計數,相應的CameraService實例裡面onFirstRef()函數完成調用。 CameraService::connect()返回client的時候,就表明客戶端和服務端連接建立。Camera完成初始化,可以進行拍照和preview等動作。
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved