1. 程式人生 > >Android Camera從Camera HAL1到Camera HAL3的過渡(已更新到Android6.0 HAL3.3)

Android Camera從Camera HAL1到Camera HAL3的過渡(已更新到Android6.0 HAL3.3)

本文均屬自己閱讀原始碼的點滴總結,轉賬請註明出處謝謝。

歡迎和大家交流。qq:1037701636 email:

Software:系統原始碼Android5.1

1. Android系統中Camera模組版本號的歷史演變進度

/**
 * All module versions <= HARDWARE_MODULE_API_VERSION(1, 0xFF) must be treated
 * as CAMERA_MODULE_API_VERSION_1_0
 */
#define CAMERA_MODULE_API_VERSION_1_0 HARDWARE_MODULE_API_VERSION(1, 0)
#define CAMERA_MODULE_API_VERSION_2_0 HARDWARE_MODULE_API_VERSION(2, 0)
#define CAMERA_MODULE_API_VERSION_2_1 HARDWARE_MODULE_API_VERSION(2, 1)
#define CAMERA_MODULE_API_VERSION_2_2 HARDWARE_MODULE_API_VERSION(2, 2)
#define CAMERA_MODULE_API_VERSION_2_3 HARDWARE_MODULE_API_VERSION(2, 3)

#define CAMERA_MODULE_API_VERSION_CURRENT CAMERA_MODULE_API_VERSION_2_3

/**
 * All device versions <= HARDWARE_DEVICE_API_VERSION(1, 0xFF) must be treated
 * as CAMERA_DEVICE_API_VERSION_1_0
 */
#define CAMERA_DEVICE_API_VERSION_1_0 HARDWARE_DEVICE_API_VERSION(1, 0)
#define CAMERA_DEVICE_API_VERSION_2_0 HARDWARE_DEVICE_API_VERSION(2, 0)
#define CAMERA_DEVICE_API_VERSION_2_1 HARDWARE_DEVICE_API_VERSION(2, 1)
#define CAMERA_DEVICE_API_VERSION_3_0 HARDWARE_DEVICE_API_VERSION(3, 0)
#define CAMERA_DEVICE_API_VERSION_3_1 HARDWARE_DEVICE_API_VERSION(3, 1)
#define CAMERA_DEVICE_API_VERSION_3_2 HARDWARE_DEVICE_API_VERSION(3, 2)

// Device version 3.2 is current, older HAL camera device versions are not
// recommended for new devices.
#define CAMERA_DEVICE_API_VERSION_CURRENT CAMERA_DEVICE_API_VERSION_3_2
從上述對Camera版本的定義可知,Android將整個camera模組劃分為module和device兩個部分,前者擁有對後者的控制權,而後者直接就是代表的camera hal介面的實現。

對於Module API的區別主要在於2.1之後增加了set_callbacks介面,用於HAL檢測當前module的工作狀態,低版本的module不需要實現。

此外對於Module API版本號高於2.2時可支援get_vendor_tag_ops,Framework呼叫後課獲取對廠商自己擴充套件定義的tag ops,便於操作廠商自己私有定義的camera所需的metadata資訊,同理低版本的module不需要去實現該介面。

此外對於Module API 為2.3的版本增加了open_legacy介面:

    int (*open_legacy)(const struct hw_module_t* module, const char* id,
            uint32_t halVersion, struct hw_device_t** device);

他描述的是可以根據自己所選的device version,比如對於一個camera hal他支援並實現了CAMERA_DEVICE_API_VERSION_1_0和CAMERA_DEVICE_API_VERSION_3_2兩種版本下的hal介面的實現,只有module api定義的是2.3的版本的話,在Framework中就可以通過對open_legacy()來指定hal_version,從而獲取不同版本下的hal device的實現介面即hw_device_t。但目前來看,Android提供了該介面,卻在Framework層都沒有給出直接的呼叫,此外可見的hal module api2.3的版本,也都不會去實現該介面。說明hw_module_t所屬的open目前依舊還是獲取對camera device控制權的唯一路徑與方法,也許對於一個camera device而言實現一種版本的介面就已經夠用和麻煩的了。

2 Camera Client

    關於CameraService相關的內容可以參考博文Android4.2.2 CameraService服務啟動和應用端camera初始化記錄來梳理整個Camera.so模組的載入與處理過程。每一個應用端的camera在connect到CameraService處會以一個Camera Client形式存在,該類繼承並實現CameraService::Client的一個內部類,通過匿名的Binder服務與應用端進行互動。在CamerService啟動並建立的時候,就會自動載入一個camera.xxx.so的模組,提取module相關的handle。

每當connect時,CameraService會執行一個getDeviceVersion的函式:

