主要记录一下启动的过程,顺便看看是否能把握到数据流的走向,这次以高通810平台Android5.1为蓝本。本篇主要讲述Framework及Hardware部分,涉及到JAVA及driver部分的如有必要也会捎带提及一下。
一、启动Camera在JAVA层开始,主要是启动了一个OpenCameraThread的线程(PhotoModule.java),代码如下:
1 if (mOpenCameraThread == null && !mActivity.mIsModuleSwitchInProgress) { 2 mOpenCameraThread = new OpenCameraThread(); 3 mOpenCameraThread.start(); 4 }
在这个线程中只做了两件事情,整个Camera的启动过程也是围绕着他们展开的:
1 private class OpenCameraThread extends Thread { 2 @Override 3 public void run() { 4 openCamera(); // 第一步开启camera 5 startPreview(); // 第二部开始preview 6 } 7 }
二、开启第一步openCamera
1. 还是在Java层,openCamera主要干了下面这些事情:
1.1 CameraUtility.openCamera ------->重点部分
1.2 getParameters ------->一些参数获得
1.3 initializeFocusManager -------->Focus管理
1.4 initializeCapabilities -------->Camera选择的一些特性
1.5 sendMSG--CAMERA_OPEN_DONE -------->Open完成之后的处理
2. 上面那么多,我们只需要关注第一点就可以了,现在继续往下查看。关于这部分网上也有不少资料,可自行查看,直接查看源代码也比较清晰。总之在Camera开启成功后Java层会获得一个mCameraDevice,这个其实就是Camera的一个代理--AndroidCameraProxyImpl,当然我们要关注的是前面开启的过程。
1 public CameraManager.CameraProxy cameraOpen( 2 Handler handler, int cameraId, CameraOpenErrorCallback callback) { 3 mCameraHandler.obtainMessage(OPEN_CAMERA, cameraId, 0, 4 CameraOpenErrorCallbackForward.getNewInstance( 5 handler, callback)).sendToTarget(); 6 mCameraHandler.waitDone(); 7 if (mCamera != null) { 8 return new AndroidCameraProxyImpl(); // ----->这个就是丢给前台的mCameraDevice 9 } else { 10 return null; 11 } 12 }
3. OPEN_CAMERA的处理先使用传统的方式开启,如果不行再尝试新的open方式,这里开始就转到frameworks。frameworks基本没做什么东西,就是一个传话筒而已,很快就到了JNI。
1 public void handleMessage(final Message msg) { 2 try { 3 switch (msg.what) { 4 case OPEN_CAMERA: 5 try { 6 mCamera = android.hardware.Camera.openLegacy(msg.arg1, // 这里的android.hardware.Camera就指向frameworks\base\core\java\android\hardware\camera.java 7 android.hardware.Camera.CAMERA_HAL_API_VERSION_1_0); // 先使用传统的接口打开 8 } catch (RuntimeException e) { 9 /* Retry with open if openLegacy fails */ 10 Log.v(TAG, "openLegacy failed. Using open instead"); 11 mCamera = android.hardware.Camera.open(msg.arg1); //若出现异常再使用新的接口打开,这里提供两种方式也是方便硬件厂商做兼容及区别处理,到现在的AndroidM版本,Camera HAL已经有了3个版本了,但高通810目前还是使用HAL1 12 }
4. openLegacy的JNI调用为native_setup。JNI调用将转到android_hardware_Camera.cpp文件,关于这部分网上也有很多资料。其实这里也没干什么事情,跟frameworks一样,都只是一个传递的作用,整个Camera框架真正有内涵的还是HAL以及driver部分,当然APP部分的各种呈现也很有内涵。
1 return native_setup(new WeakReference
这里通过JNI到了C++层
1 // connect to camera service 2 static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, 3 jobject weak_this, jint cameraId, jint halVersion, jstring clientPackageName) 4 { 。。。。。。10 //ALOGV("native setup: halversion %d", halVersion);//native setup: halversion 256 11 spcamera; 12 if (halVersion == CAMERA_HAL_API_VERSION_NORMAL_CONNECT) { //CAMERA_HAL_API_VERSION_NORMAL_CONNECT = -2 13 // Default path: hal version is don't care, do normal camera connect. 14 camera = Camera::connect(cameraId, clientName, 15 Camera::USE_CALLING_UID); 16 } else { 17 jint status = Camera::connectLegacy(cameraId, halVersion, clientName, 18 Camera::USE_CALLING_UID, camera); 19 if (status != NO_ERROR) { 20 return status; 21 }
调用到Camera的connectLegacy
1 status_t Camera::connectLegacy(int cameraId, int halVersion, 2 const String16& clientPackageName, 3 int clientUid, 4 sp& camera) // 需返回的Camera设备 5 { 6 ALOGV("connectLegacy: connect legacy camera device,halVersion %d", halVersion); 7 sp c = new Camera(cameraId); 8 sp cl = c; // 这个示例很重要,CameraService将包含此示例,用来执行回调调用到Client这边。 9 status_t status = NO_ERROR; 10 const sp & cs = CameraBaseT::getCameraService(); // 获取CameraService 11 12 if (cs != 0) { 13 status = cs.get()->connectLegacy(cl, cameraId, halVersion, clientPackageName, // 调用CameraService的connectLegacy 14 clientUid, /*out*/c->mCamera); 15 } 16 if (status == OK && c->mCamera != 0) { 17 c->mCamera->asBinder()->linkToDeath(c); 18 c->mStatus = NO_ERROR; 19 camera = c; 20 } else { 21 ALOGW("An error occurred while connecting to camera: %d", cameraId); 22 c.clear(); 23 } 24 return status; 25 }
这部分有太多的资料阐述,毕竟还是Android通用代码,未涉及到硬件芯片厂商的差异性。简约一些,connect会获得一个CameraService,这个Service将进行HAL层设备的管理及交互。我们跳转到CameraService::connectLegacy可以看到在这个Service中包含了一个CameraClient,而上面说到的返回的Camera设备就是这个Client(源码:device = client;)。
1 status_t CameraService::connectLegacy( 2 const sp& cameraClient, 3 int cameraId, int halVersion, 4 const String16& clientPackageName, 5 int clientUid, 6 /*out*/ 7 sp & device) {// go here 8 9 。。。。。。 10 11 status_t status = validateConnect(cameraId, /*inout*/clientUid); 12 if (status != OK) { 13 return status; 14 } 15 16 sp client; 17 { 18 sp clientTmp; 19 Mutex::Autolock lock(mServiceLock); 20 if (!canConnectUnsafe(cameraId, clientPackageName, 21 cameraClient->asBinder(), 22 /*out*/clientTmp)) { 23 return -EBUSY; 24 } else if (client.get() != NULL) { 25 device = static_cast (clientTmp.get()); 26 return OK; 27 } 28 29 status = connectHelperLocked(/*out*/client, // 这个client就是上面调用中要返回的Camera设备device 30 cameraClient, // 传下来的ICameraClient实例 31 cameraId, 32 clientPackageName, 33 clientUid, 34 callingPid, 35 halVersion, 36 /*legacyMode*/true); 37 if (status != OK) { 38 return status; 39 } 40 41 } 42 // important: release the mutex here so the client can call back 43 // into the service from its destructor (can be at the end of the call) 44 45 device = client; // 返回的Client设备 46 return OK; 47 }
在connectHelperLocked中,将根据不同HAL版本实现不同的示例,目前有CameraClient和Camera2Client两种
1 case CAMERA_DEVICE_API_VERSION_1_0: 2 ALOGV("create a camera client.line %d",__LINE__); 3 client = new CameraClient(this, cameraClient, // 前面那个CameraClient是要实现的Client,第二个cameraClient就是上面传下来的ICameraClient实例 4 clientPackageName, cameraId, 5 facing, callingPid, clientUid, getpid(), legacyMode); 6 break; 7 case CAMERA_DEVICE_API_VERSION_2_0: 8 case CAMERA_DEVICE_API_VERSION_2_1: 9 case CAMERA_DEVICE_API_VERSION_3_0: 10 case CAMERA_DEVICE_API_VERSION_3_1: 11 case CAMERA_DEVICE_API_VERSION_3_2: 12 ALOGI("create a camera2 client"); 13 client = new Camera2Client(this, cameraClient, 14 clientPackageName, cameraId, 15 facing, callingPid, clientUid, getpid(), legacyMode); 16 break;
上面获得Client后会调用connectFinishUnsafe(client, client->getRemote()),这个函数将会执行到HAL的interface,所以厂家通用。
1 status_t CameraService::connectFinishUnsafe(const sp& client, 2 const sp & remoteCallback) { 3 status_t status = client->initialize(mModule); //这个mModule很关键,是在CameraService.cpp中onFirstRef中获取的。其实就是根据类名等规则加载一个动态库,一般在/system/lib/hw/目录下,如camera.msm8994.so 4 if (status != OK) {
5 ALOGE("%s: Could not initialize client from HAL module.", __FUNCTION__); 6 return status; 7 } 8 if (remoteCallback != NULL) { 9 remoteCallback->linkToDeath(this); 10 } 11 12 return OK; 13 }
上面client中的initialize会调用到hardware interface中的initialize并设置callback (CameraHardwareInterface.h),而在这里就会调用到具体厂家HAL层的函数了。
1 status_t initialize(hw_module_t *module) 2 { 3 ALOGI("Opening camera %s", mName.string()); 4 camera_module_t *cameraModule = reinterpret_cast(module); 5 camera_info info; 6 status_t res = cameraModule->get_camera_info(atoi(mName.string()), &info); 7 if (res != OK) return res; 8 ALOGI("init hal-ver:%d,dev-ver %d",module->module_api_version,info.device_version);// 515=v2.3,770=v3.2 9 int rc = OK; 10 if (module->module_api_version >= CAMERA_MODULE_API_VERSION_2_3 && 11 info.device_version > CAMERA_DEVICE_API_VERSION_1_0) {ALOGI("open legacy"); 12 // Open higher version camera device as HAL1.0 device. 13 rc = cameraModule->open_legacy(module, mName.string(), // 这个cameraModule就上具体厂家代码编译出来的so库,这里对应QCamera2Factory.cpp 14 CAMERA_DEVICE_API_VERSION_1_0, 15 (hw_device_t **)&mDevice); 16 } else { 17 rc = CameraService::filterOpenErrorCode(module->methods->open( 18 module, mName.string(), (hw_device_t **)&mDevice)); 19 } 20 if (rc != OK) { 21 ALOGE("Could not open camera %s: %d", mName.string(), rc); 22 return rc; 23 } 24 initHalPreviewWindow(); 25 return rc; 26 }
5.到这里就正式进入HAL层,每个厂家的实现代码也变得不一样,但大致模式还是差不多,都是通过V4L2的命令接口来控制具体的Camera设备。 HAL及driver将在另一篇继续讨论。