カメラ

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 インターフェース
binder IPC インターフェースは、プロセスの境界を越えた通信を容易にします。frameworks/av/camera/camera/aidl/android/hardware ディレクトリには、カメラサービスへの呼び出しを行う複数の camera binder クラスがあります。ICameraService はカメラサービスへのインターフェースです。ICameraDeviceUser はオープンになっている特定のカメラデバイスへのインターフェースです。ICameraServiceListenerICameraDeviceCallbacks はそれぞれ、アプリケーションフレームワークへの 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.cppCameraDevice.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 カメラのアーキテクチャ

図 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 バインダ プロキシを呼び出すことで、カメラサービスへのアクセス権を取得します。
バインダ 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.hcamera_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 実装を共有ライブラリに正しくパッケージ化して、適切な場所にその共有ライブラリをコピーします。

  1. ライブラリのソースファイルを格納する device/<company_name>/<device_name>/camera ディレクトリを作成します。
  2. 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 を参照してください。

  3. デバイスにカメラ機能があることを指定するには、デバイスの 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 を参照してください。

  4. カメラのメディア コーデック、フォーマット、解像度を device/<company_name>/<device_name>/media_profiles.xml XML ファイルと device/<company_name>/<device_name>/media_codecs.xml XML ファイルで宣言します。詳細については、フレームワークにコーデックを公開するをご覧ください。
  5. デバイスの 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
    
  6. デバイスの device/<company>/<device>/device.mk makefile の PRODUCT_PACKAGES 変数でカメラアプリを指定して、デバイスのシステム イメージにカメラアプリを含めます。
    PRODUCT_PACKAGES := \
    Gallery2 \
    ...