Android のカメラ ハードウェア抽象化レイヤ(HAL)は、Camera 2 の高レベルのカメラ フレームワーク API を、基盤となるカメラのドライバとハードウェアに接続します。カメラのサブシステムには、カメラ パイプライン内のコンポーネントの実装が含まれています。一方、カメラ用 HAL は、これらのコンポーネントの各バージョンの実装に使用するインターフェースを備えています。
アーキテクチャ
次の図とリストでは、HAL コンポーネントについて説明しています。
- アプリのフレームワーク
- アプリ フレームワーク レベルには、Camera 2 API を利用してカメラ ハードウェアと通信するアプリコードがあります。このコードは、対応する Binder インターフェースを内部で呼び出して、カメラと通信するネイティブ コードにアクセスします。
- AIDL
CameraService
に関連付けられた Binder インターフェースは frameworks/av/camera/aidl/android/hardware にあります。生成されたコードは下位レベルのネイティブ コードを呼び出すことで物理カメラへのアクセス権を取得して、CameraDevice
を生成し、最終的にフレームワーク レベルでのCameraCaptureSession
オブジェクトを生成するために使用するデータを返します。- ネイティブ フレームワーク
frameworks/av/
に存在するこのフレームワークには、CameraDevice
クラスとCameraCaptureSession
クラスに相当するネイティブ クラスが用意されています。NDK camera2 のリファレンスもご覧ください。- binder IPC インターフェース
- binder IPC インターフェースは、プロセスの境界を越えた通信を容易にします。
frameworks/av/camera/camera/aidl/android/hardware
ディレクトリには、カメラサービスへの呼び出しを行う複数の camera binder クラスがあります。ICameraService
はカメラサービスへのインターフェースです。ICameraDeviceUser
はオープンになっている特定のカメラデバイスへのインターフェースです。ICameraServiceListener
とICameraDeviceCallbacks
はそれぞれ、アプリケーションフレームワークへのCameraService
コールバックとCameraDevice
コールバックです。 - カメラサービス
frameworks/av/services/camera/libcameraservice/CameraService.cpp
に配置されているカメラサービスは、HAL と通信する実際のコードです。- HAL
- ハードウェア抽象化レイヤは、カメラサービスの呼び出し先となり、カメラ ハードウェアを正しく機能させるために実装する必要がある標準インターフェースを定義します。
HAL の実装
HAL は、カメラドライバと上位レベルの Android フレームワークの間にあり、アプリがカメラ ハードウェアを正しく操作できるようにするために実装する必要があるインターフェースを定義します。Camera 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 はカメラサービスとは異なるリソースにアクセスできるため、この 2 つの境界はセキュリティ境界として扱われます。つまり、カメラサービスから渡されたパラメータは信頼できない、サニタイズされていないものであると判断されます。攻撃者が権限を昇格させる、またはアクセスすることを想定されていないデータにアクセスするセキュリティ上の脆弱性を回避するため、カメラ HAL でカメラサービスから HAL に渡されたパラメータを検証する必要があります。これには、バッファ長の値が許容範囲内にあることを確認し、使用前およびハードウェアまたはカーネルのドライバに渡す前にパラメータをサニタイズすることが含まれます。
レガシー HAL コンポーネント
このセクションでは、レガシー HAL コンポーネントのアーキテクチャと HAL の実装方法について説明します。Android 8.0 以降での Camera HAL の実装には、代わりに上記の HIDL API を使用する必要があります。
アーキテクチャ(レガシー)
次の図とリストでは、レガシー Camera HAL コンポーネントについて説明しています。
- アプリのフレームワーク
- アプリ フレームワーク レベルには、
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 バインダ プロキシを呼び出すことで、カメラサービスへのアクセス権を取得します。- バインダ IPC プロキシ
- IPC バインダ プロキシは、プロセスの境界を越えた通信を容易にします。カメラサービスを呼び出す
frameworks/av/camera
ディレクトリには、3 つのカメラバインダ クラスがあります。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
構造体を宣言し、この構造体は HAL インターフェースを実装する関数へのポインタを持つ camera_device_ops
構造体を含みます。デベロッパーが設定できるカメラ パラメータに関するドキュメントについては、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 ビルドシステムを設定し、Android.mk
ファイルの作成によって HAL 実装を共有ライブラリに正しくパッケージ化して、適切な場所にその共有ライブラリをコピーします。
- ライブラリのソースファイルを格納する
device/<company_name>/<device_name>/camera
ディレクトリを作成します。 Android.mk
ファイルを作成して、共有ライブラリをビルドします。makefile に次の行が含まれていることを確認します。LOCAL_MODULE := camera.<device_name> LOCAL_MODULE_RELATIVE_PATH := hw
Android でライブラリを正しくロードできるように、ライブラリの名前は
camera.<device_name>
とします(.so
は自動的に付加されます)。例については、hardware/ti/omap4xxx/Android.mk
にある Galaxy Nexus カメラの makefile を参照してください。- デバイスにカメラ機能があることを指定するには、デバイスの makefile を使用して必要となる機能 XML ファイルを
frameworks/native/data/etc
ディレクトリにコピーします。たとえば、デバイスにカメラ フラッシュと自動フォーカス機能があることを指定するには、デバイスの<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
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
makefile のPRODUCT_PACKAGES
変数でカメラアプリを指定して、デバイスのシステム イメージにカメラアプリを含めます。PRODUCT_PACKAGES := \ Gallery2 \ ...