センサー Multi-HAL

センサー Multi-HAL は、センサー HAL と他のセンサー HAL の併用を可能にするフレームワークです。センサー Multi-HAL は、動的ライブラリとして保存されたセンサーサブ HAL をベンダー パーティションに動的に読み込んで、イベントのポストと wake lock の取得および解放を処理できるコールバック オブジェクトを提供します。センサーサブ HAL は、ベンダー パーティションの共有オブジェクトに組み込まれ、マルチ HAL フレームワークで使用されるセンサー HAL です。これらのサブ HAL は、相互にまたはプロセスのメイン関数を含むマルチ HAL コードに依存しません。

Android 11 以降を搭載するデバイスで利用可能なセンサー Multi-HAL 2.1 は、センサー Multi-HAL 2.0 の後継です。この HAL は、ヒンジ角度センサーのタイプを公開できるサブ HAL の読み込みをサポートしています。このセンサータイプをサポートするには、サブ HAL で 2.1 SubHal ヘッダーで定義されているサブ HAL API を使用する必要があります。

センサー AIDL HAL を使用する Android 13 以降を搭載したデバイスでは、Multi-HAL shim レイヤを使用して Multi-HAL 機能を有効にできます。実装の詳細については、センサー AIDL HAL でのセンサー Multi-HAL の使用をご覧ください。

センサー Multi-HAL 2 とセンサー HAL 2 の相違点

センサー Multi-HAL 2(Android 10 以降を搭載しているデバイスで利用可能)では、センサー HAL 2 の上に複数の抽象化が導入され、HAL API を簡単に操作できるようになりました。センサー Multi-HAL 2 には、HalProxy クラスが導入されており、センサー HAL 2 インターフェースと V2_1/SubHal(または V2_0/SubHal)インターフェースの実装を処理し、HalProxy がサブ HAL を操作できるようにします。

ISensorsSubHal インターフェースは、2.1/ISensors.hal(または 2.0/ISensors.hal)インターフェースとは次の点で異なります。

  • 初期化メソッドは、2 つの FMQ と ISensorsCallback ではなく IHalProxyCallback クラスを渡します。
  • サブ HAL は、バグレポートにデバッグ情報を表示するデバッグ関数を実装する必要があります。
  • 読み込まれたサブ HAL を他のサブ HAL と区別できるように、サブ HAL は名前関数を実装する必要があります。

センサー Multi-HAL 2 とセンサー HAL 2 の主な相違点は、初期化関数にあります。IHalProxyCallback インターフェースには、FMQ の代わりに、センサー イベントをセンサー フレームワークにポストするメソッドと、wake lock を作成するメソッドの 2 つのメソッドが用意されています。センサー Multi-HAL は内部で FMQ とのすべてのインタラクションを管理し、すべてのサブ HAL のセンサー イベントをタイムリーに配信できるようにします。サブ HAL で createScopedWakelock メソッドを使用して wake lock をタイムアウトする際の負荷をセンサー Multi-HAL に委任し、センサー Multi-HAL 全体で wake lock の使用を 1 つの共通の wake lock に一元化することが強く推奨されます。これにより、ロックとロック解除の呼び出しが最小限に抑えられます。

センサー Multi-HAL 2 には、いくつかの安全機能も内蔵されています。こうした機能により、センサー FMQ に空きがなくなった状況や、Android センサー フレームワークが再起動されてセンサーの状態をリセットする必要がある状況に対処します。さらに、イベントが HalProxy クラスにポストされても、センサー フレームワークで直ちにイベントを受け入れることができない場合、センサー Multi-HAL はイベントをバックグラウンド スレッドに移動して、イベントがポストされるのを待機しながら、すべてのサブ HAL で処理を続行できます。

ソースコードとリファレンス実装

すべてのセンサー Multi-HAL コードは hardware/interfaces/sensors/common/default/2.X/multihal/ で入手できます。以下のリソースをご覧ください。

  • HalProxy.h: HalProxy オブジェクトはセンサー Multi-HAL によってインスタンス化され、サブ HAL からセンサー フレームワークにデータを渡す作業を処理します。
  • HalProxy.cpp: HalProxy の実装には、サブ HAL とセンサー フレームワーク間の通信を多重化する際に必要なすべてのロジックが含まれています。
  • SubHal.h: ISensorsSubHal インターフェースは、HalProxy との互換性を持つサブ HAL に必要なインターフェースを定義します。サブ HAL は初期化メソッドを実装して、postEventscreateScopedWakelock に対して HalProxyCallback オブジェクトを使用できるようにします。

    Multi-HAL 2.0 の実装では、SubHal.h のバージョン 2.0 を使用します。

  • hardware/interfaces/sensors/common/default/2.X/multihal/tests/: これらの単体テストでは、HalProxy の実装を検証します。

  • hardware/interfaces/sensors/common/default/2.X/multihal/tests/fake_subhal/: このサンプルのサブ HAL の実装では、疑似センサーを使用して偽のデータを生成します。デバイス上で複数のサブ HAL がどのように動作するかをテストする場合に有用です。

