動的シャットダウンを実装する作業には、以下のセクションで説明するように、データフローの結合と動的プロセスの実行が含まれます。
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_start
、ctl.interface_stop
、ctl.interface_restart
の 3 つのメッセージが追加されています。これらのメッセージを使用して、特定のハードウェア インターフェースの起動と停止を init
に指示することもできます。サービスがリクエストされ、そのサービスが登録されていない場合は、hwservicemanager
がサービスの開始をリクエストします。ただし、動的 HAL ではこれらのいずれも使用する必要はありません。
HAL の終了の決定
Android 9 では、HAL の終了を手動で決定する必要があります。Android 10 以上では、自動ライフサイクルで決定することもできます。
動的シャットダウンには、HAL をいつ起動していつシャットダウンするかを決めるためのポリシーが複数必要です。HAL がなんらかの理由で終了を決断した場合、HAL 定義で提供される情報と、init
と hwservicemanager
の変更により提供されるインフラストラクチャを使用して、必要に応じて 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()
も呼び出すようにしてください。これにより、関連する参照カウントの変更がバインダ ドライバに通知されるようになります。