http://blog.csdn.net/dnfchan/article/details/7594590
首先既然Camera是利用binder通信,它肯定要將它的service注冊到ServiceManager里面,以備后續(xù)Client引用,那么這一步是在哪里進行的呢?細心的人會發(fā)現(xiàn),在frameworks\base\media\mediaserver\Main_MediaServer.cpp下有個main函數(shù),可以用來注冊媒體服務。CameraService完成了服務的注冊
Main_MediaServer主函數(shù)由init.rc在啟動是調(diào)用,所以在設備開機的時候Camera就會注冊一個服務,用作binder通信。
Binder服務已注冊,那接下來就看看client如何連上server端,并打開camera模塊。
咱們先從camera app的源碼入手。在onCreate()函數(shù)中專門有一個open Camera的線程
public void onCreate(Bundle icicle) {
......
mCameraOpenThread.start();
}
再看看mCameraOpenThread
Thread mCameraOpenThread = new Thread(new Runnable() {
public void run() {
try {
qcameraUtilProfile("open camera");
mCameraDevice = Util.openCamera(Camera.this, mCameraId);
qcameraUtilProfile("camera opended");
} catch (CameraHardwareException e) {
mOpenCameraFail = true;
} catch (CameraDisabledException e) {
mCameraDisabled = true;
}
}
});
繼續(xù)追Util.openCamera
return CameraHolder.instance().open(cameraId)又來了個CameraHolder,該類用一個實例openCamera
public synchronized android.hardware.Camera open(int cameraId)mCameraDevice = android.hardware.Camera.open(cameraId);
return mCameraDevice;
}
在這里就開始進入framework層了,調(diào)用frameworks\base\core\java\android\hardware\Camera.java類的open方法 。
public static Camera open(){
return new Camera(i);
}
這里調(diào)用了Camera的構(gòu)造函數(shù),在看看構(gòu)造函數(shù)
Camera(int cameraId){
native_setup(new WeakReference<Camera>(this), cameraId)
}
static JNINativeMethod camMethods[] = {
{ "getNumberOfCameras",
"()I",
(void *)android_hardware_Camera_getNumberOfCameras },
{ "getCameraInfo",
"(ILandroid/hardware/Camera$CameraInfo;)V",
(void*)android_hardware_Camera_getCameraInfo },
{ "native_setup",
"(Ljava/lang/Object;I)V",
(void*)android_hardware_Camera_native_setup },
{ "native_release",
"()V",
(void*)android_hardware_Camera_release },
{ "setPreviewDisplay",
"(Landroid/view/Surface;)V",
(void *)android_hardware_Camera_setPreviewDisplay },
{ "setPreviewTexture",
"(Landroid/graphics/SurfaceTexture;)V",
(void *)android_hardware_Camera_setPreviewTexture },
{ "startPreview",
"()V",
(void *)android_hardware_Camera_startPreview },
{ "_stopPreview",
"()V",
(void *)android_hardware_Camera_stopPreview },
{ "previewEnabled",
"()Z",
(void *)android_hardware_Camera_previewEnabled },
{ "setHasPreviewCallback",
"(ZZ)V",
(void *)android_hardware_Camera_setHasPreviewCallback },
{ "_addCallbackBuffer",
"([BI)V",
(void *)android_hardware_Camera_addCallbackBuffer },
{ "native_autoFocus",
"()V",
(void *)android_hardware_Camera_autoFocus },
{ "native_cancelAutoFocus",
"()V",
(void *)android_hardware_Camera_cancelAutoFocus },
{ "native_takePicture",
"(I)V",
(void *)android_hardware_Camera_takePicture },
{ "native_setParameters",
"(Ljava/lang/String;)V",
(void *)android_hardware_Camera_setParameters },
{ "native_getParameters",
"()Ljava/lang/String;",
(void *)android_hardware_Camera_getParameters },
{ "reconnect",
"()V",
(void*)android_hardware_Camera_reconnect },
{ "lock",
"()V",
(void*)android_hardware_Camera_lock },
{ "unlock",
"()V",
(void*)android_hardware_Camera_unlock },
//HTC_START howard 20120904
{ "setPinchZoom",
"(I)V",
(void *)android_hardware_Camera_setPinchZoom },
//HTC_END
{ "startSmoothZoom",
"(I)V",
(void *)android_hardware_Camera_startSmoothZoom },
{ "stopSmoothZoom",
"()V",
(void *)android_hardware_Camera_stopSmoothZoom },
{ "setDisplayOrientation",
"(I)V",
(void *)android_hardware_Camera_setDisplayOrientation },
{ "_startFaceDetection",
"(I)V",
(void *)android_hardware_Camera_startFaceDetection },
{ "_stopFaceDetection",
"()V",
(void *)android_hardware_Camera_stopFaceDetection},
{ "enableFocusMoveCallback",
"(I)V",
(void *)android_hardware_Camera_enableFocusMoveCallback},
};
好,終于來到JNI了
繼續(xù)看camera的JNI文件android_hardware_camera.cpp
static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
jobject weak_this, jint cameraId)
{
sp<Camera> camera = Camera::connect(cameraId);
sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera);
camera->setListener(context);
}
JNI函數(shù)里面,我們找到Camera C/S架構(gòu)的客戶端了,它調(diào)用connect函數(shù)向服務器發(fā)送連接請求。JNICameraContext這個類是一個監(jiān)聽類,用于處理底層Camera回調(diào)函數(shù)傳來的數(shù)據(jù)和消息
看看客戶端的connect函數(shù)有什么
sp<Camera> Camera::connect(int cameraId)
{
LOGV("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;
}
先看標紅的第一句,通過getCameraService()函數(shù)獲取一個Camera服務實例。
const sp<ICameraService>& Camera::getCameraService()
{
if (mCameraService.get() == 0) {
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder;
do {
binder = sm->getService(String16("media.camera"));
if (binder != 0)
break;
LOGW("CameraService not published, waiting...");
usleep(500000); // 0.5 s
} while(true);
mCameraService = interface_cast<ICameraService>(binder);
}
LOGE_IF(mCameraService==0, "no CameraService!?");
return mCameraService;
}
可以看出,該CameraService實例是通過binder獲取的,由binder機制可以知道,該服務就是CameraService一個實例。
然后執(zhí)行服務端的connect()函數(shù),并返回一個ICamera對象賦值給Camera 的mCamera, 服務端connect()返回的其實是它內(nèi)部類client的一個實例。
sp<ICamera> CameraService::connect(){
hardware = new CameraHardwareInterface(camera_device_name);
if (hardware->initialize(&mModule->common) != OK) {
hardware.clear();
return NULL;
}
client = new Client(this, cameraClient, hardware, cameraId, info.facing, callingPid);
mClient[cameraId] = client;
LOG1("CameraService::connect X");
return client;
}
先實例化Camera Hal接口 hardware,hardware調(diào)用initialize()進入HAL層打開Camear驅(qū)動
status_t initialize(hw_module_t *module)
{
LOGI("Opening camera %s", mName.string());
int rc = module->methods->open(module, mName.string(),
(hw_device_t **)&mDevice);
if (rc != OK) {
LOGE("Could not open camera %s: %d", mName.string(), rc);
return rc;
}
initHalPreviewWindow();
return rc;
}
module->methods->open(module, mName.string(),
(hw_device_t **)&mDevice)這一句作用就是打開Camera底層驅(qū)動
hardware->initialize(&mModule->common)中mModule模塊是一個結(jié)構(gòu)體camera_module_t,他是怎么初始化的呢?我們發(fā)現(xiàn)CameraService里面有個函數(shù)
void CameraService::onFirstRef()
{
BnCameraService::onFirstRef();
if (hw_get_module(CAMERA_HARDWARE_MODULE_ID,
(const hw_module_t **)&mModule) < 0) {
LOGE("Could not load camera HAL module");
mNumberOfCameras = 0;
}
}
了解HAL層的都知道hw_get_module函數(shù)就是用來獲取模塊的Hal stub,這里是通過CAMERA_HARDWARE_MODULE_ID 獲取Camera Hal層的代理stub,并賦值給mModule,后面就可通過操作mModule完成對Camera模塊的控制。那么onFirstRef()函數(shù)又是何時調(diào)用的?
onFirstRef()屬于其父類RefBase,該函數(shù)在強引用sp新增引用計數(shù)時調(diào)用,什么意思?就是當 有sp包裝的類初始化的時候調(diào)用,那么camera是何時調(diào)用的呢?可以發(fā)現(xiàn)在
sp<Camera> Camera::connect(int cameraId)
{
LOGV("connect");
sp<Camera> c = new Camera();
const sp<ICameraService>& cs = getCameraService();
}
這個時候初始化了一個CameraService實例,且用Sp包裝,這個時候sp將新增計數(shù),相應的CameraService實例里面onFirstRef()函數(shù)完成調(diào)用。
CameraService::connect()返回client的時候,就表明客戶端和服務端連接建立。Camera完成初始化,可以進行拍照和preview等動作。一個看似簡單Camera初始化的過程,研究起來卻也讓人費勁啊。。。
下面是整個過程的時序圖