実装

このセクションでは、次の状況でセンサー Multi-HAL を実装する方法について説明します。

センサー AIDL HAL でセンサー Multi-HAL を使用する

センサー AIDL HAL で Multi-HAL 機能を有効にするには、hardware/interfaces/sensors/aidl/default/multihal/ にある、AIDL Multi-HAL shim レイヤ モジュールをインポートします。このモジュールは、AIDL センサーと HIDL センサーの HAL 定義タイプ間の変換を処理し、センサー Multi-HAL 2.1 の実装で説明されているマルチ HAL インターフェースのラッパーを定義しています。AIDL マルチ HAL shim レイヤは、センサー Multi-HAL 2.1 を実装しているデバイスと互換性があります。

AIDL マルチ HAL shim レイヤでは、センサー AIDL HAL でセンサータイプとしてヘッド トラッカーと軸制限付き IMU を公開できます。AIDL HAL インターフェースで定義されたこれらのセンサータイプを使用するには、getSensorsList_2_1() 実装の SensorInfo 構造体の type フィールドを設定します。AIDL センサーと HIDL センサーの HAL の整数を使用しているセンサータイプ フィールドは重複していないため、このようにしても安全です。

センサー Multi-HAL 2.1 を実装する

センサー Multi-HAL 2.1 を新しいデバイスに実装する手順は次のとおりです。

  1. SubHal.h で説明したように、ISensorsSubHal インターフェースを実装します。
  2. SubHal.hsensorsHalGetSubHal_2_1 メソッドを実装します。
  3. 新しく実装されたサブ HAL をビルドするため、cc_library_shared ターゲットを追加します。ターゲットを追加する場合は次の作業を行います。

    1. ターゲットがデバイスのベンダー パーティションのどこかにプッシュされていることを確認します。
    2. /vendor/etc/sensors/hals.conf にある構成ファイルで、新しい行にライブラリへのパスを追加します。必要に応じて、hals.conf ファイルを作成します。

    サブ HAL ライブラリをビルドするための Android.bp エントリの例については、hardware/interfaces/sensors/common/default/2.X/multihal/tests/Android.bp をご覧ください。

  4. manifest.xml ファイルから android.hardware.sensors エントリをすべて削除します。このファイルには、デバイスでサポートされている HAL のリストが含まれています。

  5. device.mk ファイルから android.hardware.sensors サービスと service.rc ファイルをすべて削除し、android.hardware.sensors@2.1-service.multihalandroid.hardware.sensors@2.1-service.multihal.rcPRODUCT_PACKAGES に追加します。

起動時に HalProxy が開始され、新しく実装されたサブ HAL を探して、sensorsHalGetSubHal_2_1 を呼び出すことによって初期化します。

センサー Multi-HAL 2.0 から Multi-HAL 2.1 に移植する

Multi-HAL 2.0 から Multi-HAL 2.1 に移植するには、SubHal インターフェースを実装し、サブ HAL を再コンパイルします。

2.0 と 2.1 の SubHal インターフェースの違いは次のとおりです。

  • IHalProxyCallback は、ISensors.hal 仕様のバージョン 2.1 で作成されたタイプを使用します。
  • initialize() 関数は、2.0 SubHal インターフェースのコードではなく、新しい IHalProxyCallback を渡します。
  • これらのメソッドは、ISensors.hal 仕様のバージョン 2.1 で追加された新しいタイプを使用することから、サブ HAL では、getSensorsListinjectSensorData ではなく、getSensorsList_2_1injectSensorData_2_1 を実装する必要があります。
  • サブ HAL は、マルチ HAL でバージョン 2.1 サブ HAL として扱われるために、sensorsHalGetSubHal ではなく sensorsHalGetSubHal_2_1 を公開する必要があります。

センサー HAL 2.0 から移植する

センサー HAL 2.0 からセンサー Multi-HAL 2.0 にアップグレードする場合は、HAL 実装が次の要件を満たしていることを確認してください。

HAL を初期化する

センサー HAL 2.0 には、センサー サービスが FMQ と動的センサー コールバックを渡すことのできる初期化関数が用意されています。センサー Multi-HAL 2.0 では、initialize() 関数が 1 つのコールバックを渡します。このコールバックは、センサー イベントのポスト、wake lock の取得、動的センサー接続と接続解除の通知に使用する必要があります。

