1. 程式人生 > >Android Camera2架構及原理分析

Android Camera2架構及原理分析

請點選轉載地址

前面幾篇主要分析的是android Camera API1.0的架構以及初始化流程,而google在android5.0(Lollipop)開始對Camera的架構進行了調整,為了適應HAL3,新新增實現了CameraDeviceClient,而Camera API1.0已經被deprecated(即可能在更新的版本里會不支援此API).


接下來,我將會分如下幾篇文章來分析Camera2
android6.0原始碼分析之Camera API2.0簡介
android6.0原始碼分析之Camera2 HAL分析
android6.0原始碼分析之Camera API2.0下的初始化流程分析


android6.0原始碼分析之Camera API2.0下的Preview(預覽)流程分析
android6.0原始碼分析之Camera API2.0下的Capture流程分析
android6.0原始碼分析之Camera API2.0下的video流程分析
Camera API2.0的應用


1、Camera API2.0的架構圖

Camera API2.0下的Camera架構與API1.0有所區別,下面將給出Camera API2.0以及Camera HAL3.2+下的Camera的總體架構圖:
這裡寫圖片描述
由圖可知,Java層要想與C++層的CameraService層進行通訊,都是通過Java層的IPC Binder進位制進行的,主要包括ICameraService.aidl以及ICameraDeviceUser.aidl兩個介面來實現,其會在Java層維護一個CameraDeviceImpl即Camera裝置的代理,而CameraService以及CameraDeviceImpl的初始化會在此文的第二,第三節進行分析。而Java層對Camera的具體操作的操作流程大致為,Java層通過Device代理髮送一個CaptureRequest,而C++層進行相應的處理,再呼叫相應的回撥來通知Java相應的處理結果,並將相應的Capture資料儲存在Surface Buffer裡,這樣Java層在回撥函式中可以對資料進行相應的處理。而對於具體操作流程的分析,請參考文章開始時的Camera2相關文章的連線。


2、Java層的CameraService的實現和應用

從Camera API2開始,Camera的實現方式有所不同,最主要的區別是不再使用JNI來呼叫原生代碼,從而獲得本地CameraService,並實現其C/S模式的通訊,而是直接在Java層通過Java層的IPC Binder機制來獲取Java層的CameraService的代理物件,從而直接在Java層獲取本地的CameraService與Camera Device進行相應的通訊。
相應的程式碼及目錄:
ICameraService.aidl:frameworks/base/core/java/android/hardware
CameraService.cpp:frameworks/av/services/camera/libcameraservice
CameraManager.java:frameworks/base/core/java/android/hardware/camera2

獲取CameraService的核心程式碼如下:

//CameraManager.java
prvate void connectCameraServiceLocked(){
    if(mCameraService != null)return;
    //獲取Binder
    IBinder cameraServiceBinder = ServiceManager.getService(CAMERA_SERVICE_BINDER_NAME);
    if(cameraServiceBinder == null){
        return;
    }
    try{
        cameraServiceBinder.linkToDeath(this,/*flags*/ 0);
    }catch(RemoteException e){
        return;
    }
    ICameraService cameraServiceRaw = ICameraService.Stub.asInterface(cameraServiceBinder);
    //根據cameraServiceRaw 建立CameraService例項
    ICameraService cameraService = CameraServiceDecorator.newInstance(cameraServiceRaw);
    ...
    try{
        //新增監聽
        cameraService.addListener(this);
        //賦值給mCameraService的全域性變數
        mCameraService = cameraService;
    }catch(CameraRuntimeException e){
        ...
    }
}
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

由程式碼可知,通過Java層的Binder從ServiceManager裡獲取了一個Java層的CameraService例項,在開啟Camera的流程中,會通過此CameraService(Native的CameraService)與Camera通訊,而其中的通訊通過ICameraDeviceUser來實現,接下來分析ICameraDeviceUser的實現。

3、ICameraDeviceUser.aidl的通訊實現

Java層與C++ CameraService層之間的通訊,通過封裝了一個CameraDeviceUser來實現,它只是在Java層使用了AIDL技術來實現Client,即在Java層維護了一個CameraDevice,這樣的好處是響應速度更快,因為這樣不需要通過每次進入Native層來完成通訊,而可以通過Java層的IPC Binder機制即可完成。即API2.0通過AIDL實現一個介面ICameraDeviceUser,從而在Java層維護一個Camera proxy,之後的通訊都是通過此代理CameraDeviceImpl來實現。