int CameraService::getDeviceVersion(int cameraId, int* facing) {
    struct camera_info info;
    if (mModule->get_camera_info(cameraId, &info) != OK) {
        return -1;
    }

    int deviceVersion;
    if (mModule->common.module_api_version >= CAMERA_MODULE_API_VERSION_2_0) {
        deviceVersion = info.device_version;
    } else {
        deviceVersion = CAMERA_DEVICE_API_VERSION_1_0;
    }

    if (facing) {
        *facing = info.facing;
    }

    return deviceVersion;
}
即對於那些module_api_version小於2.0的版本,即所謂的1.0版本外,其他module對應的device 版本號,由HAL自行決定,決定權通過get_camera_info來獲取hal支援的camera_info相關資訊,其中包括device_version。1.0版本的module直接預設的device_verison則為1.0版本。
     case CAMERA_DEVICE_API_VERSION_1_0:
            client = new CameraClient(this, cameraClient,
                    clientPackageName, cameraId,
                    facing, callingPid, clientUid, getpid(), legacyMode);
            break;
          case CAMERA_DEVICE_API_VERSION_2_0:
          case CAMERA_DEVICE_API_VERSION_2_1:
          case CAMERA_DEVICE_API_VERSION_3_0:
          case CAMERA_DEVICE_API_VERSION_3_1:
          case CAMERA_DEVICE_API_VERSION_3_2:
            client = new Camera2Client(this, cameraClient,
                    clientPackageName, cameraId,
                    facing, callingPid, clientUid, getpid(), legacyMode);//CameraService端新建Camera2Client
            break;
通過上述的程式碼邏輯可知,對於Camera Client的升級,由底層Device API Version來決定。很明顯可以知道,目前1.0的device api以CameraClient的形式存在,而2.0以上的版本則均以Camera2Client的形式存在。 

對於Camera模組不同版本的DEVICE_API來說,其區別本質上就是在HAL所需要實現的介面不同,分別由以下三個版本的device介面:

typedef struct camera_device {
    /**
     * camera_device.common.version must be in the range
     * HARDWARE_DEVICE_API_VERSION(0,0)-(1,FF). CAMERA_DEVICE_API_VERSION_1_0 is
     * recommended.
     */
    hw_device_t common;
    camera_device_ops_t *ops;
    void *priv;
} camera_device_t;
對應的是1.0的DEVICE_API,目前低版本的Android系統中以該方式來實現的較多。
typedef struct camera2_device {
    /**
     * common.version must equal CAMERA_DEVICE_API_VERSION_2_0 to identify
     * this device as implementing version 2.0 of the camera device HAL.
     */
    hw_device_t common;
    camera2_device_ops_t *ops;
    void *priv;
} camera2_device_t;
2.0版本的ops目前主流的IC廠商實現的較少。
typedef struct camera3_device {
    /**
     * common.version must equal CAMERA_DEVICE_API_VERSION_3_0 to identify this
     * device as implementing version 3.0 of the camera device HAL.
     *
     * Performance requirements:
     *
     * Camera open (common.module->common.methods->open) should return in 200ms, and must return
     * in 500ms.
     * Camera close (common.close) should return in 200ms, and must return in 500ms.
     *
     */
    hw_device_t common;
    camera3_device_ops_t *ops;
    void *priv;
} camera3_device_t;
對於3.0而言,也就是所謂的HAL3.0就體現在這裡,當下可見的只有高通、三星等有對該種介面形式進行了實現。

本質上來說,三個不同的版本都進行了全盤的升級,則重點則是歸於在HAL中按照Google在Framework層定義的camerax_device_ops來實現該種介面,相關介面的實現形式在分析高通的HAL架構時再去分析。

3 Camera device

對於三個不同版本的hal層介面,在Camera的Framework中實現的過程略有不同,可以分為device1、device2、device3。

對於1.0版本的Device API,在建立CameraClient時,是以CameraHardwareInterface(可以認為是Camera Device1)來維護隊整個對HAL層中Camera Device的控制權,即 camera_device_t歸CameraHardwareInterface來呼叫。

對於2.0以上版本的Device API時,在建立Camera2Client時,會通過CameraDeviceFactory::createDevice來建立相應的Camera Device