Multi-HAL 実装にセンサー イベントをポストする

センサー イベントが利用可能な場合、サブ HAL は FMQ を介してセンサー イベントをポストする代わりに IHalProxyCallback にセンサー イベントを書き込む必要があります。

WAKE_UP イベント

センサー HAL 2.0 では、HAL で実装の wake lock を管理できます。センサー Multi-HAL 2.0 では、サブ HAL は Multi-HAL 実装による wake lock の管理を可能にするとともに、createScopedWakelock を呼び出すことで wake lock を取得するようリクエストできます。Multi-HAL 実装にウェイクアップ イベントをポストする場合は、ロックされた範囲の wake lock を取得して postEvents に渡す必要があります。

動的センサー

センサー Multi-HAL 2.0 では、動的センサー接続が変更されるたびに、IHalProxyCallbackonDynamicSensorsConnectedonDynamicSensorsDisconnected を呼び出す必要があります。これらのコールバックは、initialize() 関数によって提供される IHalProxyCallback ポインタの一部として使用できます。

センサー HAL 1.0 から移植する

センサー HAL 1.0 からセンサー Multi-HAL 2.0 にアップグレードする場合は、HAL 実装が次の要件を満たしていることを確認してください。

HAL を初期化する

サブ HAL と Multi-HAL 実装の間でコールバックを確立するには、initialize() 関数がサポートされている必要があります。

使用可能なセンサーを公開する

センサー Multi-HAL 2.0 で getSensorsList() 関数は、単一デバイスの起動中(センサー HAL の再起動後も)同じ値を返す必要があります。これにより、システム サーバーが再起動されると、フレームワークはセンサー接続の再確立を試行できます。getSensorsList() が返す値は、デバイスの再起動後に変更される可能性があります。

Multi-HAL 実装にセンサー イベントをポストする

センサー HAL 2.0 では、poll() が呼び出されるのを待つのではなく、センサー イベントが発生するたびに、サブ HAL がセンサー イベントを IHalProxyCallback に前もって書き込む必要があります。

WAKE_UP イベント

センサー HAL 1.0 では、HAL で実装の wake lock を管理できます。センサー Multi-HAL 2.0 では、サブ HAL は Multi-HAL 実装による wake lock の管理を可能にするとともに、createScopedWakelock を呼び出すことで wake lock を取得するようリクエストできます。Multi-HAL 実装にウェイクアップ イベントをポストする場合は、ロックされた範囲の wake lock を取得して postEvents に渡す必要があります。

動的センサー

センサー HAL 1.0 では、動的センサーは poll() 関数を介して返されます。センサー Multi-HAL 2.0 では、動的センサー接続が変更されるたびに、IHalProxyCallbackonDynamicSensorsConnectedonDynamicSensorsDisconnected を呼び出す必要があります。これらのコールバックは、initialize() 関数によって提供される IHalProxyCallback ポインタの一部として使用できます。

センサー Multi-HAL 1.0 から移植する

センサー Multi-HAL 1.0 から既存の実装を移植する手順は次のとおりです。

  1. センサー HAL 構成が /vendor/etc/sensors/hals.conf. に配置されていることを確認します。これには、/system/etc/sensors/hals.conf にあるファイルの移動が必要になる場合があります。
  2. hardware/hardware.hhardware/sensors.h への参照は HAL 2.0 でサポートされていないため削除します。
  3. センサー HAL 1.0 からの移植の説明に従ってサブ HAL を移植します。
  4. センサー Mutli-HAL 2.0 の実装セクションの手順 3 と 4 に従って、指定された HAL としてセンサー Multi-HAL 2.0 を設定します。

検証

VTS を実行する

のサブ HAL をセンサー Multi-HAL 2.1 に統合したら、ベンダー テストスイート(VTS)を使用して、センサー HAL インターフェースによって設定された要件をサブ HAL 実装がすべて満たしていることを確認します。

ホストマシン上で VTS がセットアップされている場合にセンサー VTS テストのみを実行するには、次のコマンドを実行します。

vts-tradefed run commandAndExit vts \
    --skip-all-system-status-check \
    --primary-abi-only \
    --skip-preconditions \
    --module VtsHalSensorsV2_0Target && \
  vts-tradefed run commandAndExit vts \
    --skip-all-system-status-check \
    --primary-abi-only \
    --skip-preconditions \
    --module VtsHalSensorsV2_1Target

AIDL Multi-HAL shim レイヤを実行している場合は、VtsAidlHalSensorsTargetTest を実行します。

vts-tradefed run commandAndExit vts \
    --skip-all-system-status-check \
    --primary-abi-only \
    --skip-preconditions \
    --module VtsAidlHalSensorsTargetTest

単体テストを実行する