相關程式碼及目錄:
ICameraDeviceUser.aidl:frameworks/base/core/java/android/hardware/camera2
ICameraDeviceUser.cpp:frameworks/av/camera/camera2
CameraDeviceImpl.java:frameworks/base/core/java/android/hardware/camera2/impl

獲取Camera Device的Java層代理的核心程式碼如下:

//CameraManager.java
private CameraDevice openCameraDeviceUserAsync(...){
    //初始化Camera Java層代理物件
    CameraDevice device = null;
    try{
        synchronized(mLock){
            //初始化ICameraDeviceUser
            ICameraDeviceUser cameraUser = null;
            //初始化具體的CameraDevice代理
            android.hardware.camera2.impl.CameraDeviceImpl deviceImpl = new android.hardware.
                camera2.impl.CameraDeviceImpl(cameraId,callback,handler,characteristics);
            BinderHolder holder = new BinderHolder();
            ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks();
            ...
            try{
                //如果支援HAL3.2+的devices
                if(supportsCamera2ApiLocked(cameraId)){
                    //獲取CameraService
                    ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
                    ...
                    //連線裝置
                    cameraService.connectDevice(callbacks,id,mContextgetOpPackageName()
                        ,USE_CALLING_UID,holder);
                    //通過Binder獲得開啟的Camera裝置返回的Camera代理
                    cameraUser = ICameraDeviceUser.Stub.asInterface(holder.getBinder());
                }else{//否則用遺產API
                    cameraUser = CameraDeviceUserShim.connectBinderShim(callbacks,id);
                }
            }catch(...){
                ...
            }
            //包裝代理物件
            deviceImpl.setRemoteDevice(cameraUser);
            device = deviceImpl;
        }
    }catch(...){
        ...
    }
    返回Camera代理
    return device;
}
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

由程式碼可知,首先獲取CameraService,然後通過它來開啟Camera,而開啟成功後,C++層會返回一個Camera device代理物件,此處即為ICameraDeviceUser,所以在Java層對其進行相應的封裝,變成一個CameraDeviceImpl物件,此後,只要需要對Camera進行操作,都會呼叫CameraDeviceImpl物件的相關方法,並通過ICameraDeviceUser以及Java IPC Binder來與本地的Camera device進行通訊,至此,Camera API2.0的框架就分析結束了,具體的操作,如Camera的初始化,preview,capture等流程的分析,請看文章開始時,所列出的分析連結。

        <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/markdown_views-ea0013b516.css">
            </div>

前面幾篇主要分析的是android Camera API1.0的架構以及初始化流程,而google在android5.0(Lollipop)開始對Camera的架構進行了調整,為了適應HAL3,新新增實現了CameraDeviceClient,而Camera API1.0已經被deprecated(即可能在更新的版本里會不支援此API).


接下來,我將會分如下幾篇文章來分析Camera2
android6.0原始碼分析之Camera API2.0簡介
android6.0原始碼分析之Camera2 HAL分析
android6.0原始碼分析之Camera API2.0下的初始化流程分析
android6.0原始碼分析之Camera API2.0下的Preview(預覽)流程分析
android6.0原始碼分析之Camera API2.0下的Capture流程分析
android6.0原始碼分析之Camera API2.0下的video流程分析
Camera API2.0的應用


1、Camera API2.0的架構圖

Camera API2.0下的Camera架構與API1.0有所區別,下面將給出Camera API2.0以及Camera HAL3.2+下的Camera的總體架構圖:
這裡寫圖片描述
由圖可知,Java層要想與C++層的CameraService層進行通訊,都是通過Java層的IPC Binder進位制進行的,主要包括ICameraService.aidl以及ICameraDeviceUser.aidl兩個介面來實現,其會在Java層維護一個CameraDeviceImpl即Camera裝置的代理,而CameraService以及CameraDeviceImpl的初始化會在此文的第二,第三節進行分析。而Java層對Camera的具體操作的操作流程大致為,Java層通過Device代理髮送一個CaptureRequest,而C++層進行相應的處理,再呼叫相應的回撥來通知Java相應的處理結果,並將相應的Capture資料儲存在Surface Buffer裡,這樣Java層在回撥函式中可以對資料進行相應的處理。而對於具體操作流程的分析,請參考文章開始時的Camera2相關文章的連線。


2、Java層的CameraService的實現和應用

從Camera API2開始,Camera的實現方式有所不同,最主要的區別是不再使用JNI來呼叫原生代碼,從而獲得本地CameraService,並實現其C/S模式的通訊,而是直接在Java層通過Java層的IPC Binder機制來獲取Java層的CameraService的代理物件,從而直接在Java層獲取本地的CameraService與Camera Device進行相應的通訊。
相應的程式碼及目錄:
ICameraService.aidl:frameworks/base/core/java/android/hardware
CameraService.cpp:frameworks/av/services/camera/libcameraservice
CameraManager.java:frameworks/base/core/java/android/hardware/camera2

