動的に使用可能な HAL

Android 9 では、Android ハードウェアのサブシステムが使用されていない場合または不要な場合の動的なシャットダウンをサポートしています。たとえば、ユーザーが Wi-Fi を使用していない場合、Wi-Fi サブシステムがメモリ、電源、その他のシステム リソースを占有するのは望ましくありません。以前のバージョンの Android では、Android スマートフォンが起動している間ずっと、HAL / ドライバが Android デバイスで開いたままになっていました。

動的シャットダウンを実装する作業には、以下のセクションで説明するように、データフローの結合と動的プロセスの実行が含まれます。

HAL 定義の変更

動的シャットダウンでは、どのプロセスがどのような HAL インターフェースにサービスを提供するかについての情報が必要です(この情報は後で他のコンテキストでも役立ちます)。また、起動時にプロセスを起動せず、終了時に(再度リクエストされるまでは)プロセスを再起動しないことも必要です。

# some init.rc script associated with the HAL
service vendor.some-service-name /vendor/bin/hw/some-binary-service
    # init language extension, provides information of what service is served
    # if multiple interfaces are served, they can be specified one on each line
    interface android.hardware.light@2.0::ILight default
    # restarted if hwservicemanager dies
    # would also cause the hal to start early during boot if disabled wasn't set
    class hal
    # will not be restarted if it exits until it is requested to be restarted
    oneshot
    # will only be started when requested
    disabled
    # ... other properties

init と hwservicemanager の変更

動的シャットダウンには、リクエストされたサービスの開始を init に指示するための hwservicemanager も必要です。Android 9 では、init に含まれる制御メッセージ(ctl.start など)に、ctl.interface_startctl.interface_stopctl.interface_restart の 3 つのメッセージが追加されています。これらのメッセージを使用して、特定のハードウェア インターフェースの起動と停止を init に指示することもできます。サービスがリクエストされ、そのサービスが登録されていない場合は、hwservicemanager がサービスの開始をリクエストします。ただし、動的 HAL ではこれらのいずれも使用する必要はありません。

HAL の終了の決定

Android 9 では、HAL の終了を手動で決定する必要があります。Android 10 以上では、自動ライフサイクルで決定することもできます。

動的シャットダウンには、HAL をいつ起動していつシャットダウンするかを決めるためのポリシーが複数必要です。HAL がなんらかの理由で終了を決断した場合、HAL 定義で提供される情報と、inithwservicemanager の変更により提供されるインフラストラクチャを使用して、必要に応じて HAL が自動的に再起動されます。これには、次のようなさまざまな戦略があります。

  • HAL は、close または類似の API が HAL 上で呼び出された場合、HAL 上で exit を呼び出すことを選択できます。この動作は、対応する HAL インターフェースで指定する必要があります。
  • タスクが完了すると、HAL はシャットダウンを実行できます(HAL ファイルに記述されています)。

自動ライフサイクル

Android 10 では、カーネルと hwservicemanager に対するサポートが追加され、クライアントがない場合にいつでも HAL を自動的にシャットダウンできるようになりました。この機能を使用するには、HAL 定義の変更のすべてのステップに加えて、以下を行います。

  • メンバー関数 registerAsService の代わりに、LazyServiceRegistrar を使用して C++ でサービスを登録します。
    // only one instance of LazyServiceRegistrar per process
    LazyServiceRegistrar registrar;
    registrar.registerAsService(myHidlService /* , "default" */);
  • HAL クライアントが、使用されているときにのみトップレベルの HAL(hwservicemanager に登録されているインターフェース)への参照を保持することを確認します。遅延を回避するために、実行を継続する hwbinder スレッドでこの参照が破棄された場合、参照の破棄後にクライアントが IPCThreadState::self()->flushCommands() も呼び出すようにしてください。これにより、関連する参照カウントの変更がバインダ ドライバに通知されるようになります。