HalProxy_test.cpp の単体テストでは、単体テストでインスタンス化され、動的に読み込まれていない疑似サブ HAL を使用して HalProxy をテストします。新しいサブ HAL を作成する際は、新しいサブ HAL が適切に実装されていることを検証する単体テストの追加方法に関するガイドとして、これらのテストが機能する必要があります。

テストを実施するには、次のコマンドを実行します。

cd $ANDROID_BUILD_TOP/hardware/interfaces/sensors/common/default/2.X/multihal/tests
atest

疑似サブ HAL を使用してテストする

疑似サブ HAL は、ISensorsSubHal インターフェースのダミー実装です。サブ HAL は、さまざまなセンサーリストを公開します。センサーが有効になると、特定のセンサー リクエストで指定された間隔に基づいて、自動的に生成されたセンサー イベントを HalProxy に定期的にポストします。

疑似サブ HAL を使用すると、システムに読み込まれた他のサブ HAL と、完全なマルチ HAL コードがどのように連携して動作するかをテストでき、センサー Multi-HAL のコードのさまざまな側面を明確にできます。

hardware/interfaces/sensors/common/default/2.X/multihal/tests/fake_subhal/ で 2 つの疑似サブ HAL を利用できます。

疑似サブ HAL をビルドして、デバイスに push する手順は次のとおりです。

  1. 次のコマンドを実行して、3 つの異なる疑似サブ HAL をビルドしてデバイスに push します。

    $ANDROID_BUILD_TOP/hardware/interfaces/sensors/common/default/2.X/multihal/tests/
    mma
    adb push \
      $ANDROID_BUILD_TOP/out/target/product/<device>/symbols/vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config1.so \
      /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config1.so
    adb push \
      $ANDROID_BUILD_TOP/out/target/product/<device>/symbols/vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config2.so \
      /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config2.so
    adb push \
      $ANDROID_BUILD_TOP/out/target/product/<device>/symbols/vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config3.so \
      /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config3.so
    
  2. 疑似サブ HAL のパスを指定して、/vendor/etc/sensors/hals.conf のセンサー HAL 構成を更新します。

    /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config1.so
    /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config2.so
    /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config3.so
    
  3. HalProxy を再起動して、構成にリストされている新しいサブ HAL を読み込みます。

    adb shell stop
    adb shell start
    

デバッグ

デベロッパーは lshal コマンドを使用してフレームワークをデバッグできます。センサー HAL のデバッグ出力をリクエストするには、次のコマンドを実行します。

adb root
adb shell lshal debug android.hardware.sensors@2.1::ISensors/default

HalProxy の現在の状態に関する情報とサブ HAL は、ターミナルに出力されます。HalProxy オブジェクトと疑似サブ HAL のコマンド出力の例を以下に示します。

Internal values:
  Threads are running: true
  Wakelock timeout start time: 200 ms ago
  Wakelock timeout reset time: 73208 ms ago
  Wakelock ref count: 0
  # of events on pending write queue: 0
  # of non-dynamic sensors across all subhals: 8
  # of dynamic sensors across all subhals: 0
SubHals (2):
  Name: FakeSubHal-OnChange
  Debug dump:
Available sensors:
Name: Ambient Temp Sensor
Min delay: 40000
Flags: 2
Name: Light Sensor
Min delay: 200000
Flags: 2
Name: Proximity Sensor
Min delay: 200000
Flags: 3
Name: Relative Humidity Sensor
Min delay: 40000
Flags: 2
  Name: FakeSubHal-OnChange
  Debug dump:
Available sensors:
Name: Ambient Temp Sensor
Min delay: 40000
Flags: 2
Name: Light Sensor
Min delay: 200000
Flags: 2
Name: Proximity Sensor
Min delay: 200000
Flags: 3
Name: Relative Humidity Sensor
Min delay: 40000
Flags: 2

# of events on pending write queue に対して指定した数値が大きい場合(1,000 以上)は、センサー フレームワークへの書き込みが保留状態になっているイベントが多数存在することを示しています。これは、センサー サービスでデッドロックやクラッシュが発生してセンサー イベントを処理していない、または最近多数のセンサー イベントがサブ HAL からポストされたことを意味します。

wake lock 参照の数が 0 より大きい場合は、HalProxy が wake lock を取得したことを意味します。これは、ScopedWakelock が意図的に保持されている場合、またはウェイクアップ イベントが HalProxy に送信され、センサー フレームワークによって処理されていない場合に限り、0 より大きくする必要があります。

HalProxy のデバッグ メソッドに渡されるファイル記述子は各サブ HAL に渡されるため、デベロッパーは ISensorsSubHal メソッドの一部としてデバッグ メソッドを実装する必要があります。