sp<CameraDeviceBase> CameraDeviceFactory::createDevice(int cameraId) {

    sp<CameraService> svc = sService.promote();
    if (svc == 0) {
        ALOGE("%s: No service registered", __FUNCTION__);
        return NULL;
    }

    int deviceVersion = svc->getDeviceVersion(cameraId, /*facing*/NULL);

    sp<CameraDeviceBase> device;

    switch (deviceVersion) {
        case CAMERA_DEVICE_API_VERSION_2_0:
        case CAMERA_DEVICE_API_VERSION_2_1:
            device = new Camera2Device(cameraId);
            break;
        case CAMERA_DEVICE_API_VERSION_3_0:
        case CAMERA_DEVICE_API_VERSION_3_1:
        case CAMERA_DEVICE_API_VERSION_3_2:
            device = new Camera3Device(cameraId);
            break;
        default:
            ALOGE("%s: Camera %d: Unknown HAL device version %d",
                  __FUNCTION__, cameraId, deviceVersion);
            device = NULL;
            break;
    }

    ALOGV_IF(device != 0, "Created a new camera device for version %d",
                          deviceVersion);

    return device;
}
可以看到對於Camera2Client而言,對Device API2.0、2.1的版本通過Camera2Device來實現對底層device的控制,對3.0以上的版本通過Camera3Device來實現,前者可以說是呼叫的是Camera HAL2.0相關的camera2_device_t的介面,後者呼叫的是Camera HAL3.0相關的camera3_device_t的介面,當然重點就是兩者內部實現的形式不同,3.0版本的處理也更顯的複雜。其中Camera Device API2.0的版本從Android4.2開始釋出,而API3更多的是對前者的升級與換代而已在4.4.2的版本中科院看到。

4.小結

Camera不斷的過渡,也算是Android系統原始碼中,變化較大的一個部分了,雖然Framework層核心的CameraService、Camera等的實現邏輯都沒有發生很大的變化,但和底層HAL的互動卻有著質的變異。而目前主流的IC廠商都在朝著Camera HAL3.0的方向進行發展,所有有必要對3.0實現的原理與本質進行探究與學習。

附圖:camera在Android Framework層中的變遷


Camera HAL1.0 在Android4.0 ICE開始;Camera HAL2.0、HAL3.0在Android4.2/4.3 JB版本開始支援;Camera HAL3.1 在Androiod4.4 KitKat開始Support;Camera HAL3.2 在Android5.0 L 開始支援;Camera API2在Android5.0 L開始支援,並逐步deprecate Camera API1。Android幾個版本下camera_common.h的文件集:Android4.0Android4.2Android4.3

相關推薦

Android CameraCamera HAL1到Camera HAL3過渡更新Android6.0 HAL3.3

