相機

Android Camera HAL 圖示

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

建築

下圖和清單說明 HAL 元件。

Android 相機架構

圖 1. 相機架構

應用程式架構
應用程式架構層級是應用程式程式碼,會使用 Camera 2 API 與相機硬體互動。在內部,此程式碼會呼叫相應的 Binder 介面,以存取與相機互動的原生程式碼。
AIDL
CameraService 相關聯的 Binder 介面可在 frameworks/av/camera/aidl/android/hardware 中找到。產生的程式碼會呼叫較低層級的原生程式碼,取得對實體相機的存取權,並傳回用於在架構層級建立 CameraDevice 和最終 CameraCaptureSession 物件的資料。
原生架構
這個位於 frameworks/av/ 中的架構提供與 CameraDevice CameraCaptureSession 類別等同的原生類別。另請參閱 NDK camera2 參考資料
binder IPC 介面
IPC 繫結器介面可協助處理序邊界進行通訊。frameworks/av/camera/camera/aidl/android/hardware 目錄中有多個攝影機 Binder 類別,可呼叫攝影機服務。 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 起,相機 HAL 實作必須使用 HIDL API;系統不支援使用舊版介面。

輸入驗證

由於 HAL 可存取的資源與相機服務不同,因此兩者之間的界線會視為安全界線。這表示從相機服務傳遞的參數會視為不受信任且未經清理。為避免安全漏洞讓攻擊者提升權限或存取不應存取的資料,相機 HAL 必須驗證從相機服務傳遞至 HAL 的參數。這包括檢查緩衝區長度值是否在可接受的範圍內,並在使用和傳遞至硬體或核心驅動程式之前,先清理參數。

舊版 HAL 元件

本節將說明舊版 HAL 元件的架構,以及如何實作 HAL。在 Android 8.0 以上版本中,相機 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 繫結器代理程式,以取得相機服務的存取權。
Binder IPC Proxy
IPC 繫結器代理程式可協助處理序間通訊。有三個相機 Binder 類別位於 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 檔案,即可指定裝置具有相機功能。舉例來說,如要指定裝置具有相機閃光燈並可自動對焦,請在裝置的 <device>/<company_name>/<device_name>/device.mk 製作檔中新增下列行:
    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. 如要在裝置的系統映像檔中加入相機應用程式,請在裝置的 device/<company>/<device>/device.mk 製作檔中,使用 PRODUCT_PACKAGES 變數指定相機應用程式:
    PRODUCT_PACKAGES := \
    Gallery2 \
    ...