之前的10篇博文主要是記錄了Android4.2.2的SurfaceFlinger的相關內容,為何之前會投入那麼多的時間,原因就在於之前在看camera的架構時,遇到了本地的ANativeWindow和Surface的內容。而這些是SurfaceFlinger中最常見的應用端的使用品。故而在學習完了SurfaceFlinger之後就來看看Camera的的架構內容。這裡先和大家分享android4.2.2的CameraService的啟動過程與其的架構。
1.cameraService在何處啟動
mediaserver啟動了我們cameraservice,即所謂的多媒體相關的服務總管。
int main(int argc, char** argv){ signal(SIGPIPE, SIG_IGN); sp proc(ProcessState::self()); sp sm = defaultServiceManager(); ALOGI("ServiceManager: %p", sm.get()); AudioFlinger::instantiate();//多媒體服務的啟動包括音頻,網路攝影機等 MediaPlayerService::instantiate(); CameraService::instantiate(); AudioPolicyService::instantiate(); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool();}
之前的文章有提到過一般的Service的啟動方式,這裡是典型的一種BinderService的啟動
class BinderService{public: static status_t publish(bool allowIsolated = false) { sp sm(defaultServiceManager()); return sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated); } static void publishAndJoinThreadPool(bool allowIsolated = false) { sp sm(defaultServiceManager()); sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); } static void instantiate() { publish(); }//兩種初始化binder服務的方式 static status_t shutdown() { return NO_ERROR; }};
CameraService::CameraService():mSoundRef(0), mModule(0){ ALOGI("CameraService started (pid=%d)", getpid()); gCameraService = this;}void CameraService::onFirstRef()//camerservice產生sp後被調用{ BnCameraService::onFirstRef(); if (hw_get_module(CAMERA_HARDWARE_MODULE_ID, (const hw_module_t **)&mModule) < 0) {//擷取並載入mModule變數,實際的hal層的硬體庫camera.fiber.so,載入了模組 ALOGE("Could not load camera HAL module"); mNumberOfCameras = 0; } else { mNumberOfCameras = mModule->get_number_of_cameras();//通過hal擷取camera的數目 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的建構函式後,會自動執行onFirstRef().在該函數內部主要實現了對Camera的Hal層的操作。
通過hw_get_module()獲得載入HAL層的模組控制代碼到mModule成員變數之中,並獲得硬體的Camera的個數到mNumberOfCameras之中。可以看到CameraService比起SurfaceFinger這個強大的service來說簡單了很多。
step3,camera用戶端的建立
通java層的new Camera()來到JNI層,依次經過camera.java再到本地JNI的android_hardware_Camera.cpp。
camera.java中Camera.open()函數的執行
public static Camera open(int cameraId) { return new Camera(cameraId); } /** * Creates a new Camera object to access the first back-facing camera on the * device. If the device does not have a back-facing camera, this returns * null. * @see #open(int) */ public static Camera open() { int numberOfCameras = getNumberOfCameras(); CameraInfo cameraInfo = new CameraInfo(); for (int i = 0; i < numberOfCameras; i++) { getCameraInfo(i, cameraInfo); if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) { return new Camera(i); } } return null; }
Camera中的類
Camera(int cameraId) { mShutterCallback = null; mRawImageCallback = null; mJpegCallback = null; mPreviewCallback = null; mPostviewCallback = null; mZoomListener = null; Looper looper; if ((looper = Looper.myLooper()) != null) {..... native_setup(new WeakReference(this), cameraId); }
JNI層的android_hardware_camera.cpp中:
// connect to camera servicestatic void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, jobject weak_this, jint cameraId){ sp camera = Camera::connect(cameraId);//調用Camera的connect函數 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; }......}
來到Camera應用程式層的類connect函數,目標是請求CameraService建立一個Camera用戶端。
step4:camera用戶端的connect函數
sp Camera::connect(int cameraId){ ALOGV("connect"); sp c = new Camera();//BnCameraClient const sp& cs = getCameraService();//擷取一個Bpcamerservice if (cs != 0) { c->mCamera = cs->connect(c, cameraId);//基於binder驅動最終會去調用camerservice側的connect,mCamera指向一個Bpcamera } if (c->mCamera != 0) { c->mCamera->asBinder()->linkToDeath(c); c->mStatus = NO_ERROR; } else { c.clear(); } return c;}
建立一個應用端的Camera,該類class Camera : public BnCameraClient, public IBinder::DeathRecipient繼承關係如下。
cs = getCameraService()通過SM擷取CameraService在本地的一個代理。調用connect函數後最終調用CameraService側的connect()函數。
virtual sp connect(const sp& cameraClient, int cameraId) { Parcel data, reply; data.writeInterfaceToken(ICameraService::getInterfaceDescriptor()); data.writeStrongBinder(cameraClient->asBinder()); data.writeInt32(cameraId);//發送到服務端的資料包 remote()->transact(BnCameraService::CONNECT, data, &reply);//實際調用的是Bpbinder的transact return interface_cast(reply.readStrongBinder());//傳入Bpbinder的handle數值返回一個new BpCamera,實際是服務端的Bncamera }};
在這裡可以看到這邊傳入一個本地Camera類對象即new Camera(),這個匿名的binder對象將通過Binder驅動傳遞給CameraService。主要用於後續CameraService的回調給應用程式層的Camera來處理
step5:CameraSevice端的connect函數
sp CameraService::connect( const sp& 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; 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); 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]) { ALOGW("CameraService::connect X (pid %d) rejected" " (camera %d is still busy).", callingPid, cameraId); return NULL; } struct camera_info info; if (mModule->get_camera_info(cameraId, &info) != OK) {//擷取camera的相關資訊 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) { case CAMERA_DEVICE_API_VERSION_1_0: client = new CameraClient(this, cameraClient, cameraId, info.facing, callingPid, getpid());//client是CameraClient的基類,建立一個camerservice側的cameraclient break; case CAMERA_DEVICE_API_VERSION_2_0: client = new Camera2Client(this, cameraClient, cameraId, info.facing, callingPid, getpid()); break; default: ALOGE("Unknown camera device HAL version: %d", deviceVersion); return NULL; } if (client->initialize(mModule) != OK) {//cameraclient init初始化,實際調用的是CameraClient return NULL; } cameraClient->asBinder()->linkToDeath(this); mClient[cameraId] = client;//串連請求後建立立的 LOG1("CameraService::connect X (id %d, this pid is %d)", cameraId, getpid()); return client;//返回CameraClient}
分以下幾個過程來分析這個函數:
a. sp client;一個CameraService內部的用戶端類
先查看當前服務端維護的camera client個數mClient[cameraId] != 0,初次啟動是該數為0.
b.擷取底層camera模組的資訊get_camera_info,查看當前的api版本資訊是CAMERA_MODULE_API_VERSION_2_0還是CAMERA_MODULE_API_VERSION_1_0.我的平台是1.0故執行如下:
switch(deviceVersion) { case CAMERA_DEVICE_API_VERSION_1_0: client = new CameraClient(this, cameraClient, cameraId, info.facing, callingPid, getpid());//client是CameraClient的基類,建立一個camerservice側的cameraclient break;
c.CameraClient的建立,該類繼承了public CameraService::Client這個CameraService的內部類,Client繼承了BnCamera。
d.client->initialize(mModule)的處理,和硬體相關
status_t CameraClient::initialize(camera_module_t *module) {//一個cameraClient建立一個CameraHardwareInterface硬介面 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);//建立一個camera硬體介面,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);//將camerservice處的回呼函數註冊到HAL處 // 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 | CAMERA_MSG_CONTINUOUSSNAP | CAMERA_MSG_SNAP | CAMERA_MSG_SNAP_THUMB | CAMERA_MSG_SNAP_FD); //enable the continuoussnap and singlesnap message by fuqiang LOG1("CameraClient::initialize X (pid %d, id %d)", callingPid, mCameraId); return OK;}
這裡出現了一個封裝Camera底層操作的一個硬體介面類CameraHardwareInterface,可以屏蔽不同的平台硬體特性,主要是實現的HAL的相關操作。
step6.CameraHardwareInterface介面類的實現initialize()函數。
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();//初始preview的相關流opspreview_stream_ops,初始化hal的預覽視窗 return rc; }
這裡的module就是底層的camera模組,最終完成open的操作,這裡占時不說明HAL的操作,後續會專門分享camera的HAL的實現。
step7:setCallbacks()設定回呼函數,即註冊回呼函數到HAL處
void setCallbacks(notify_callback notify_cb, data_callback data_cb, data_callback_timestamp data_cb_timestamp, void* user) { mNotifyCb = notify_cb; mDataCb = data_cb; mDataCbTimestamp = data_cb_timestamp; mCbUser = user; ALOGV("%s(%s)", __FUNCTION__, mName.string()); if (mDevice->ops->set_callbacks) { mDevice->ops->set_callbacks(mDevice, __notify_cb, __data_cb, __data_cb_timestamp, __get_memory, this);//傳入的是__notify_cb函數 }//硬體裝置設定回調 }
分別訊息回調,資料回調,時間戳記回調,以及記憶體相關操作的回調。
step8:
mClient[cameraId] = client將建立好的cameraclient對象維護到CameraService中並返回退出connect,而最終通過Binder驅動返回到用戶端的是CameraClient的代理BpCameraClient,是一個匿名的Binder服務。
c->mCamera = cs->connect(c, cameraId);將這個服務端的cameraclient維護到本地應用端的Camera的mCamera成員中。而後續的Camera的相關操作都通過該mCamera成員和CameraService進行進一步的互動操作。
camera的一個調用架構圖: