camera打開流程(Camera App--->JNI)


參考:

http://blog.csdn.net/vasvas/article/details/50109907

 
一.Android Camera 運行流程的綜述

總體架構
   CameraService服務的注冊
   client端的應用層到JNI層Camera App---JNI
   client到service的連接
HAL層
驅動層

1.總體架構
   Android Camera 框架從整體上看是一個 client/service 的架構,
有兩個進程:
   client 進程,可以看成是 AP 端,主要包括 JAVA 代碼與一些 native c/c++代碼;
   service 進 程,屬於服務端,是 native c/c++代碼,主要負責和 linux kernel 中的 camera driver 交互,搜集 linuxkernel 中 cameradriver 傳上來的數據,並交給顯示系統顯示。
   client 進程與 service 進程通過 Binder 機制通信, client 端通過調用 service 端的接口實現各個具體的功能。

 

 

 

二.CameraService服務的注冊

 

SystemServer.java (frameworks\base\services\java\com\android\server)

在systemsever里面注冊很多服務,包括CameraService

startOtherServices

    mSystemServiceManager.startService(CameraService.class);

 

Main_mediaserver.cpp (frameworks\av\media\mediaserver)

    main

        CameraService::instantiate();
        可是我們到CameraService文件里面卻找不到instantiate()這個函數,它在哪?繼續追到它的一個父類BinderService,
        從以上定義可以看出CameraService 繼承於BinderService,所以CameraService::instantiate(); 其實是調用BinderService中的instantiate。

BinderService的定義在frameworks/av/base/include/binder/BinderService.h中
// ---------------------------------------------------------------------------
namespace android {

template<typename SERVICE>    

class BinderService

{

    public:

        static status_t publish() {

        sp<IServiceManager> sm(defaultServiceManager());

        return sm->addService(String16(SERVICE::getServiceName()), new SERVICE());
}
static void publishAndJoinThreadPool() {

}

static void publishAndJoinThreadPool() {

    sp<ProcessState> proc(ProcessState::self());

    sp<IServiceManager> sm(defaultServiceManager());

    sm->addService(String16(SERVICE::getServiceName()), new SERVICE());

    ProcessState::self()->startThreadPool();

    IPCThreadState::self()->joinThreadPool();
}

}

}    

static void instantiate() { publish(); }

   static status_t shutdown() {

        return NO_ERROR;

    }
};

};

}; // namespace android
// ---------------------------------------------------------------------------
    可以發現在publish()函數中,CameraService完成服務的注冊 。這里面有個SERVICE,源碼中有說明 template<typename SERVICE>
這表示SERVICE是個模板,這里是注冊CameraService,所以可以用CameraService代替
return sm->addService(String16(CameraService::getServiceName()), new CameraService());
    這樣,Camera就在ServiceManager完成服務注冊,提供給client隨時使用。
Main_MediaServer主函數由init.rc在啟動是調用,所以在設備開機的時候Camera就會注冊一個服務,用作binder通信。

 

 

三.client端的應用層到framework層

   從第2節的分析中可知,Binder服務已注冊,那接下來就看看client如何連上server端,並打開camera模塊。先從camera app的源碼入手。在onCreate()函數中專門有一個open Camera的線程。

 

應用層
camera app的源碼文件在以下目錄packages/apps/LegacyCamera/src/com/android/camera/camera.java
@Override
public void onCreate(Bundle icicle) {

super.onCreate(icicle);

getPreferredCameraId();

String[] defaultFocusModes = getResources().getStringArray(

R.array.pref_camera_focusmode_default_array);

mFocusManager = new FocusManager(mPreferences, defaultFocusModes);

 

/*

* To reduce startup time, we start the camera open and preview threads.

* We make sure the preview is started at the end of onCreate.

*/

mCameraOpenThread.start();

................

mCameraPreviewThread = null;

}
再看看mCameraOpenThread

Thread mCameraOpenThread = new Thread(new Runnable() {
  public void run() {
  try {
    mCameraDevice = Util.openCamera(Camera.this, mCameraId);
  } catch (CameraHardwareException e) {
     mOpenCameraFail = true;
  } catch (CameraDisabledException e) {
    mCameraDisabled = true;
  }
}
});
 

繼續追Util.openCamera ,Util類的定義在以下目錄:packages/apps/LegacyCamera/src/com/android/camera/Util.java

public static android.hardware.Camera openCamera(Activity activity, int cameraId)
throws CameraHardwareException, CameraDisabledException {
  // Check if device policy has disabled the camera.
  ...............
  try {
      return CameraHolder.instance().open(cameraId);
   } catch (CameraHardwareException e) {
   // In eng build, we throw the exception so that test tool
   // can detect it and report it
      if ("eng".equals(Build.TYPE)) {
           throw new RuntimeException("openCamera failed", e);
      } else {
           throw e;
    }
  }
}
 

又來了個CameraHolder,該類用一個實例open Camera
CameraHolder的定義在以下目錄:packages/apps/LegacyCamera/src/com/android/camera/CameraHolder.java

