センサー ハードウェア抽象化レイヤ(HAL)は、Android センサー フレームワークとデバイスのセンサー(加速度計やジャイロスコープなど)との間のインターフェースです。センサー HAL は、フレームワークがセンサーを制御できるように実装する必要がある関数を定義します。
センサー HAL 2.0 は、Android 10 以降で、新しいデバイスとアップグレードされたデバイスで利用できます。センサー HAL 2.0 はセンサー HAL 1.0 がベースになっていますが、いくつかの重要な相違点があるため、下位互換性がありません。センサー HAL 2.0 は高速メッセージ キュー(FMQ)を使用して、センサー イベントを HAL から Android センサー フレームワークに送信します。
センサー HAL 2.1 は、Android 11 以降で、新しいデバイスとアップグレードされたデバイスで利用できます。センサー HAL 2.1 は、センサー HAL 2.0 の後継であり、HINGE_ANGLE センサータイプをエクスポーズして各種メソッドを更新し、HINGE_ANGLE
タイプを受け入れます。
HAL 2.1 インターフェース
センサー HAL 2.1 の詳細については、hardware/interfaces/sensors/2.1/ISensors.hal にある HAL の定義に記載されているドキュメントをご覧ください。このページと ISensors.hal
で要件が異なる場合は、ISensors.hal
の要件を優先してください。
HAL 2.0 インターフェース
センサー HAL 2.0 の詳細については、hardware/interfaces/sensors/2.0/ISensors.hal にある HAL の定義に記載されているドキュメントをご覧ください。このページと ISensors.hal
で要件が異なる場合は、ISensors.hal
の要件を優先してください。
センサー HAL 2.0 と HAL 2.1 を実装する
センサー HAL 2.0 または 2.1 を実装するには、オブジェクトで ISensors
インターフェースを拡張し、2.0/ISensors.hal
または 2.1/ISensors.hal
で定義された関数をすべて実装する必要があります。
HAL を初期化する
センサー HAL を使用するには、Android センサー フレームワークで初期化する必要があります。フレームワークは HAL 2.0 の initialize()
関数と HAL 2.1 の initialize_2_1()
関数を呼び出して、センサー HAL に 3 つのパラメータ(2 つの FMQ 記述子と ISensorsCallback
オブジェクトへの 1 つのポインタ)を渡します。
HAL は、最初の記述子を使用して、センサー イベントをフレームワークに書き込む際に使用するイベント FMQ を作成します。2 番目の記述子は HAL が wake lock FMQ を作成する際に使用されます。この wake lock FMQ は、WAKE_UP
センサー イベントの wake lock を解放する際、同期するために使用されます。さらに、必要なコールバック関数を呼び出すことができるように、ISensorsCallback
オブジェクトへのポインタを保存する必要があります。
initialize()
関数または initialize_2_1()
関数は、センサー HAL の初期化時に呼び出される最初の関数であることが必要です。
使用可能なセンサーをエクスポーズする
デバイスで使用可能なすべての静的センサーのリストを取得するには、HAL 2.0 の getSensorsList()
関数と HAL 2.1 の getSensorsList_2_1()
関数を使用します。この関数は、ハンドルで一意に識別されたセンサーのリストを返します。センサー HAL をホストするプロセスが再起動されたときに、対象のセンサーのハンドルを変更しないでください。ハンドルは、デバイスの再起動のたびに、また、システム サーバーの再起動のたびに変更される場合があります。
複数のセンサーが同じセンサータイプとウェイクアップ プロパティを共有する場合、リスト内の最初のセンサーがデフォルト センサーとして呼び出され、getDefaultSensor(int sensorType, bool wakeUp)
関数を使用するアプリに返されます。
センサーリストの安定性
センサー HAL の再起動後に、getSensorsList()
または getSensorsList_2_1()
によって返されたデータが、再起動前に取得したセンサーリストと比較して大幅な変化を示している場合は、フレームワークにより Android ランタイムの再起動がトリガーされます。センサーリストの大幅な変更には、特定のハンドルを持つセンサーが欠落しているケースや、属性が変更されたケース、新しいセンサーが導入されたケースなどが該当します。Android ランタイムの再起動はユーザーの混乱を招きますが、アプリの存続期間中に静的(動的でない)センサーを変更しないという Android API 契約を、Android フレームワークが遵守できなくなるため必要です。これによって、アプリによるアクティブなセンサー リクエストをフレームワークが再確立することも回避できます。したがって、HAL ベンダーには、センサーリストの変更をできる限り回避することをおすすめします。
センサー ハンドルを安定化するため、HAL はデバイス内の物理センサーをそのハンドルに対して確定的にマッピングする必要があります。センサー HAL インターフェースで特定の実装が必須となっているわけではありませんが、デベロッパーはこの要件を満たすためにいくつかのオプションを使用できます。
たとえば、センサーリストは、各センサーの固定属性(ベンダー、モデル、センサータイプなど)を組み合わせて使用することで並べ替えることができます。もう 1 つのオプションは、デバイスの静的センサーのセットがハードウェアに固定されており、getSensorsList()
または getSensorsList_2_1()
から戻る前に、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
とイベント FMQ の getEventFlagWord()
関数を使用して、イベント FMQ から作成できます。
センサー HAL 2.0 / 2.1 は、イベント 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()
関数を使用すると、フレームワークがセンサーが構成し、そのセンサーにセンサーデータを挿入できるようになります。特に、アルゴリズムがフレームワークの下にある場合のテストに有用です。
通常は、HAL 2.0 の injectSensorData()
関数と HAL 2.1 の injectSensorsData_2_1()
関数がオペレーション パラメータをセンサー 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 テスト
センサー HAL 2.0 の VTS テストは、hardware/interfaces/sensors/2.0/vts にあります。センサー HAL 2.1 の VTS テストは、hardware/interfaces/sensors/2.1/vts にあります。これらのテストでは、センサー HAL が正しく実装されていることと、ISensors.hal
と ISensorsCallback.hal
内のすべての要件が適切に満たされていることを確認します。
センサー HAL 2.0 から 2.1 にアップグレードする
センサー HAL 2.0 から 2.1 にアップグレードする場合は、HAL 実装に initialize_2_1()
、getSensorsList_2_1()
、injectSensorsData_2_1()
の各メソッドと、HAL 2.1 の型を含める必要があります。これらのメソッドは、上記で概要を説明した HAL 2.0 の要件と同じ要件を満たす必要があります。
マイナー バージョンの HAL は以前の HAL の関数をすべてサポートする必要があるため、2.1 の HAL は 2.0 の HAL として初期化されることに対応している必要があります。HAL の両方のバージョンをサポートすることに伴う複雑さを回避するため、Multi-HAL 2.1 を使用することを強くおすすめします。
独自のセンサー HAL 2.1 を実装する方法の例については、Sensors.h をご覧ください。
センサー HAL 1.0 から 2.0 にアップグレードする
センサー HAL 1.0 から 2.0 にアップグレードする場合は、HAL 実装が次の要件を満たしていることを確認してください。
HAL を初期化する
フレームワークと HAL の間で FMQ を確立するには、initialize()
関数がサポートされている必要があります。
使用可能なセンサーをエクスポーズする
センサー HAL 2.0 では、getSensorsList()
関数は単一デバイスの起動中(センサー HAL の再起動後も)同じ値を返す必要があります。getSensorsList()
関数の新しい要件として、単一デバイスの起動中(センサー HAL の再起動後も)同じ値を返す必要があります。これにより、システム サーバーの再起動時に、フレームワークがセンサー接続の再確立を試行できます。getSensorsList()
が返す値は、デバイスの再起動後に変化する可能性があります。
センサー イベントを FMQ に書き込む
センサー HAL 2.0 では、poll()
が呼び出されるのを待つのではなく、センサー イベントが発生するたびに、センサー HAL がセンサー イベントを Event FMQ に前もって書き込む必要があります。また、HAL はフレームワーク内で FMQ が読み取りを行うようにするため、正しいビットを EventFlag
に書き込む必要があります。
WAKE_UP イベント
センサー HAL 1.0 では、HAL は、WAKE_UP
が poll()
にポストされた後の後続の poll()
の呼び出しで WAKE_UP
イベントの wake lock を解放できました。これは、フレームワークがすべてのセンサー イベントを処理し、必要に応じて wake lock を取得したことを示すためです。センサー HAL 2.0 では、フレームワークが FMQ に書き込まれたイベントをいつ処理したかを HAL が認識しなくなったため、Wake Lock FMQ はフレームワークが WAKE_UP
イベントを処理した際に HAL と通信することを許可します。
センサー HAL 2.0 では、WAKE_UP
イベントでセンサー HAL で保護された wake lock が SensorsHAL_WAKEUP
で起動する必要があります。
動的センサー
センサー HAL 1.0 では、poll()
関数を使用して動的センサーが返されました。センサー HAL 2.0 では、動的センサー接続が変更されるたびに、ISensorsCallback
の onDynamicSensorsConnected
と onDynamicSensorsDisconnected
を呼び出す必要があります。これらのコールバックは、initialize()
関数によって提供される ISensorsCallback
ポインタの一部として使用できます。
オペレーション モード
WAKE_UP
センサーの DATA_INJECTION
モードはセンサー HAL 2.0 でサポートされている必要があります。
Multi-HAL のサポート
センサー HAL 2.0 と 2.1 は、センサーの Multi-HAL フレームワークを使用した Multi-HAL をサポートしています。実装の詳細については、センサー HAL 1.0 からの移植をご覧ください。