カメラ

Android Camera HAL アイコン

Android のカメラ ハードウェア抽象化レイヤ(HAL)は、Camera 2 の高レベルのカメラ フレームワーク API を、カメラの基礎となるドライバとハードウェアに接続します。カメラ サブシステムはカメラ パイプライン コンポーネントの実装を含み、一方 Camera 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 コンポーネント

このセクションでは、レガシー 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 \
        ...