Android Camera调用流程
一個流程圖畫的非常好的文章
http://blog.csdn.net/lushengchu_luis/article/details/11033095
1、Packages/apps/到framework 打開Camera
進來第一個肯定是onCreate(Bundle icicle) {
這里是開始了一個Camera的線程
//start camera opening process mCameraStartUpThread = new CameraStartUpThread(); CameraStarUpThread是一個類 /// M: open camera process functions @{private class CameraStartUpThread extends Thread {//上面的注釋就寫著open camera process functions 打開相機進程的函數Util.openCamera(Camera.this, isPIPMode(getCurrentMode()));//這一句就是用Util這個類來打開相機進程了 ./packages/apps/Camera/src/com/android/camera/Util.java //這里面還有打開攝像頭的函數openCamera public static void openCamera(Activity activity, boolean isPIP)throws CameraHardwareException, CameraDisabledException {Log.i(TAG,"openCamera begin isPIP = " + isPIP);// Check if device policy has disabled the camera.DevicePolicyManager dpm = (DevicePolicyManager) activity.getSystemService(Context.DEVICE_POLICY_SERVICE);if (dpm.getCameraDisabled(null)) {throw new CameraDisabledException();}if (isPIP) {retryOpen(activity, OPEN_RETRY_COUNT, CameraHolder.instance().getBackCameraId());retryOpen(activity, OPEN_RETRY_COUNT, CameraHolder.instance().getFrontCameraId());} else {int currentCameraId = ((com.android.camera.Camera)activity).getCameraId();retryOpen(activity, OPEN_RETRY_COUNT, currentCameraId);}Log.i(TAG,"openCamera end");}//這里面又會調用一個retryOpen函數private static CameraManager.CameraProxy retryOpen(Activity activity, int count, int cameraId) //這個函數最終會調用open函數來打開攝像頭try {if (activity instanceof ActivityBase) {CameraProxy cameraProxy = CameraHolder.instance().open(cameraId);return cameraProxy;} else {return CameraHolder.instance().open(cameraId);}........}2. 這里面的CameraHolder.instance().open調用了下面的open函數
./packages/apps/Camera/src/com/android/camera/CameraHolder.java
public CameraProxy open(int cameraId)throws CameraHardwareException {Log.i(TAG, "CameraHolder open cameraId = " + cameraId);assertError(cameraId != UNKONW_ID);if (mMockCameraInfo == null) {//這里又有一個open函數return getCameraProxyWrapper(cameraId).open();} else {if (mMockCamera == null) {throw new RuntimeException();}getCameraProxyWrapper(cameraId).insertMockCameraProxy(mMockCamera[cameraId]);return mMockCamera[cameraId];}}public synchronized CameraProxy open()throws CameraHardwareException {Log.i(TAG, "CameraProxyWrapper open mCameraOpened = " + mCameraOpened + " mCameraId = " + mCameraId);assertError(!mCameraOpened);if (mCameraProxy == null) {try {Log.i(TAG, "open camera " + mCameraId);mCameraProxy = mCameraManager.cameraOpen(mCameraId);//現在又跑到一個mCameraManager.cameraOpen里面來了//看一下下面這個函數,這個函數就是app里面最終調用到framework里面的接口 // Open camera synchronously. This method is invoked in the context of a// background thread.CameraProxy cameraOpen(int cameraId) {// Cannot open camera in mCameraHandler, otherwise all camera events// will be routed to mCameraHandler looper, which in turn will call// event handler like Camera.onFaceDetection, which in turn will modify// UI and cause exception like this:// CalledFromWrongThreadException: Only the original thread that created// a view hierarchy can touch its views.MMProfileManager.startProfileCameraOpen();mCamera = FrameworksClassFactory.openCamera(cameraId);MMProfileManager.stopProfileCameraOpen();if (mCamera != null) {mParametersIsDirty = true;if (mParamsToSet == null) {mParamsToSet = mCamera.getParameters();}mCameraProxy = new CameraProxy();return mCameraProxy;} else {return null;}//./packages/apps/Camera/src/com/mediatek/camera/FrameworksClassFactory.java//代碼的路徑 camera.open這里就是跑到framework里面去了public static ICamera openCamera(int cameraId) {if (MOCK_CAMERA) {return MockCamera.open(cameraId);} else {Camera camera = Camera.open(cameraId);if (null == camera) {Log.e(TAG, "openCamera:got null hardware camera!");return null;}// wrap it with ICamerareturn new AndroidCamera(camera);}}2、Framework open到jni調用流程
代碼路徑:./frameworks/base/core/java/android/hardware/Camera.java
public static Camera open(int cameraId) {if (!isPermissionGranted()) {return null;}return new Camera(cameraId);} //這里的return new Camera就是在下面進行了初始化 //填充一些參數Camera(int cameraId) {mShutterCallback = null;mRawImageCallback = null;mJpegCallback = null;mPreviewCallback = null;mPreviewRawDumpCallback = null;mPostviewCallback = null;mUsingPreviewAllocation = false;mZoomListener = null;Looper looper;if ((looper = Looper.myLooper()) != null) {mEventHandler = new EventHandler(this, looper);} else if ((looper = Looper.getMainLooper()) != null) {mEventHandler = new EventHandler(this, looper);} else {mEventHandler = null;}String packageName = ActivityThread.currentPackageName();native_setup(new WeakReference<Camera>(this), cameraId, packageName);}//這個native_setup就是打開攝像頭的關鍵了看到這個native 函數說明這個函數是在jni接口,用的是c++代碼實現的,so,我們繼續找
private native final void native_setup(Object camera_this, int cameraId,
終于我們在./frameworks/base/core/jni/android_hardware_Camera.cpp
這里面找到了這個函數,然后我們看一下這個函數
3. 下面就是打開攝像頭的jni代碼,app調用open的時候就會調用到這個位置
// connect to camera service static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,jobject weak_this, jint cameraId, jstring clientPackageName) {// Convert jstring to String16const char16_t *rawClientName = env->GetStringChars(clientPackageName, NULL);jsize rawClientNameLen = env->GetStringLength(clientPackageName);String16 clientName(rawClientName, rawClientNameLen);env->ReleaseStringChars(clientPackageName, rawClientName);sp<Camera> camera = Camera::connect(cameraId, clientName,Camera::USE_CALLING_UID); //不相關的代碼就不加進來了 //sp<Camera> camera = Camera::connect(cameraId, clientName, //這句代碼應該是從camera jni連接到camera client的關鍵 上面有個clientName也說明了這點 ....... }3、Android camera Client和camera service調用流程
我只知道spCamera>是一個強指針引用,具體是多厲害百度一下更好
從client的代碼里面
frameworks/av/camera/Camera.cpp
為了查看它的調用流程,我加了一點日志在connect函數里面,加的日志代碼如下
template <typename TCam, typename TCamTraits> sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId,const String16& clientPackageName,int clientUid) {ALOGD("%s: weiqifa connect 23", __FUNCTION__);sp<TCam> c = new TCam(cameraId);sp<TCamCallbacks> cl = c;status_t status = NO_ERROR;const sp<ICameraService>& cs = getCameraService();if (cs != 0) {TCamConnectService fnConnectService = TCamTraits::fnConnectService;status = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid,/*out*/ c->mCamera);ALOGD("%s: weiqifa connect 234", __FUNCTION__);//ALOGD("cs.get()->*fnConnectService %s: weiqifawe", *(cs.get()->*fnConnectService));}if (status == OK && c->mCamera != 0) {c->mCamera->asBinder()->linkToDeath(c);c->mStatus = NO_ERROR;} else {ALOGW("An error occurred while connecting to camera: %d", cameraId);c.clear();}return c; }
我們可以看到CameraBase: connect: weiqifa connect 234這句話已經打印出來了
然后我們也可以看到CameraService::connect X 打印出來了
然后我們也可以看到CameraClient: CameraClient::initialize X這個也打印出來了
上面的三個日志還是非常重要的
看一下cameraservice.cpp的connect函數,service是服務端,client是客戶端,那么客戶端的實現在服務端應該有一個對應的函數
status_t CameraService::connect(const sp<ICameraClient>& cameraClient,int cameraId,const String16& clientPackageName,int clientUid,.....switch(deviceVersion) {case CAMERA_DEVICE_API_VERSION_1_0:client = new CameraClient(this, cameraClient,//new CameraClient 這個new了一個這個東西,那么CameraClient里面的東西就會被調用了clientPackageName, cameraId,facing, callingPid, clientUid, getpid()); ./frameworks/av/services/camera/libcameraservice/api1/CameraClient.cpp:73: status_t CameraClient::initialize(camera_module_t *module) {int callingPid = getCallingPid();status_t res;////看到這里的時候我突然看到了open的函數//但是有個問題很奇怪這個函數是誰調用了呢?誰讓他運行的??????LOG1("CameraClient::initialize E (pid %d, id %d)", callingPid, mCameraId);res = mHardware->initialize(&module->common);//這句還是比較關鍵的mHardware->initialize就是要獲取硬件設備的一些東東啊//......LOG1("CameraClient::initialize X (pid %d, id %d)", callingPid, mCameraId);return OK;./frameworks/av/services/camera/libcameraservice/device1/CameraHardwareInterface.h
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);if (rc != OK) {ALOGE("Could not open camera %s: %d", mName.string(), rc);return rc;}initHalPreviewWindow();return rc;}//日志里面也有這樣的打印01-01 22:23:00.999868 191 748 I CameraClient: Opening camera 0我們下一步就是要去找到hw_module_t這個結構體,找到了這個結構體就可以往下走
libcameraservice.so里面調用
void CameraService::onFirstRef() {LOG1("CameraService::onFirstRef weiqifa");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 {ALOGI("Loaded \"%s\" camera module", mModule->common.name);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++) {for (int i = 0; i < MAX_CAMERAS; i++) { // workaround for MATVLOG1("setCameraFree(%d)", i);setCameraFree(i);}if (mModule->common.module_api_version >=CAMERA_MODULE_API_VERSION_2_1) {mModule->set_callbacks(this);}CameraDeviceFactory::registerService(this);} }hw_get_module(CAMERA_HARDWARE_MODULE_ID這個是加載硬件hardware層對應的東東,具體可以查看鏈接hw_get_module獲取硬件模塊
看一下CAMERA_HARDWARE_MODULE_ID
hardware/libhardware/include/hardware/camera_common.h:35:#define CAMERA_HARDWARE_MODULE_ID "camera"看一下我們打印出來的日志
weiqifa@weiqifa-Inspiron-3847:~/weiqifa/log$ grep -wrn "CameraService::onFirstRef" ./ ./mobilelog/APLog_2010_0105_214945/main_log.boot:922:01-05 22:49:08.208839 194 194 D CameraService: CameraService::onFirstRef weiqifa weiqifa@weiqifa-Inspiron-3847:~/weiqifa/log$4、Android camera Hardware調用
hardware肯定是屬于平臺的特性,所以我們這里就要找到平臺特性的東西了。
從libcameraservice下來
hw_get_module這個東西就是獲取hardware下面的內容的東西。具體的可以看一下鏈接
hw_get_module
然后我們就找到了這個地方
./mediatek/hardware/mtkcam/module/module.h
里面的methods: get_module_methods()這個就是我們hardware的open函數
open_device(hw_module_t const* module, const char* name, hw_device_t** device) {return NSCam::getCamDeviceManager()->open(module, name, device); }static hw_module_methods_t* get_module_methods() {statichw_module_methods_t_methods ={open: open_device};return &_methods; }open_device就會找到NScam::getCamDeviceManager()->open
NSCam這個是一個命名空間,我看了網上的解釋,更像是類引用,后面我再跟進去找到open的地方
./mediatek/hardware/mtkcam/devicemgr/CamDeviceManagerBase.cpp
status_t CamDeviceManagerBase:: open(hw_module_t const* module, char const* name, hw_device_t** device ) {RWLock::AutoWLock _l(mRWLock);//return openDeviceLocked(module, name, device); }這里調用到了openDeviceLocked 我們找到這個地方
./mediatek/hardware/mtkcam/devicemgr/CamDeviceManagerBase.openDevice.cpp
總結
以上是生活随笔為你收集整理的Android Camera调用流程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (附代码)手写滑动验证码,完整代码开放
- 下一篇: ARM一面(二轮技术面)