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

圖 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
分別是應用程式架構的CameraService
和CameraDevice
回呼。 - 攝影機服務
- 位於
frameworks/av/services/camera/libcameraservice/CameraService.cpp
的攝影機服務,是與 HAL 互動的實際程式碼。 - HAL
- 硬體抽象層定義相機服務呼叫的標準介面,您必須實作這個介面,相機硬體才能正常運作。
實作 HAL
HAL 位於相機驅動程式和較高層級的 Android 架構之間,並定義您必須實作的介面,應用程式才能正確操作相機硬體。相機 HAL 的 HIDL 介面定義於 hardware/interfaces/camera。
典型的繫結 HAL 必須實作下列 HIDL 介面:
-
ICameraProvider
: 用於列舉個別裝置及管理裝置狀態。 -
ICameraDevice
: 攝影機裝置介面。 -
ICameraDeviceSession
: 作用中的攝影機裝置工作階段介面。
參考 HIDL 實作適用於 CameraProvider.cpp
、
CameraDevice.cpp
和 CameraDeviceSession.cpp
。實作會包裝仍使用舊版 API 的舊版 HAL。從 Android 8.0 開始,Camera HAL 實作必須使用 HIDL API;系統不支援使用舊版介面。
輸入驗證
由於 HAL 可存取的資源與攝影機服務不同,因此兩者之間的界線會視為安全界線。也就是說,從相機服務傳遞的參數會被視為不受信任且未經過清理。為避免安全漏洞導致攻擊者提升權限或存取不應存取的資料,相機 HAL 必須驗證從相機服務傳遞至 HAL 的參數。包括檢查緩衝區長度值是否在允許範圍內,以及在使用參數前和將參數傳遞至硬體或核心驅動程式前,對參數進行清理。
舊版 HAL 元件
本節說明舊版 HAL 元件的架構,以及如何實作 HAL。Android 8.0 以上版本的 Camera HAL 實作項目必須改用上述 HIDL API。
架構 (舊版)
下圖和清單說明舊版攝影機 HAL 元件。

圖 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.h
和 hardware/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
檔案,將其複製到適當位置:
- 建立
device/<company_name>/<device_name>/camera
目錄,存放程式庫的來源檔案。 - 建立
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。 - 在裝置的 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
。 - 在
device/<company_name>/<device_name>/media_profiles.xml
和device/<company_name>/<device_name>/media_codecs.xml
XML 檔案中,宣告攝影機的媒體轉碼器、格式和解析度功能。詳情請參閱「向架構公開轉碼器」。 - 在裝置的
device/<company_name>/<device_name>/device.mk
makefile 中新增下列幾行,將media_profiles.xml
和media_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
- 如要在裝置的系統映像檔中加入「相機」應用程式,請在裝置的
PRODUCT_PACKAGES
變數中指定該應用程式device/<company>/<device>/device.mk
makefile:PRODUCT_PACKAGES := \ Gallery2 \ ...