獲取CameraService的核心程式碼如下:

//CameraManager.java
prvate void connectCameraServiceLocked(){
    if(mCameraService != null)return;
    //獲取Binder
    IBinder cameraServiceBinder = ServiceManager.getService(CAMERA_SERVICE_BINDER_NAME);
    if(cameraServiceBinder == null){
        return;
    }
    try{
        cameraServiceBinder.linkToDeath(this,/*flags*/ 0);
    }catch(RemoteException e){
        return;
    }
    ICameraService cameraServiceRaw = ICameraService.Stub.asInterface(cameraServiceBinder);
    //根據cameraServiceRaw 建立CameraService例項
    ICameraService cameraService = CameraServiceDecorator.newInstance(cameraServiceRaw);
    ...
    try{
        //新增監聽
        cameraService.addListener(this);
        //賦值給mCameraService的全域性變數
        mCameraService = cameraService;
    }catch(CameraRuntimeException e){
        ...
    }
}
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

由程式碼可知,通過Java層的Binder從ServiceManager裡獲取了一個Java層的CameraService例項,在開啟Camera的流程中,會通過此CameraService(Native的CameraService)與Camera通訊,而其中的通訊通過ICameraDeviceUser來實現,接下來分析ICameraDeviceUser的實現。

3、ICameraDeviceUser.aidl的通訊實現

Java層與C++ CameraService層之間的通訊,通過封裝了一個CameraDeviceUser來實現,它只是在Java層使用了AIDL技術來實現Client,即在Java層維護了一個CameraDevice,這樣的好處是響應速度更快,因為這樣不需要通過每次進入Native層來完成通訊,而可以通過Java層的IPC Binder機制即可完成。即API2.0通過AIDL實現一個介面ICameraDeviceUser,從而在Java層維護一個Camera proxy,之後的通訊都是通過此代理CameraDeviceImpl來實現。

相關程式碼及目錄:
ICameraDeviceUser.aidl:frameworks/base/core/java/android/hardware/camera2
ICameraDeviceUser.cpp:frameworks/av/camera/camera2
CameraDeviceImpl.java:frameworks/base/core/java/android/hardware/camera2/impl

獲取Camera Device的Java層代理的核心程式碼如下:

//CameraManager.java
private CameraDevice openCameraDeviceUserAsync(...){
    //初始化Camera Java層代理物件
    CameraDevice device = null;
    try{
        synchronized(mLock){
            //初始化ICameraDeviceUser
            ICameraDeviceUser cameraUser = null;
            //初始化具體的CameraDevice代理
            android.hardware.camera2.impl.CameraDeviceImpl deviceImpl = new android.hardware.
                camera2.impl.CameraDeviceImpl(cameraId,callback,handler,characteristics);
            BinderHolder holder = new BinderHolder();
            ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks();
            ...
            try{
                //如果支援HAL3.2+的devices
                if(supportsCamera2ApiLocked(cameraId)){
                    //獲取CameraService
                    ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
                    ...
                    //連線裝置
                    cameraService.connectDevice(callbacks,id,mContextgetOpPackageName()
                        ,USE_CALLING_UID,holder);
                    //通過Binder獲得開啟的Camera裝置返回的Camera代理
                    cameraUser = ICameraDeviceUser.Stub.asInterface(holder.getBinder());
                }else{//否則用遺產API
                    cameraUser = CameraDeviceUserShim.connectBinderShim(callbacks,id);
                }
            }catch(...){
                ...
            }
            //包裝代理物件
            deviceImpl.setRemoteDevice(cameraUser);
            device = deviceImpl;
        }
    }catch(...){
        ...
    }
    返回Camera代理
    return device;
}
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

由程式碼可知,首先獲取CameraService,然後通過它來開啟Camera,而開啟成功後,C++層會返回一個Camera device代理物件,此處即為ICameraDeviceUser,所以在Java層對其進行相應的封裝,變成一個CameraDeviceImpl物件,此後,只要需要對Camera進行操作,都會呼叫CameraDeviceImpl物件的相關方法,並通過ICameraDeviceUser以及Java IPC Binder來與本地的Camera device進行通訊,至此,Camera API2.0的框架就分析結束了,具體的操作,如Camera的初始化,preview,capture等流程的分析,請看文章開始時,所列出的分析連結。

        <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/markdown_views-ea0013b516.css">
            </div>