![Android Camera HAL 圖示](https://source.android.google.cn/static/docs/core/camera/images/ape_fwk_hal_camera.png?authuser=2&hl=zh-tw)
Android 的相機硬體抽象層 (HAL) 會將 Camera 2 中較高層級的相機架構 API 連結至基礎相機驅動程式和硬體。相機子系統包含相機管道元件的實作項目,而相機 HAL 則提供介面,可用於實作這些元件的版本。
建築
下圖和清單說明 HAL 元件。
![Android 相機架構](https://source.android.google.cn/static/docs/core/camera/images/ape_fwk_camera2.png?authuser=2&hl=zh-tw)
圖 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
則分別是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 起,相機 HAL 實作必須使用 HIDL API;系統不支援使用舊版介面。
輸入驗證
由於 HAL 可存取的資源與相機服務不同,因此兩者之間的界線會視為安全界線。這表示從相機服務傳遞的參數會視為不受信任且未經清理。為避免安全漏洞讓攻擊者提升權限或存取不應存取的資料,相機 HAL 必須驗證從相機服務傳遞至 HAL 的參數。這包括檢查緩衝區長度值是否在可接受的範圍內,並在使用和傳遞至硬體或核心驅動程式之前,先清理參數。
舊版 HAL 元件
本節將說明舊版 HAL 元件的架構,以及如何實作 HAL。在 Android 8.0 以上版本中,相機 HAL 實作必須改用上述的 HIDL API。
架構 (舊版)
下圖和清單說明舊版攝影機 HAL 元件。
![Android 相機架構](https://source.android.google.cn/static/docs/core/camera/images/ape_fwk_camera.png?authuser=2&hl=zh-tw)
圖 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.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 檔案,即可指定裝置具有相機功能。舉例來說,如要指定裝置具有相機閃光燈並可自動對焦,請在裝置的<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
。 - 在
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
- 如要在裝置的系統映像檔中加入相機應用程式,請在裝置的
device/<company>/<device>/device.mk
製作檔中,使用PRODUCT_PACKAGES
變數指定相機應用程式:PRODUCT_PACKAGES := \ Gallery2 \ ...