センサー ハードウェア抽象化レイヤ(HAL)は、Android センサー フレームワークとデバイスのセンサー(加速度計やジャイロスコープなど)との間のインターフェースです。このセンサー HAL では、Android センサー フレームワークがデバイスのセンサーを制御するために実装する必要のある関数が定義されます。
センサー AIDL HAL は、新しいデバイスとアップグレード済みのデバイスにインストールされた Android 13 以降に対応しています。センサー HAL 2.1 をベースとするこのセンサー AIDL HAL では AIDL HAL インターフェースが使用され、ヘッド トラッカーおよび軸制限のある IMU センサータイプを公開します。
AIDL HAL インターフェース
センサー AIDL HAL の詳細については、hardware/interfaces/sensors/aidl/android/hardware/sensors/ISensors.aidl にある HAL の定義に記載されているドキュメントをご覧ください。
センサー AIDL HAL を実装する
センサー AIDL HAL を実装するには、オブジェクトで ISensors
インターフェースを拡張し、hardware/interfaces/sensors/aidl/android/hardware/sensors/ISensors.aidl で定義されているすべての関数を実装する必要があります。
HAL を初期化する
センサー HAL を使用するには、Android センサー フレームワークで初期化する必要があります。このフレームワークが initialize()
関数を呼び出し、センサー HAL に 3 つのパラメータ(FMQ 記述子 2 つと ISensorsCallback
オブジェクトへのポインタ 1 つ)を渡します。
HAL は 1 つ目の記述子を使用して Event FMQ を作成します。これは、センサー イベントをフレームワークに書き込む際に使用されます。2 番目の記述子は HAL が wake lock FMQ を作成する際に使用されます。この wake lock FMQ は、WAKE_UP
センサー イベントの wake lock を解放する際、同期するために使用されます。コールバック関数を呼び出す必要があるときに備えて、HAL は ISensorsCallback
オブジェクトへのポインタも保存する必要があります。
センサー HAL を初期化する際は、必ず initialize()
関数を最初に呼び出す必要があります。
使用可能なセンサーをエクスポーズする
デバイスで使用可能なすべての静的センサーのリストを取得するには、getSensorsList()
関数を使用します。この関数により取得できるリストに記載されたセンサーは、それぞれのハンドルによって一意に識別されています。そのため、センサー HAL をホストするプロセスの再起動時に、いずれのセンサーのハンドルも変更しないようにしてください。デバイスの再起動時やシステム サーバーの再起動時には、ハンドルが変更されることがあります。
複数のセンサーが同じセンサータイプとウェイクアップ プロパティを共有している場合、リスト内で最初に記載されているセンサーがデフォルト センサーとなり、getDefaultSensor(int sensorType, bool wakeUp)
関数を使用するアプリに返されます。
センサーリストの安定性
センサー HAL の再起動後に、getSensorsList()
によって返されたデータが再起動前に取得したセンサーリストと比較して大幅な変化を示している場合は、フレームワークにより Android ランタイムの再起動がトリガーされます。センサーリストの大幅な変化には、特定のハンドルを持つセンサーが欠落しているケースや、属性が変更されたケース、新しいセンサーが導入されたケースなどが該当します。Android ランタイムの再起動はユーザーの混乱を招きますが、アプリの存続期間中に静的(動的でない)センサーを変更しないという Android API 契約を、Android フレームワークが遵守できなくなるため必要です。これによって、アプリによるアクティブなセンサー リクエストをフレームワークが再確立することも回避できます。したがって、HAL ベンダーには、センサーリストの変更をできる限り回避することをおすすめします。
センサー ハンドルを安定化するため、HAL はデバイス内の物理センサーをそのハンドルに対して確定的にマッピングする必要があります。センサー HAL インターフェースで特定の実装が必須となっているわけではありませんが、デベロッパーはこの要件を満たすためにいくつかのオプションを使用できます。
たとえば、センサーリストは、各センサーの固定属性(ベンダー、モデル、センサータイプなど)の組み合わせを使用して並べ替えることができます。もう一つのオプションは、デバイスの静的センサー セットはハードウェアに固定されているため、getSensorsList()
でセンサーリストを取得する前に、想定されるすべてのセンサーの初期化が完了するタイミングを HAL が把握する必要があるという事実を前提とするものです。想定されるセンサーのリストは、HAL バイナリにコンパイルする、またはファイル システム内の構成ファイルに保存することができ、表示される順番を利用してハンドルを安定化できます。最適なソリューションは個々の HAL の実装環境によって異なりますが、重要なのは、HAL の再起動後もセンサー ハンドルが変わらないという点です。
センサーを構成する
センサーを有効にする前に、batch()
関数を使用して、センサーのサンプリング期間と最大レポート レイテンシを構成する必要があります。
センサーは、センサーデータを失うことなく batch()
を使用していつでも再構成できる必要があります。
サンプリング期間
サンプリング期間は、構成するセンサータイプによって次のように異なります。
- 連続: センサー イベントは一定の頻度で継続して生成されます。
- 変化時: サンプリング期間よりも高速にイベントが生成されることはなく、測定値に変化がない場合はサンプリング期間よりも低速に生成される可能性があります。
- ワンショット: サンプリング期間は無視されます。
- 特殊: 詳細については、センサータイプをご覧ください。
サンプリング期間とセンサーのレポートモードとの相関性については、レポートモードをご覧ください。
最大レポート レイテンシ
最大レポート レイテンシではイベントの最大遅延時間(ナノ秒単位)を設定します。この遅延により、イベントをハードウェア FIFO に保存してから、SoC の起動中に HAL を介して Event FMQ に書き込むことができます。
値 0 は、測定が完了した直後にイベントを報告する必要があることを意味します。つまり、FIFO が完全にスキップされるか、センサーからのイベントが FIFO に出現するとすぐに FIFO がクリアされます。
たとえば、50 Hz で有効になった加速度計のレポート作成に関する最大レイテンシが 0 である場合は、SoC の起動中に毎秒 50 回の割り込みがトリガーされます。
最大レポート レイテンシが 0 より大きい場合、検出された直後にセンサー イベントを報告する必要はありません。最大レポート レイテンシを超えてイベントが遅延しない限り、イベントはハードウェア FIFO に一時的に保存され、一括で報告されます。前回のバッチ以降のすべてのイベントが記録され、一度に返されます。これにより、SoC に送信される割り込みの数が減少し、センサーがデータをキャプチャしてバッチ処理を実行している間に、SoC を低消費電力モードに切り替えることができます。
各イベントにはタイムスタンプが関連付けられています。イベントが報告される時間に遅延が発生しても、イベントのタイムスタンプには影響しません。タイムスタンプは正確であり、報告された時間ではなく、イベントが実際に発生した時間を示している必要があります。
最大レポート レイテンシが 0 以外のセンサー イベントの報告に関する詳細と要件については、バッチ処理をご覧ください。
センサーを有効にする
フレームワークは、activate()
関数を使用してセンサーを有効または無効にします。センサーを有効にする前に、フレームワークは batch()
を使用してセンサーを構成する必要があります。
センサーを無効にした場合は、そのセンサーからの追加のセンサー イベントを Event FMQ に書き込まないでください。
センサーをフラッシュする
センサーデータをバッチ処理するようにセンサーを構成すると、フレームワークは flush()
を呼び出してバッチ処理済みセンサー イベントの即時フラッシュを強制できます。これにより、指定されたセンサー ハンドルのバッチ処理済みセンサー イベントが直ちに Event FMQ に書き込まれます。センサー HAL は、flush()
呼び出しの結果として書き込まれるセンサー イベントの末尾に、フラッシュ完了イベントを追加する必要があります。
フラッシュは非同期に発生します(つまり、この関数はすぐに制御を返す必要があります)。実装で複数のセンサーに対して単一の FIFO を使用している場合、その FIFO はフラッシュされ、指定されたセンサーに対してのみフラッシュ完了イベントが追加されます。
指定されたセンサーに FIFO がない(バッファリング不可能)場合や、呼び出し時に FIFO が空であった場合でも、flush()
は成功し、そのセンサーのフラッシュ完了イベントを送信する必要があります。これは、ワンショット センサー以外のすべてのセンサーに当てはまります。
ワンショット センサーに対して flush()
が呼び出された場合、flush()
は BAD_VALUE
を返し、フラッシュ完了イベントを生成しないようにする必要があります。
センサー イベントを FMQ に書き込む
Event FMQ は、センサー HAL でセンサー イベントを Android センサー フレームワークにプッシュするために使用されます。
Event FMQ は同期された FMQ です。これは、使用可能なスペースよりも多くのイベントを FMQ に書き込もうとすると、書き込みが失敗することを意味します。その場合、HAL は現在の一連のイベントを 2 つの小規模なイベントのグループとして書き込むか、十分なスペースが利用可能になった時点ですべてのイベントをまとめて書き込むかを決定する必要があります。
センサー HAL は、目的の数のセンサー イベントを Event FMQ に書き込む際、EventQueueFlagBits::READ_AND_PROCESS
ビットを Event FMQ の EventFlag::wake
関数に書き込むことにより、フレームワークに対してイベントの準備が完了したことを通知する必要があります。EventFlag は、EventFlag::createEventFlag
と Event FMQ の getEventFlagWord()
関数を使用して Event FMQ から作成できます。
センサー AIDL HAL は、Event FMQ の write
と writeBlocking
の両方をサポートします。デフォルトの実装には write
を使用するための参照が備えられています。writeBlocking
関数を使用する場合は、readNotification
フラグを EventQueueFlagBits::EVENTS_READ
に設定する必要があります。これは、Event FMQ からイベントを読み取るときにフレームワークによって設定されます。書き込み通知フラグは EventQueueFlagBits::READ_AND_PROCESS
に設定されている必要があります。これにより、Event FMQ にイベントが書き込まれたことがフレームワークに通知されます。
WAKE_UP イベント
WAKE_UP
イベントは、アプリ プロセッサ(AP)を起動して直ちにイベントを処理させるセンサー イベントです。WAKE_UP
イベントが Event FMQ に書き込まれるたびに、センサー HAL は、フレームワークがイベントを処理できるようになるまでシステムが画面をロックしないように、wake lock を保護する必要があります。WAKE_UP
イベントを受け取ると、フレームワークはフレームワーク内の wake lock を保護し、センサー HAL が wake lock を解放できるようにします。センサー HAL が wake lock を解放したときに同期するには、Wake Lock FMQ を使用します。
センサー HAL は、フレームワークが処理した WAKE_UP
イベントの数を確認するために、Wake Lock FMQ を読み取る必要があります。HAL は、未処理の WAKE_UP
イベントの合計数がゼロの場合に限り、WAKE_UP
イベントの wake lock を解放する必要があります。フレームワークではセンサー イベントの処理後に WAKE_UP
イベントとしてマークされているイベントの数をカウントし、この数を Wake Lock FMQ に書き込みます。
フレームワークは、Wake Lock FMQ にデータを書き込むたびに Wake Lock FMQ に WakeLockQueueFlagBits::DATA_WRITTEN
書き込み通知を設定します。
動的センサー
動的センサーは、物理的にデバイスの一部ではありませんが、デバイスへの入力として使用できるセンサー(加速度計を備えたゲームパッドなど)です。
動的センサーが接続されている場合は、ISensorsCallback
で onDynamicSensorConnected
関数をセンサー HAL から呼び出す必要があります。これにより、新しい動的センサーのフレームワークに通知され、フレームワークを介してセンサーを制御し、センサーのイベントをクライアントで使用できるようになります。
同様に、動的センサーの接続が切断された場合は、ISensorsCallback
で onDynamicSensorDisconnected
関数を呼び出して、使用できなくなったセンサーをフレームワークが削除できるようにする必要があります。
ダイレクト チャンネル
ダイレクト チャンネルでは、Android センサー フレームワークを迂回して、Event FMQ ではなく特定のメモリにセンサー イベントを書き込みます。ダイレクト チャンネルを登録するクライアントは、ダイレクト チャンネルの作成に使用されたメモリからセンサー イベントを直接読み取る必要があり、フレームワークを通じてセンサー イベントを受け取ることはありません。configDirectReport()
関数は、通常のオペレーションでは batch()
に類似しており、ダイレクト レポート チャンネルを構成します。
registerDirectChannel()
関数と unregisterDirectChannel()
関数はそれぞれ、新しいダイレクト チャンネルを作成または破棄します。
オペレーション モード
setOperationMode()
関数を使用すると、フレームワークがセンサーが構成し、そのセンサーにセンサーデータを挿入できるようになります。特に、アルゴリズムがフレームワークの下にある場合のテストに有用です。
injectSensorData()
関数は通常、オペレーション パラメータをセンサー HAL にプッシュするために使用されます。この関数を使用して、センサー イベントを特定のセンサーに挿入することもできます。
検証
センサー HAL の実装を検証するには、センサーの CTS テストと VTS テストを実行します。
CTS テスト
センサー CTS テストは、自動化された CTS テストと手動 CTS 検証ツールアプリの両方にあります。
自動テストは、cts/tests/sensor/src/android/hardware/cts にあります。これらのテストでは、センサーの有効化、バッチ処理、センサー イベント発生率など、センサーの標準的な機能を検証します。
CTS 検証ツールテストは cts/apps/CtsVerifier/src/com/android/cts/verifier/sensors にあります。これらのテストは、テスト オペレータの手動入力を必要とし、センサーが正確な値を報告するようにします。
テスト対象のデバイスがすべての CDD 要件を満たすようにするには、CTS テストに合格することが不可欠です。
VTS テスト
センサー AIDL HAL の VTS テストは、hardware/interfaces/sensors/aidl/vts/ にあります。これらのテストでは、センサー HAL が正しく実装されていること、ISensors.aidl
と ISensorsCallback.aidl
の中のすべての要件が適切に満たされていることを確認します。
HAL を初期化する
フレームワークと HAL の間で FMQ を確立するには、initialize()
関数がサポートされている必要があります。
使用可能なセンサーをエクスポーズする
センサー AIDL HAL では、一回のデバイス起動中、センサー HAL の再起動後も含めて、getSensorsList()
関数が同じ値を返す必要があります。getSensorsList()
関数の新しい要件では、一回のデバイス起動中に(センサー HAL の再起動後も含めて)同じ値を返す必要があります。これにより、システム サーバーの再起動時に、フレームワークがセンサー接続の再確立を試行できます。getSensorsList()
が返す値は、デバイスの再起動後に変化する可能性があります。
センサー イベントを FMQ に書き込む
センサー AIDL HAL では、poll()
が呼び出されるのを待たずにセンサー イベントを使用できる場合、常に前もってセンサー HAL が Event FMQ にセンサー イベントを書き込んでおく必要があります。また、HAL は、フレームワーク内で FMQ の読み取りが行われるように、正しいビットを EventFlag
に書き込む必要があります。
WAKE_UP イベント
センサー HAL 1.0 では、WAKE_UP
が poll()
にポストされた後、後続の poll()
の呼び出しで WAKE_UP
イベントの wake lock を HAL が自ら解放できました。フレームワークがすべてのセンサー イベントを処理し、必要に応じて wake lock を取得したことが HAL に通知されていたためです。センサー AIDL HAL では、フレームワークが FMQ に書き込まれたイベントを処理したことが HAL に通知されなくなったため、Wake Lock FMQ は、フレームワークが WAKE_UP
イベントの処理後に HAL と通信できるようにしました。
センサー AIDL HAL では、WAKE_UP
イベントのためにセンサー HAL が保護する wake lock の冒頭を SensorsHAL_WAKEUP
にする必要があります。
動的センサー
センサー HAL 1.0 では、poll()
関数を使用して動的センサーが返されていました。センサー AIDL HAL では、動的センサーの接続が変更されるたびに、ISensorsCallback
で onDynamicSensorsConnected
と onDynamicSensorsDisconnected
を呼び出す必要があります。これらのコールバックは、initialize()
関数によって提供される ISensorsCallback
ポインタの一部として使用できます。
オペレーション モード
WAKE_UP
センサーの DATA_INJECTION
モードをサポートする必要があります。
Multi-HAL のサポート
センサー AIDL HAL は、センサー Multi-HAL フレームワークを使用することで Multi-HAL をサポートしています。実装の詳細については、センサー HAL 2.1 からの移植をご覧ください。