相機

Android Camera HAL 圖示

Android 的相機硬體抽象層 (HAL) 會將 Camera 2 中的高階相機架構 API 連線至底層相機驅動程式和硬體。相機子系統包含相機管道元件的實作項目,而相機 HAL 則提供介面,用於實作這些元件的版本。

建築

下圖和清單說明 HAL 元件。

Android 相機架構

圖 1. 相機架構

應用程式架構
在應用程式架構層級,應用程式的程式碼會使用 Camera 2 API 與相機硬體互動。在內部,這段程式碼會呼叫對應的 Binder 介面,存取與攝影機互動的原生程式碼。
AIDL
CameraService 相關聯的繫結器介面位於 frameworks/av/camera/aidl/android/hardware。 產生的程式碼會呼叫較低層級的原生程式碼,取得實體攝影機的存取權,並傳回用於建立 CameraDevice 和最終 CameraCaptureSession 物件的資料 (位於架構層級)。
原生架構
這個架構位於 frameworks/av/ 中,提供與 CameraDevice CameraCaptureSession 類別對應的原生類別。另請參閱 NDK camera2 參考資料
繫結器 IPC 介面
IPC 繫結器介面可促進跨程序界線的通訊。 frameworks/av/camera/camera/aidl/android/hardware 目錄中有幾個攝影機繫結器類別,會呼叫攝影機服務。 ICameraService 是相機服務的介面; ICameraDeviceUser 是特定已開啟相機裝置的介面; ICameraServiceListener ICameraDeviceCallbacks 分別是應用程式架構的 CameraServiceCameraDevice 回呼。
攝影機服務
位於 frameworks/av/services/camera/libcameraservice/CameraService.cpp 的攝影機服務,是與 HAL 互動的實際程式碼。
HAL
硬體抽象層定義相機服務呼叫的標準介面,您必須實作這個介面,相機硬體才能正常運作。

實作 HAL

HAL 位於相機驅動程式和較高層級的 Android 架構之間,並定義您必須實作的介面,應用程式才能正確操作相機硬體。相機 HAL 的 HIDL 介面定義於 hardware/interfaces/camera

典型的繫結 HAL 必須實作下列 HIDL 介面:

參考 HIDL 實作適用於 CameraProvider.cpp CameraDevice.cppCameraDeviceSession.cpp。實作會包裝仍使用舊版 API 的舊版 HAL。從 Android 8.0 開始,Camera HAL 實作必須使用 HIDL API;系統不支援使用舊版介面。

輸入驗證

由於 HAL 可存取的資源與攝影機服務不同,因此兩者之間的界線會視為安全界線。也就是說,從相機服務傳遞的參數會被視為不受信任且未經過清理。為避免安全漏洞導致攻擊者提升權限或存取不應存取的資料,相機 HAL 必須驗證從相機服務傳遞至 HAL 的參數。包括檢查緩衝區長度值是否在允許範圍內,以及在使用參數前和將參數傳遞至硬體或核心驅動程式前,對參數進行清理。

舊版 HAL 元件

本節說明舊版 HAL 元件的架構,以及如何實作 HAL。Android 8.0 以上版本的 Camera HAL 實作項目必須改用上述 HIDL API。

架構 (舊版)

下圖和清單說明舊版攝影機 HAL 元件。

Android 相機架構

圖 2. 舊版攝影機架構

應用程式架構
在應用程式架構層級,應用程式的程式碼會使用 android.hardware.Camera API 與相機硬體互動。在內部,這段程式碼會呼叫對應的 JNI 黏著類別,存取與攝影機互動的原生程式碼。
JNI
android.hardware.Camera 相關聯的 JNI 程式碼位於 frameworks/base/core/jni/android_hardware_Camera.cpp。這段程式碼會呼叫較低層級的原生程式碼,取得實體攝影機的存取權,並傳回用於在架構層級建立 android.hardware.Camera 物件的資料。
原生架構
frameworks/av/camera/Camera.cpp 中定義的原生架構提供原生類別,相當於 android.hardware.Camera 類別。這個類別會呼叫 IPC 繫結器 Proxy,以取得攝影機服務的存取權。
繫結 IPC Proxy
IPC 繫結器 Proxy 可促進跨程序界線的通訊。 有三個攝影機繫結器類別位於 frameworks/av/camera 目錄中,會呼叫攝影機服務。ICameraService 是相機服務的介面,ICamera 是特定開啟相機裝置的介面,而 ICameraClient 則是裝置返回應用程式架構的介面。
攝影機服務
位於 frameworks/av/services/camera/libcameraservice/CameraService.cpp 的攝影機服務,是與 HAL 互動的實際程式碼。
HAL
硬體抽象層定義相機服務呼叫的標準介面,您必須實作這個介面,相機硬體才能正常運作。
核心驅動程式
攝影機的驅動程式會與實際攝影機硬體和 HAL 實作項目互動。相機和驅動程式必須支援 YV12 和 NV21 影像格式,才能在螢幕上預覽相機影像和錄製影片。