public synchronized android.hardware.Camera open(int cameraId)
throws CameraHardwareException {
    ..............
   if (mCameraDevice == null) {
     try {
       Log.v(TAG, "open camera " + cameraId);
        mCameraDevice = android.hardware.Camera.open(cameraId);//進入framework層
       mCameraId = cameraId;
   } catch (RuntimeException e) {
      Log.e(TAG, "fail to connect Camera", e);
      throw new CameraHardwareException(e);
  }
   mParameters = mCameraDevice.getParameters();
} else {
   ............
}
   ++mUsers;
   mHandler.removeMessages(RELEASE_CAMERA);
   mKeepBeforeTime = 0;
   return mCameraDevice;
}
 

 

自己分析的流程

CameraManager.java (packages\apps\camera\src\com\android\camera)
onCreate
    Thread mCameraOpenThread = new Thread(new Runnable() //創建一個線程用於打開攝像頭 
         mCameraDevice = Util.openCamera(Camera.this, mCameraId); //執行函數是打開攝像頭方法
   mCameraOpenThread.start();     //啟動這個線程,所以調用Util.openCamera(Camera.this, mCameraId);
         mCameraDevice = Util.openCamera(Camera.this, mCameraId);
            Util.java (packages\apps\legacycamera\src\com\android\camera)里面
            CameraHolder.instance().open(cameraId); 
                //CameraHolder.java (packages\apps\legacycamera\src\com\android\camera)
                mCameraDevice = android.hardware.Camera.open(cameraId); //進入framework層
 
 
 
 
四.framework到jni
    其中調用frameworks\base\core\java\android\hardware\Camera.java類的open方法 ,進入Framework層。
public static Camera open(int cameraId) 

其Framework層的open函數定義在如下文件中:frameworks\base\core\java\android\hardware\Camera.java    
    return new Camera(cameraId);
}
這里調用了Camera的構造函數,對Camera類的一些參數進行簡單初始化,其構造函數如下:

Camera(int cameraId) {
    mShutterCallback = null;
    mRawImageCallback = null;
    mJpegCallback = null;
    mPreviewCallback = null;
    mPostviewCallback = null;
    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;
  }


native_setup(new WeakReference<Camera>(this), cameraId);  //調用JNI
}
 

從這里開始通過JNI調用到native_setup( ),這里在系統上電時已經把JNI的一個對象注冊成類Camer的Listener。

 

native_setup( )接口在libandroid_runtime.so中實現,由Framework層通過JNI調用該接口。該接口主要是實現如下兩個功能:
1、實現CameraC/S架構的客戶端和服務端的連接(通過調用connect方法,進入libcamera_client.so)

2、set一個監聽類,用於處理底層Camera回調函數傳來的數據和消息

 
 
自己分析的流程
public static Camera open(int cameraId) 
    new Camera(cameraId);
        int err = cameraInitNormal(cameraId);
             cameraInitVersion(cameraId, CAMERA_HAL_API_VERSION_NORMAL_CONNECT);  //通過指定API版本號,進行初始化
                if ((looper = Looper.myLooper()) != null) {
                    mEventHandler = new EventHandler(this, looper);  //這里初始化一個消息等待隊列
                native_setup(new WeakReference<Camera>(this), cameraId, halVersion, ActivityThread.currentOpPackageName()); //從這里進入JNI
 
 
 
 
五.JNI到HAL層

native_setup()的定義在如下源文件中:frameworks/base/core/jni/android_hardware_Camera.cpp
static JNINativeMethod camMethods[] = {
    { "native_setup",    "(Ljava/lang/Object;I)V", (void*)android_hardware_Camera_native_setup },

   { "startPreview","()V", (void *)android_hardware_Camera_startPreview },

   { "native_autoFocus","()V", (void *)android_hardware_Camera_autoFocus },
    ..................
};
    通過這個定義,使得native_setup( )和android_hardware_Camera_native_setup( )關聯起來。所以,native_setup(new WeakReference<Camera>(this), cameraId);這個調用即是對下面android_hardware_Camera_native_setup( )這個函數的調用:


// connect to camera service
static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, jobject weak_this, jint cameraId)
{

sp<Camera> camera = Camera::connect(cameraId);

...........

// make sure camera hardware is alive

if (camera->getStatus() != NO_ERROR) {

jniThrowRuntimeException(env, "Camera initialization failed");

return;

}

...........

// We use a weak reference so the Camera object can be garbage collected.

// The reference is only used as a proxy for callbacks.

sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera);

context->incStrong(thiz);

camera->setListener(context);

// save context in opaque field

env->SetIntField(thiz, fields.context, (int)context.get());

}
    JNI函數里面,我們找到Camera C/S架構的客戶端了,它調用connect函數向服務器發送連接請求。JNICameraContext這個類是一個監聽類,用於處理底層Camera回調函數傳來的數據和消息。

 

 

自己分析的流程

    static JNINativeMethod camMethods[] = {

         { "native_setup","(Ljava/lang/Object;IILjava/lang/String;)I",  (void*)android_hardware_Camera_native_setup }, //對應的調用android_hardware_Camera_native_setup 

 

   android_hardware_Camera_native_setup 

             jint status = Camera::connectLegacy(cameraId, halVersion, clientName,Camera::USE_CALLING_UID, camera); //這里進入service

              sp<JNICameraContext> context = new MtkJNICameraContext(env, weak_this, clazz, camera); //用於處理底層Camera回調函數傳來的數據和消息。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM