对技术执着
分类: LINUX
2015-03-14 15:28:57
首先既然Camera是利用binder通信,它肯定要将它的service注册到ServiceManager里面,以备后续Client引用,那么这一步是在哪里进行的呢?细心的人会发现,在frameworks\base\media\mediaserver\Main_MediaServer.cpp下有个main函数,可以用来注册媒体服务。没错就是在这里,CameraService完成了服务的注册
int main(int argc, char** argv) { sp
Main_MediaServer主函数由init.rc在启动是调用,所以在设备开机的时候Camera就会注册一个服务,用作binder通信。
Binder服务已注册,那接下来就看看client如何连上server端,并打开camera模块。
咱们先从camera app的源码入手。在onCreate()函数中专门有一个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;
}
}
});
继续追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层了,调用frameworks\base\core\java\android\hardware\Camera.java类的open方法 。
public static Camera open(){
return new Camera(i);
}
这里调用了Camera的构造函数,在看看构造函数
Camera(int cameraId){
native_setup(new WeakReference
}
好,终于来到JNI了
继续看camera的JNI文件android_hardware_camera.cpp
static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
jobject weak_this, jint cameraId)
{
sp
sp
camera->setListener(context);
}
JNI函数里面,我们找到Camera C/S架构的客户端了,它调用connect函数向服务器发送连接请求。JNICameraContext这个类是一个监听类,用于处理底层Camera回调函数传来的数据和消息
看看客户端的connect函数有什么
sp
{
LOGV("connect");
sp
const sp
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()函数获取一个Camera服务实例。
const sp
{
if (mCameraService.get() == 0) {
sp
sp
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
}
LOGE_IF(mCameraService==0, "no CameraService!?");
return mCameraService;
}
可以看出,该CameraService实例是通过binder获取的,由binder机制可以知道,该服务就是CameraService一个实例。
然后执行服务端的connect()函数,并返回一个ICamera对象赋值给Camera 的mCamera, 服务端connect()返回的其实是它内部类client的一个实例。
sp
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调用initialize()进入HAL层打开Camear驱动
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底层驱动
hardware->initialize(&mModule->common)中mModule模块是一个结构体camera_module_t,他是怎么初始化的呢?我们发现CameraService里面有个函数
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函数就是用来获取模块的Hal stub,这里是通过CAMERA_HARDWARE_MODULE_ID 获取Camera Hal层的代理stub,并赋值给mModule,后面就可通过操作mModule完成对Camera模块的控制。那么onFirstRef()函数又是何时调用的?
onFirstRef()属于其父类RefBase,该函数在强引用sp新增引用计数时调用,什么意思?就是当 有sp包装的类初始化的时候调用,那么camera是何时调用的呢?可以发现在
sp
{
LOGV("connect");
sp
const sp
}
这个时候初始化了一个CameraService实例,且用Sp包装,这个时候sp将新增计数,相应的CameraService实例里面onFirstRef()函数完成调用。
CameraService::connect()返回client的时候,就表明客户端和服务端连接建立。Camera完成初始化,可以进行拍照和preview等动作。一个看似简单Camera初始化的过程,研究起来却也让人费劲啊。。。
下面是整个过程的时序图