實作 HAL (舊版)

HAL 位於相機驅動程式和較高層級的 Android 架構之間,並定義您必須實作的介面,應用程式才能正確操作相機硬體。HAL 介面定義於 hardware/libhardware/include/hardware/camera.hhardware/libhardware/include/hardware/camera_common.h 標頭檔案中。

camera_common.h 定義 camera_module,這是一種標準結構,可取得相機的一般資訊,例如相機 ID 和所有相機通用的屬性 (也就是前置或後置鏡頭)。

camera.h 包含對應至 android.hardware.Camera 的程式碼。這個標頭檔案會宣告 camera_device 結構體,其中又包含 camera_device_ops 結構體,以及指向實作 HAL 介面的函式指標。如要參閱開發人員可設定的攝影機參數說明文件,請前往 frameworks/av/include/camera/CameraParameters.h。這些參數會透過 HAL 中 int (*set_parameters)(struct camera_device *, const char *parms) 指向的函式設定。

如需 HAL 實作範例,請參閱 hardware/ti/omap4xxx/camera 中的 Galaxy Nexus HAL 實作。

設定共用程式庫

設定 Android 建構系統,將 HAL 實作項目正確封裝至共用程式庫,並建立 Android.mk 檔案,將其複製到適當位置:

  1. 建立 device/<company_name>/<device_name>/camera 目錄,存放程式庫的來源檔案。
  2. 建立 Android.mk 檔案來建構共用程式庫。確認 makefile 包含下列幾行:
    LOCAL_MODULE := camera.<device_name>
    LOCAL_MODULE_RELATIVE_PATH := hw
    

    程式庫必須命名為 camera.<device_name> (系統會自動附加 .so),Android 才能正確載入程式庫。如需範例,請參閱 hardware/ti/omap4xxx/Android.mk 中的 Galaxy Nexus 相機 Makefile。

  3. 在裝置的 Makefile 中,將 frameworks/native/data/etc 目錄中必要的 XML 檔案複製到裝置的 Makefile,即可指定裝置具備相機功能。舉例來說,如要指定裝置有相機閃光燈且可自動對焦,請在裝置的 <device>/<company_name>/<device_name>/device.mk makefile 中加入下列程式碼:
    PRODUCT_COPY_FILES := \ ...
    
    PRODUCT_COPY_FILES += \
    frameworks/native/data/etc/android.hardware.camera.flash-autofocus.xml:system/etc/permissions/android.hardware.camera.flash-autofocus.xml \
    

    如需裝置 Makefile 的範例,請參閱 device/samsung/tuna/device.mk

  4. device/<company_name>/<device_name>/media_profiles.xmldevice/<company_name>/<device_name>/media_codecs.xml XML 檔案中,宣告攝影機的媒體轉碼器、格式和解析度功能。詳情請參閱「向架構公開轉碼器」。
  5. 在裝置的 device/<company_name>/<device_name>/device.mk makefile 中新增下列幾行,將 media_profiles.xmlmedia_codecs.xml 檔案複製到適當位置:
    # media config xml file
    PRODUCT_COPY_FILES += \
        <device>/<company>/<device>/media_profiles.xml:system/etc/media_profiles.xml
    
    # media codec config xml file
    PRODUCT_COPY_FILES += \
        <device>/<company>/<device>/media_codecs.xml:system/etc/media_codecs.xml
    
  6. 如要在裝置的系統映像檔中加入「相機」應用程式,請在裝置的 PRODUCT_PACKAGES變數中指定該應用程式 device/<company>/<device>/device.mk makefile:
    PRODUCT_PACKAGES := \
    Gallery2 \
    ...