本文均屬自己閱讀原始碼的點滴總結,轉賬請註明出處謝謝。歡迎和大家交流。qq:1037701636 email:Software:系統原始碼Android5.11. Android系統中Camera模組版本號的歷史演變進度/** * All module versions &

Android 如何應用深入到Framework

分享轉發,舉手之勞,手有餘香。 Android 如何從應用深入到Framework (一) 上節講到了孵化器,講到了system server程序,同時說了system server的一堆執行緒,比如我們熟悉的AMS WMS PMS ,這幾個服務執行緒,完成應

Android 如何應用深入到Framework

今天,明哥想跟大家聊聊,如何從應用開發,轉向Framework開發。 系統應用開發,現在來說,已經開始脫離系統,單獨拿出來開發,系統定製介面,已提供給應用呼叫,用來增強功能。 原生的桌面,撥號,設定,已經沒法做出差異化優勢,因此都費盡心機,來進行應用深度開發。 對於之前

Android研發-java基礎開始學 一般三天更新一次

   前言:  IT新人。。。新人。。。新人。。。(這個要說三遍)  做為一名機械設計的應屆生。已經走上了IT研發的 不歸路。並且越走越遠……  第一天​   ​經過一系列流程(省略幾千字)坐在自己的位置上,開始學java基礎了。 ​第一章   java語言

Android 系統自帶圖片裁剪功能適配7.0、8.0、對了還有小米手機

前段時間寫了如何獲取相簿和拍照之後的照片並且進行顯示和上傳,這一次是如何進行圓形影象製作,經常看我寫的筆記的人會知道,我很懶。那麼我就懶的自定義了,目前需求就用原生的就好了,大神的輪子,我會在後面進行推薦。這篇筆記是依賴於:Android呼叫相簿、相機(相容6.0、7.0、8.0) 文

推薦android幾本研究深入的書籍對開發人員很有幫助

 Android Web應用 Android 開發管家技術與精彩案例 Android 開發實戰經典 Android 平臺開發之旅 Android 開發應用實戰詳解 Android 經典應用程式開發 Android 開發應用從入門到精通 Android 從入門到精通 Android 開發寶典 Android 程

Android app 線上更新那點事兒適配Android6.0、7.0、8.0

一、前言 app線上更新是一個比較常見需求,新版本釋出時,使用者進入我們的app,就會彈出更新提示框,第一時間更新新版本app。線上更新分為以下幾個步驟: 1, 通過介面獲取線上版本號,versionCode 2, 比較線上的versionCode 和本地的versi

Ueditor增加文字豎排顯示和右向左輸入支援蒙古文和維吾爾文

平時我們在ueditor中都是輸入的中文,排版都是從左向右輸入。但是當輸入一些少數民民族言時,ueditor卻不能正常顯示。 例如蒙古文字,傳統蒙文是豎排書寫。如下圖:傳統蒙古文排文方式,《蒙古人的文字與書籍》   在word2010中,是支援豎排的,從左向右、從右向左都能完美

Android 版本更新適配7.0 xml配置

版本更新一般分兩種情況: 需要更新時跳轉到應用市場或者跳轉到瀏覽器處理 另一種情況則是在App內進行更新 第一種沒什麼好說的,本文主要是實現應用內進行更新 App內部更新分以下幾個步驟: 檢測App版本 下載Apk 安裝已下載完成的Apk 下面貼上例項: 1.

零開始學USB十、USB的描述符

USB裝置使用描述符報告其屬性。描述符是具有定義格式的資料結構。每個描述符都以位元組寬度欄位開頭,該欄位包含描述符中的總位元組數,後跟一個標識描述符型別的位元組寬度欄位。 使用描述符允許簡單地儲存各個配置的屬性,因為每個配置可以重用具有相同特徵的其他配置的描述符或描述符的部分。以這種方式,描

零開始學USB五、USB的電器特性

關於機械特性就不在這裡詳細描述了,這裡列出幾個重要的知識點。 USB電纜:標準的USB電纜包括一對用於電源分配的20~28AWG規格的線對和一對28AWG規格的雙絞線,並具有遮蔽和完整的保護層。 高速(480 Mb / s)和全速(12 Mb / s)要求使用帶有兩根電源導線和雙絞線訊號

Android許可權管理原理含6.0-4.3

Android 4.3-5.1 AppOpsManager動態許可權管理(官方不成熟的許可權管理) AppOpsManager 是Google在Android4.3-Android5.0引入的動態許可權管理方式,但是又與Google覺得不成熟,所以在每個發行版

Android怎樣控制評價小星星的顯示能獲取到星星的個數

程式碼中: mRatingBar.setRating(3.8f); 程式碼: package com.example.sj.xiaoxingxing2; import android.app.Ac

有五個學生,每個學生有3門課的成績, 鍵盤輸入以上資料包括姓名,三門課成績, 輸入的格式:如:zhagnsan,30,40,60計算出總成績, 並把學生的資訊和計算出的總分數高低順序存放在磁碟文

有五個學生,每個學生有3門課的成績, 從鍵盤輸入以上資料(包括姓名,三門課成績), 輸入的格式:如:zhagnsan,30,40,60計算出總成績, 並把學生的資訊和計算出的總分數高低順序存放在磁碟檔案"stud.txt"中。 1:定義一個描述學生的類2定義一個操作學生的工

Android自定義主題樣式詳解結合自定義title欄講解

此篇部落格將總結主題樣式的自定義並且結合例項自定義title欄進行講解。為了方便閱讀,在此先寫明文章結構: 1.對android主題樣式的理解 (簡略結合系統自帶樣式的講解) 2.如何自定義主題樣式 (主要,有例子) 3.如何自定義titl

Android程式設計心得-常見問題解決辦法不斷更新中..

1.進行模擬器除錯時出現 Failed to install Remote_Monitoring.apk on device 'emulator-5554': timeout      解決辦法:在Eclipse-->Window-->Preferences--

Android 相簿或者拍照設定頭像,相容Android6.0後許可權問題

                                    平時開發中我們會需要設定使用者頭像  從手機相簿或者拍照設定,在Android6.0以前還不用考慮許可權問題,到了6.0後還需要考慮許可權問題,這裡我們就來給大家一起處理下。有些可能不完善大家自己完善

Android讀取assets目錄下的資源 webview載入assets下的html

1。獲取資源的輸入流 資原始檔 sample.txt 位於 $PROJECT_HOME/assets/ 目錄下,可以在 Activity 中通過 Context.getAssets().open(“sample.txt”) 方法獲取輸入流。 注意:如果資原始檔是文字檔案

android中引用Library中的Activity 針對eclipse,as沒有這個問題

第一輯:小試牛刀 我們在一些專案中需要使用我們自定義的一個包中的Activity,那麼我們如何開啟Library中的Activity呢?下面我們就來研究一下吧: 第一步,我們需要清楚的是,我們在把library中作為一個庫引入我們的專案中的時候,library中的資原始

ffmpeg 記憶體中讀取資料或將資料輸出到記憶體

原文見雷大神部落格:http://blog.csdn.net/leixiaohua1020/article/details/12980423 更新記錄(2014.7.24): 1.為了使本文更通俗易懂,更新了部分內容,將例子改為從記憶體中開啟。 2.增加了將資料輸出