日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android Camera调用流程

發布時間:2023/12/20 Android 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android Camera调用流程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一個流程圖畫的非常好的文章

http://blog.csdn.net/lushengchu_luis/article/details/11033095

1、Packages/apps/到framework 打開Camera

  • ./packages/apps/Camera/src/com/android/camera/Camera.java
  • 進來第一個肯定是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調用流程

  • 還是open這個接口
  • 代碼路徑:./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就是打開攝像頭的關鍵了
  • jni的調用接口
    看到這個native 函數說明這個函數是在jni接口,用的是c++代碼實現的,so,我們繼續找
    private native final void native_setup(Object camera_this, int cameraId,
    終于我們在./frameworks/base/core/jni/android_hardware_Camera.cpp
    這里面找到了這個函數,然后我們看一下這個函數
  • 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;ILjava/lang/String;)V",(void*)android_hardware_Camera_native_setup },//從這里可以看出來,實現這個函數的真正函數是android_hardware_Camera_native_setup//所以我們繼續找一下這個函數在哪里{ "native_release","()V",

    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

    sp<Camera> Camera::connect(int cameraId, const String16& clientPackageName,int clientUid) {return CameraBaseT::connect(cameraId, clientPackageName, clientUid);//CameraBaseT::connect這個又是從哪里來的,而且都是c++這可是難倒了我//不太好辦 } //在./frameworks/av/include/camera/CameraBase.h:113: //typedef CameraBase<TCam> CameraBaseT; //里面有一個typedef 好了,那我們下一句就應該去找CameraBase<TCam>這個東西 //找到在這個位置 //./frameworks/av/camera/CameraBase.cpp:94:sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId, sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId,const String16& clientPackageName,int clientUid) {ALOGV("%s: connect", __FUNCTION__);sp<TCam> c = new TCam(cameraId);sp<TCamCallbacks> cl = c;status_t status = NO_ERROR;//下一步就應該到getCameraService這里來了//這時候我們就要到cameraservice.java里面去看代碼了const sp<ICameraService>& cs = getCameraService();if (cs != 0) {TCamConnectService fnConnectService = TCamTraits::fnConnectService;status = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid,/*out*/ c->mCamera);}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; }

    為了查看它的調用流程,我加了一點日志在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下來

    if (hw_get_module(CAMERA_HARDWARE_MODULE_ID,(const hw_module_t **)&mModule) < 0) {ALOGE("Could not load camera HAL module");mNumberOfCameras = 0;}

    hw_get_module這個東西就是獲取hardware下面的內容的東西。具體的可以看一下鏈接
    hw_get_module
    然后我們就找到了這個地方
    ./mediatek/hardware/mtkcam/module/module.h

    static camera_module get_camera_module() {camera_module module = { common: { tag: HARDWARE_MODULE_TAG, module_api_version: CAMERA_MODULE_API_VERSION_2_1, hal_api_version: HARDWARE_HAL_API_VERSION, id: CAMERA_HARDWARE_MODULE_ID, name: "MediaTek Camera Module", author: "MediaTek", methods: get_module_methods(), dso: NULL, reserved: {0}, }, get_number_of_cameras: get_number_of_cameras, get_camera_info: get_camera_info, set_callbacks: set_callbacks, };return module; }

    里面的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

    /*************************************************************************************************************************************************************/ status_t CamDeviceManagerBase:: openDeviceLocked(hw_module_t const* module, char const* name, hw_device_t** device ) {status_t status = OK;sp<ICamDevice> pDevice = NULL;int32_t const i4OpenId = (name != NULL) ? ::atoi(name) : -1;//String8 const s8ClientAppMode = queryClientAppMode();uint32_t const version = determineOpenDeviceVersionLocked(s8ClientAppMode, i4OpenId);//MY_LOGD("+ mOpenMap.size:%d mEnumMap.size:%d", mOpenMap.size(), mEnumMap.size());//// [1] check to see whether it's ready to open.if ( OK != (status = validateOpenLocked(i4OpenId)) ){return status;}//// [2] get platformIPlatform*const pPlatform = getPlatform();if ( ! pPlatform ){MY_LOGE("No Platform");return NAME_NOT_FOUND;}//// [3] create device based on device version.if ( version == CAMERA_DEVICE_API_VERSION_1_0 ){pDevice = pPlatform->createCam1Device(s8ClientAppMode.string(), i4OpenId);}elseif ( version >= CAMERA_DEVICE_API_VERSION_3_0 ){MY_LOGE("Unsupported version:0x%x >= CAMERA_DEVICE_API_VERSION_3_0", version);return UNKNOWN_ERROR;}else{MY_LOGE("Unsupported version:0x%x", version);return UNKNOWN_ERROR;}//if ( pDevice == 0 ){MY_LOGE("device creation failure");return NO_MEMORY;}//// [4] open device successfully.{*device = const_cast<hw_device_t*>(pDevice->get_hw_device());//pDevice->set_hw_module(module);pDevice->set_module_callbacks(mpModuleCallbacks);pDevice->setDeviceManager(this);//attachDeviceLocked(pDevice);}//return OK; }

    總結

    以上是生活随笔為你收集整理的Android Camera调用流程的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。