AndroidHIDLソースコード分析



Android Hidl Source Code Analysis



Android HIDL基本的な知識、ソースコード分析。



概念

In Android O 8.0後で紹介Trebleプロジェクトの目的はFramework HAL分離されたレイヤーGoogle焦点Framework以上HAL以下と以下は実現のためにさまざまなメーカーに引き渡されますHALレイヤーとベンダーの実装の両方が新しい/vendorに入れられますこのようにパーティション内でGoogleフォローアップ中OTAシステムがアップグレードされると、メーカーの実装部分を変更することなく、システム部分を個別にアップグレードできます。したがって、再定義しますFramework HALレイヤーのインターフェース、つまりHIDL 'インターフェース層テストを追加VTS: Vendor Test Suiteメーカーが仕様に準拠してインターフェース設計の一部を実装し、上位互換性があることを確認します。つまり、Googleこれの主な目的は次のとおりです。メーカーがどのように認識し、何を変更しても、Androidネイティブシステムをアップグレードしてこのデバイスで使用できるようにする必要があります。もちろん、この構造は携帯電話メーカーにとっても便利ですsystem現在のバージョンがすでにある場合はアップグレードAndroid O各パーティションが割り当てられており、更新できるのはAOSP部分的にPその他vendor変更しないでおくことができ、可能性と利便性を提供します。実際、メーカーはこれを喜んで行いますか?

0110-android-hidl-treble.png



HIDL: HAL Interface Definition LanguageHIDL発音hide-l、指定HALレイヤーおよびFrameworkレイヤー通信のインターフェース、目的はFrameworkHALレイヤーはユーザーが再コンパイルせずにAndroidフレームワークを置き換えることができるように相互に通信するHAL

HALの種類

HAL 2つのタイプがあります。

  • Binder HAL
    バインディングHALスルーBinderメカニズムはクロスプロセス通信を実現します。
  • Passthrough HAL
    ストレートスルーHALスルーdlopenライブラリをロードする方法は、同じプロセスで直接呼び出すことです。ここで、デフォルトでは*が通常使用されることに注意してください BinderストレートスルーHAL * 、つまり、最終的にはまだクロスプロセスBinder通信です。

0110-android-hidl-treble_cpp_legacy_hal_progression.png



Binder HAL

Android O開始、Framework HALクロスプロセスも使用されますBinder相互に通信します。この通信方法は、古いバージョンでは大幅に増加していますBinderトラフィック、新しいBinderドメイン、公式Webサイトでは、次の3つのドメインの使用を推奨しています。

  • /dev/binder
    のためにFramework APPIPC使用AIDLインターフェース間。
  • /dev/hwbinder
    のためにFramework Vendorプロセス間IPC使用HIDLインターフェース。
    サプライヤープロセス間で使用IPC使用HIDLインターフェース。
  • /dev/vndbinder
    サプライヤー/サプライヤープロセス間IPC使用AIDLインターフェース。

BinderストレートスルーHAL

それは実際にはパススルーモードですHALスルーBinderそれを達成するために。例HALインターフェースroot@xxxxx::IFoo、システムは2つのパッケージを作成します:

  • root@xxxxx::IFoo-impl
    含むHAL実装および公開関数IFoo* HIDL_FETCH_IFoo(const char* name)。古いデバイスでは、このソフトウェアパッケージはdlopen使用の処理と実現HIDL_FETCH_IFooインスタンス化されます。使用することもできますhidl-gen -Lc++-impl-Landroidbp-impl基本的なコードを生成します。
  • root@xxxxx::IFoo-service
    ストレートスルーをオンにするHALそして自分自身をBinderサービスとして登録して、同じHAL同時に使用する機能を実現するBinder化学モードで使用する。
    ある場合IFoo電話することができますsp IFoo::getService(string name, bool getStub)権利を取得するにはIFooインスタンスのアクセス権。 getStub For Trueの場合、getServiceパススルーモードでのみ開こうとしますHALgetStub For Falseの場合、getServiceサービスを見つけようとしますBinderサービスが見つからない場合は、ストレートスルーサービスを見つけようとします。 defaultPassthroughServiceImplementationを除いて、それまでの間、残りのケースは使用されませんgetStubパラメータ。 (パイロットAndroid O機器は完全にBinder機器はパススルーモードでサービスを開くことができません。)

ネットワーク構成ツール

Android標準を含めるLinuxネットワークユーティリティ:ifconfig, ip, ip6tables待機しますが、これらの手順はsystem/binディレクトリの下、Android Oその後、システムの更新によって不一致が発生するのを防ぎます。これらのプログラムを使用する場合、これらのプログラムはnetutils-wrapper-1.0ツールに統合されます。

Android O vendor

/system/bin/netutils-wrapper-1.0その後、/system/bin/ip 直接呼び出すことはできません/system/bin/ip-wrapper-1.0 そうしないと、直接呼び出すことができないというエラーが発生しますvendorパッケージ化されたプログラムを使用する代わりにSELinux policy Androidプロセスがこれらのコマンドを呼び出す場合hal追加:

HIDL HAL c2hal: system/tools/hidl/c2hal

変換ツール

Binderツールの古いソースバージョンはソースコードで提供されますHIDLモジュール変換Binderフォーマット、ツール:HAL、使用例:

HAL HIDL

変換が完了した後、いくつかのマイナーエラーを手動でさらに修正できます。

用語

  • HAL華華
    意味HIDLプロセス間のリモートプロシージャコールに使用され、同様の方法で使用されますHAL達成するメカニズム。
  • 非同期コールバック
    by Minorユーザーによって提供され、C++(経由Javaメソッド)およびby HIDLいつでもデータを返すために呼び出されるインターフェース。
  • 同期コールバック
    サーバーからのデータHIDLメソッドの実装はクライアントに戻り、無効な値や単一の元の値を返すために使用されません。
  • クライアント
    特定のインターフェースのメソッドを呼び出すプロセス。 A dlopenプロセスまたはフレームワークプロセスは、あるインターフェイス上のクライアントと別のインターフェイス上のサーバーにすることができます。
  • 展開
    継承として理解することもできます。これは、メソッドやインターフェイスのタイプを別のインターフェイスに追加することを意味します。あるインターフェイスは別のインターフェイスのみを拡張できます。同じパッケージ名で使用できますHIDLインクリメンタルバージョンは、古いソフトウェアパッケージの上に構築された新しいソフトウェアパッケージにも使用できます。
  • 生む
    クライアントに値を返すインターフェイスメソッドを表します。元の値以外の値または複数の値を返すために、同期コールバック関数が生成されます。
  • インターフェース
    メソッドとタイプのコレクション。クラス内でHIDLまたはMajorに変換されます。インターフェイスのすべてのメソッドは同じ方向で呼び出されます。クライアントプロセスは、サーバープロセスによって実装されたメソッドを呼び出します。
  • 一方向
    適用対象Minorメソッドが使用される場合、メソッドが値を返さず、ブロッキングも発生しないことを意味します。
  • まっすぐ通り抜ける
    Minorこのモードを使用する場合、サーバーが共有ライブラリであり、クライアントによって実行されるモードfqName扱う。パススルーモードでは、クライアントとサーバーは同じプロセスですが、コードベースが異なります。このモードは、古いコードベースhidlモデルをマージするためにのみ使用されます。
  • サーバ
    インターフェイスのメソッドを実装するプロセス。
  • トランスミッション
    サーバーとクライアント間でデータを移動するroot@xxxxx::IFooインフラストラクチャ。
  • バージョン
    パッケージのバージョン。 HIDLバージョンとroot@xxxxxバージョンの2つの整数で構成されます。 A HIDLインクリメンタルバージョンでは、タイプとメソッドを追加できます(変更はできません)。
  • アプリケーションバイナリインターフェース `ABI
    アプリケーションプログラミングインターフェイス+必要なバイナリリンク。
  • 完全修飾名HIDL
    区別するために使用されますandroid.hardwareタイプの名前。例:root@xxxxx
  • ソフトウェアパッケージ
    バージョンを共有するインターフェースとデータ型のコレクション。含まれていますAndroidソフトウェアパッケージのインターフェースとタイプ。例:/** */, /* */, //
  • パッケージルートディレクトリ
    含む[empty]インターフェイスのルートディレクトリソフトウェアパッケージ。例:?インターフェース...パッケージのルートHIDL中。
  • パッケージのルートディレクトリパス
    パッケージのルートディレクトリは、,ソースコードツリー内の場所にマップされます。

基本的な文法

ルール

package.subpackage package root@xxxxx
  • hardware/interfaces/example/extension/light/2.0コメントするには
  • .hal単語が空である可能性があることを示します
  • packageテキストまたは単語の後に続き、オプションであることを示します
  • types.hal&iexclは、指定された区切り文字で区切られた、0個以上の項目を含むシーケンスを表します。major.minor中央 含まれていない 可変パラメータ
  • カンマMajorシーケンス要素を区切るために使用
  • Semicolon最後の要素を含む各要素を終了するために使用されます
  • 大文字はターミネーターではありません
  • イタリックは、整数や識別子などの一連のトークンです(標準のC解析ルール)
  • constexprは、Cスタイルの定数式(1 + 1や1Lなど)です。<< 3)
  • import_nameは、HIDLバージョン番号で説明されているように修飾されたソフトウェアパッケージまたはインターフェイスの名前です。
  • 小文字はテキストトークンです

ソフトウェアパッケージ

パッケージ名には子を含めることができます(例:Major)。パッケージプレフィックスと対応する場所は次のとおりです。

パッケージプレフィックス ポジション
android.hardware。* ハードウェア/インターフェース/ *
android.frameworks。* フレームワーク/ハードウェア/インターフェース/ *
android.system。* システム/ハードウェア/インターフェース/ *
android.hidl。* system / libhidl / transport / *

例:Minorソフトウェアパッケージ:
Minor次に見つかります。パッケージディレクトリには拡張子が含まれますMinor各ファイルには、指定されたファイルが属するソフトウェアパッケージとバージョンが含まれている必要がありますHALステートメントファイルMajor(存在する場合)インターフェイスは定義しませんが、ソフトウェアパッケージの各インターフェイスがアクセスできるデータ型を定義します。

バージョンナンバー

ソフトウェアパッケージは、2つの整数で表されるバージョンに分割されています:Minor

  • Minorバージョンには下位互換性がありません
    インクリメントMajorバージョン番号が作成されますMinorバージョン番号は0にリセットされます。
  • Minor下位互換性のあるバージョン
    増加している場合@callflowバージョン番号は、新しいバージョンが以前のバージョンと完全に下位互換性があることを意味します。新しいデータ構造とメソッドを追加できますが、既存のデータ構造またはメソッドの署名を変更することはできません。

1つのデバイスで同時に提供できますnext=複数@entryまたは@exitバージョン。ただし、halバージョンは前のバージョンと同じであるためextendsバージョンよりも優先する必要がありますroot@xxxxx::IBaseバージョンインターフェイスと一緒に使用されるクライアントコードは、のフォローアップにも適しています同じインターフェースJavaバージョン。

サポートされているメモ

主にVTSテストに使用されます

  • java.lang.Object
    IBase
  • hal
  • Minor

original定義

IFoo Minor

明示的original宣言されたインターフェースはIFooIFoo中間Majorと同様)暗黙的拡張から変更されます。暗黙的にインポートされますderivativeインターフェイスは、ユーザー定義インターフェイスで再宣言したり、他の方法で使用したりするべきではない、またはできないさまざまな予約メソッドを宣言します。つまり、IBarオーバーロードがなく、書き直し!

インターフェイスは、他の1つのインターフェイスのみを拡張できます( 多重継承をサポートしていません )、ゼロ以外originalバージョン番号の付いたソフトウェアパッケージの各インターフェイスは、前のバージョンのソフトウェアパッケージのインターフェイスを拡張する必要があります。

  • バージョン1.2のソフトウェアパッケージが存在しますIFooインターフェース入力Minor
  • 小さいバージョンIBarバージョン1.3、ソフトウェアパッケージにアップグレードIBarインターフェース入力IFooバージョン1.2を継承する必要がありますIFoo
  • ラージバージョンMajorバージョン4.0にアップグレードし、ソフトウェアパッケージIBarインターフェイス入力HALバージョン1.2から継承されたソフトウェアパッケージHIDLインターフェイス入力HAL
  • 小さいバージョンHALバージョン4.1にアップグレードするimportバージョン4.0を拡張する必要があるimportただし、バージョン1.3を継承することはできませんHIDLバージョン1.2と互換性があるためimportバインド
  • ビッグバージョンtypes.halこの時点でバージョン5.0に再度アップグレードimprot `IFooのバージョン1.3に直接アクセスできます

インターフェイス拡張は、生成されたコードにコードベースの依存関係またはクロスがあることを意味するものではありませんcustom.hal包含関係、インターフェイス拡張はimportレベルでのデータ構造とメソッド定義のインポートのみです。types.hal types.hal中国で再実装された各メソッド。

types.halインポート

Hashこのステートメントは、ソフトウェアパッケージインターフェイスにアクセスし、他のソフトウェアパッケージを入力するために使用されますcurrent.txtメカニズム、2つのインポート状況があります。

  • HIDLステートメントは次の場所にありますHIDLファイルでは、インポートされたコンテンツは、パッケージレベルのインポートに属するソフトウェアパッケージ全体に表示されます。
  • current.txtステートメントは次の場所にあります-r vendor.awesome:vendor/awesome/interfacesインターフェイスファイルでは、インポートされたコンテンツは、インターフェイスレベルのインポートに属する現在のインターフェイスファイルにのみ表示されます。

$ANDROID_BUILD_TOP/vendor/awesome/interfaces/current.txtステートメントの後、インポートされた値に応じて3つのケースがあります。

  • パッケージの完全なインポート
    インポート値はパッケージ名とバージョンであり、システムはパッケージ全体をインポートし、パッケージ全体のインターフェースまたはタイプにアクセスできます。
  • インターフェイスのインポート
    インポート値はインターフェースファイルであり、インターフェースとcurrent.txt 2つのファイルをインポートします。
  • インポートと入力します
    インポートされる値はsystem/libhidl/transport/current.txtで定義された特定のタイプについては、そのタイプのみがインポートされ、current.txtの他のタイプはインポートされません。
Android Android O

インターフェイスハッシュAndroid O-MR1およびバージョン管理ファイルcurrent.txt

hidl-genインターフェースハッシュは、偶発的なインターフェース変更を防ぎ、インターフェース変更が徹底的にレビューされるように設計されたメカニズムです。なぜなら-Lhashインターフェースにはバージョン番号があります。つまり、一度リリースされるとインターフェースを変更することはできません。

ソフトウェアパッケージのルートディレクトリには、バージョン管理ファイルが必要ですhal current.txtなどのパッケージパスを作成する場合は、ファイルも作成する必要がありますIBase::getHashChain
hidl-genインターフェースハッシュとインターフェースの完全修飾名(HALなど)を含める必要があります。ファイルの内容は次のとおりです。

current.txt HAL

current.txt内容によるとcamera分離する大きなバージョン、たとえば、上部は.hal後半はonewayベンダー定義のインターフェースファイルも従う必要がありますこのフォーマット。

ハッシュを手動で追加できますinファイルでは、out, inoutパラメータの追加Binder追加されたオプションを使用することもできます。
以下は、タイプファイル、インターフェイス、およびソフトウェアパッケージ全体のハッシュ生成です。

HIDL HIDL

新しく追加された場合HIDLソフトウェアパッケージはハッシュと対応するインターフェイスファイルを生成し、一緒に書き込みますHIDLファイルに:

Binder RPC FMQ

インターフェイスファイルのハッシュはHIDLで呼び出すことができます。チェックしてください。 A FMQインターフェースがコンパイルされると、チェックされますHIDLソフトウェアパッケージのルートディレクトリRPC表示するファイルBinder変更されていますか:

  • 対応するハッシュ値が見つからない場合は、コンパイルを続行し、インターフェイスが解放されていないことを考慮してください
  • 対応するハッシュ値が見つかった場合は、それに応じて確認してください。
    • インターフェイスがハッシュ値と一致する場合は、コンパイルを続行します
    • インターフェイスがハッシュ値と一致しない場合は、インターフェイスが変更され、コンパイルを停止したことを意味します

したがって、インターフェイスファイルがデバッグ段階にある場合は、デバッグが完了するのを待ってから公開する必要がありますHIDLインターフェイスファイルが公開されると、インターフェイスを変更する場合は変更できません。インターフェイスを再定義するためのバージョン番号をアップグレードする必要があります。例FMQ関連するインターフェースを変更するには、バージョン番号をアップグレードする必要があります。

FMQ MQDescriptorSync, MQDescriptorUnsync

データ転送

データ送信の過程で:

  • HIDL RPCファイルインターフェイスで定義されたメソッドはデフォルトでブロッキングモードになっています。非ブロッキングタイプを使用する必要がある場合は、メソッドの前にキーワードを使用してくださいHIDL
  • メソッド呼び出しとコールバックは受け入れることができますMQDescriptorSyncパラメーター、サポートされていませんMQDescriptorUnsyncパラメーター
  • メソッドがデータ転送中に4KBを超えるデータを渡す場合、同時にオーバーコールしていると見なされます。クロスプロセス呼び出しはRPCメカニズムに基づいているため、データ転送の合計は1MBを超えることはできません。

クロスプロセス通信の場合、MessageQueueメモリ所有権の厄介な問題を回避するためにパラメータコールバック関数のみが使用されます。特に、メソッドで効果的に返すことができない値は、コールバック関数で直接返すことができます。これはデータをflavorフォローしないflavor: kSynchronizedReadWriteデータを受信し、データの所有権を変更しません。データは、呼び出された関数の期間中のみ存在する必要があり、呼び出された関数が戻った直後に破棄できます。

flavor: kUnsynchronizedWrite使用しない場合FMQデータを転送する方法は2つあります。

  • 共有メモリ
    割り当てられたメモリは、マッピングを通じて共有されます。
  • 高速メッセージキューMessageQueue
    .h待機なしのメッセージ配信を実現できるテンプレート化されたメッセージキュータイプを提供します。

高速メッセージキューMQDescriptor.h

MessageQueue(numElements)リモートプロシージャコールMessageQueue(numElements, configureEventFlagWord)インフラストラクチャの使用flavorメカニズム。これは、呼び出しにオーバーヘッドが含まれ、カーネル操作が必要であり、スケジューラ操作をトリガーできることを意味します。ただし、オーバーヘッドが少なく、カーネルの関与がないプロセス間でデータを転送する必要がある場合は、kSynchronizedReadWrite高速メッセージキューを提供しますkUnsynchronizedWriteシステム。
uint16_t必要な属性を持つメッセージキューが作成されますstringオブジェクトを渡すことができますvec呼び出しが送信され、受信プロセスがメッセージキューにアクセスするために使用できます。

ストレートモードまたはバウンドモードではカーネルまたはスケジューラーを使用しないため、組み込みのHIDLを使用して作成できます。 kNumElementsInQueueまたはHIDLパラメーターのタイプMemoryBlock配信のオブジェクト。

hidl_memoryサポートされているキュータイプHIDL @1.0::IAllocator 2つのタイプがあります。

  • 非同期キューHIDL @1.0::IMapper
    オーバーフローする可能性があり、複数のリーダーが存在する可能性があります。各リーダーは時間内にデータを読み取る必要があります。そうしないと、データが失われます。非同期キューのライターは1つだけですが、リーダーはいくつでもかまいません。このタイプのキューには書き込み位置がありますが、各リーダーは独自の独立した読み取り位置を追跡します。書き込み操作は成功します(オーバーフローがチェックされません)が、書き込まれたコンテンツが構成されたキュー容量を超えない場合に限ります(書き込まれたコンテンツがキュー容量を超えた場合、操作はすぐに失敗します)。各リーダーの読み取り位置は異なる場合があるため、システムは、各リーダーが各データを読み取るのを待たずに、新しい書き込み操作でスペースが必要になるたびにデータをキューから残すことができます。
  • キューが同期されましたHIDL
    オーバーフローすることはできず、リーダーは1つしか存在できません。同期キューにはライターとリーダーがあり、ライターには書き込み位置があり、リーダーには読み取り位置があります。書き込まれるデータの量は、キューで使用可能なスペースを超えることはできません。読み取られるデータの量は、現在キューにあるデータの量を超えることはできません。

これらのキューはどちらもアンダーフローできず(空のキューからの読み取りは失敗します)、ライターは1人しか存在できません。

HIDL関連するソースコードパスは次のとおりですFMQこれは主にテンプレートであるため、定義とコードの実装は次のとおりですMemoryBlockファイル内:

mmap/munmap hidl_memory

キュータイプは次のとおりですHIDL定義:

system/libhidl/base HidlSupport.h

高速キューの作成例:

hidl_death_recipient hidl_handle
  • native_handle_t初期化プログラムは、メッセージ待ち行列機能をサポートするオブジェクトの作成と初期化を担当します。
  • hidl_handle初期化プログラムは、メッセージキュー機能とブロックをサポートするオブジェクトの作成と初期化を担当します。
  • HIDL可能性がありますhidl_handleキューを同期するかnative_handle_tキューを同期しません
  • hidl_handleネストされたバッファ(なし_cbまたはnative_handle_tタイプ)、ハンドル、またはインターフェイスを含まないものにすることができますhidl_handle定義されたタイプ
  • native_handle_tキューに割り当てられた共有メモリバッファのサイズを決定するために使用されるキューのサイズ(エントリの観点から)を表します

メモリ共有

transport共有メモリclose構築されているHIDLJava with hidl_string上記の抽象化レイヤーは、単一のメモリヒープを共有する複数のメモリブロック用に設計されていますHIDLサービス用に設計されています。
つまり、HIDL共有メモリブロックは考え方を提供するだけであり、Java特定の実装用途を提供するJava大幅に削減できるhidl_memory数とユーザースペースのセグメンテーションエラーが正しくないため、パフォーマンスが向上します。アーキテクチャ図は次のとおりです。基本的な考え方は、複数のメモリブロックが単一のメモリヒープを共有することですmemory

0110-android-hidl_memoryblock_arch.png

基本的なデータ型

HIDL基本データ型と対応する処理はすべて含まれていますhidl_vecディレクトリに実装されている基本データ型の定義ファイルはvecディレクトリ構造は次のとおりです。

T T

HIDL

サービス死亡通知。クライアントが通知を登録すると、サーバーが切断されたときに通知が送信されます。

vec vec

vec

ハンドルの基本的なタイプは右ですTハンドルのカプセル化:

T uint32_t

呼び出しパスinterfaceオブジェクト(複合型の上部または一部)vec,vecインターフェイスメソッドを使用する場合、それに含まれるファイル記述子の所有権は次のとおりです。

  • Will bitfieldオブジェクトがパラメーターとして渡される呼び出し側プログラムは、カプセル化を保持しますvec呼び出し側は、これらのファイル記述子の操作を完了した後、これらのファイル記述子を閉じる必要があります。
  • スルーUオブジェクトはに渡されますvec関数とともにオブジェクトを返すプロセスは、オブジェクトのカプセル化を保持しますU[]それに含まれるファイル記述子の所有権プロセスはこれらを閉じる必要がありますこれらのファイル記述子の操作を完了した後のファイル記述子
  • 受信U送信には対応するオブジェクトのカプセル化がありますU受信者のファイル記述子の所有権受信者はトランザクションコールバック中にこれらのファイル記述子をそのまま使用できますが、引き続き使用する場合はコールバックが完了した後、これらのファイル記述子は、ネイティブハンドルのクローンを作成する必要があります。トランザクションが完了すると、hidl_arrayファイル記述子が自動的に実行されますhidl_version操作

HIDLサポートされていません.halハンドルを使用してください。

.hal

hardware/interface文字列の受け渡しmyintereインターフェイスは文字列を1.0またはfrom .halに渡します文字列を渡すと文字セットが変換され、この変換では元のエンコーディングが正確に保持されない場合があります。

.hal update-makefiles.sh

hidl-gen

Android.bp/mkタイプはhardware/interfaceマップされていない共有メモリを示すために使用されます。

./hardware/interfaces/update-makefiles.sh Android.bp

hidl-gen

hidl-genテンプレートは包含を示すために使用されますAndroid.bpインスタンスと可変サイズのバッファー。 A hidl, aidl何でもかまいませんjava, cpp, hハンドルを除き、ユーザーが提供または定義するタイプ。 (system/tools/hidl-genIFoo.hal構造体の配列を指し、内部を指していませんIFoo.hバッファ配列。)C++次のいずれかになります。

  • 基本タイプ(例:IFoo
  • ストリング
  • ユーザー定義の列挙
  • ユーザー定義の構造
  • インターフェース、またはIFoo.halキーワード(IFooトップレベルのパラメーターとしてのみサポートされます)
  • 扱う
  • C++
  • RPC 、それらの中でHwBinderインターフェースを除いて、このリストの任意の項目にすることができます(たとえば、::android::hardware::samples::IFoo::V1_0サポートされていません)
  • IHwFoo.h(サイズ付きBpFoo.h配列)、ここでIFooインターフェースを除く、このリスト内の任意の項目にすることができます

HwBinder

多次元配列を表します。

BnFoo.h IFoo

HwBinder

Stubバージョンナンバー。

FooAll.cpp HwBinder

HwBinder自動ファイル生成コード

基本的な手順

Stubファイルを追加する準備ができましたStub内容の下:

  • aidl-cppなどのパッケージ名に対応するフォルダーを作成します。
  • パッケージフォルダの下に、HIDLなどのメジャーバージョンとマイナーバージョンに対応するフォルダを作成します。
  • バージョンディレクトリの下に定義して書き込みますRPCファイル
  • 実行IFoo.hファイルの場所HIDLスクリプト(実際にはまだ呼び出されています)HwBinder RPC )、自動生成IFooファイル
    にあるのでIFoo.hディレクトリの下に追加された場合は、次を実行します。IFoo.hal対応は自動的に生成されますBinder
hidl-gen BsFoo.h

dlopenルール

HAL変換ルールと生成されるファイルは自動的に生成されますonewayドキュメントで定義されていますHAL自動ファイル生成onewayファイルツールのソースコードは| _ +にあります_ |内容の下:

HAL BsFoo.h

バインドモードの使用BpFoo.hコンパイラとBinderインターフェイスファイルを入力として使用すると、次の自動生成ファイルがあります。

0110-android-hidl-treble_cpp_compiler_generated_files.png

コンパイラによって生成されたファイル:

  • IPC
    説明HALカテゴリ内で純粋FooFast HAL含まれるインターフェースFooAccurate HALファイル内PTFooFast.cppインターフェースで定義されたメソッドとタイプは必要に応じて変換されますPTFooAccurate.cppの種類。このインターフェースの実装には含まれていませんhidl-genメカニズム(例fqName)関連する詳細。クラス名前空間には、パッケージ名とバージョン番号が含まれています(例:-L)。クライアントとサーバーの両方にこのヘッダーが含まれています。クライアントはこのヘッダーを使用してメソッドを呼び出し、サーバーはこのヘッダーを使用してこれらのメソッドを実装します。
  • -r
    インターフェイスで使用されるデータ型をシリアル化するために使用される関数の宣言を含むヘッダーファイル。開発者は、ヘッダーを直接含めてはなりません(クラスは含まれていません)。
  • hal
    From halインターフェースを記述できる継承クラス-r android.hardware:hardware/interfacesプロキシ(クライアント)の実装。開発者は、このクラスを直接参照することはできません。
  • hidl-gen
    ペアを保存するvendor.awesome:some/device/independent/path/interfaces実装された参照クラスは、インターフェースvendor.awesomeスタブ$ANDROID_BUILD_TOP/some/device/independent/path/interfaces(サーバー側)の実装を記述できます。開発者は、このクラスを直接参照することはできません。
  • root@xxxxx::IFoo
    含むvendor.awesomeエージェントおよびfooスタブ1.0実装クラス。クライアントがインターフェイスメソッドを呼び出すと、エージェントはクライアントからのパラメーターを自動的にマーシャリングし、トランザクションをバインドされたカーネルドライバーに送信します。これにより、トランザクションがもう一方の端のスタブに転送されますIFoo.hal(スタブはその後、実際のサーバー実装を呼び出します)。

これらの生成されたファイルの構造は、$ANDROID_BUILD_TOP/some/device/independent/path/interfaces/foo/1.0/IFoo.hal生成されたファイルに似ています。 -rsome.package:$PATH_Aとは無関係使用中-rsome.package:$PATH_Bメカニズムの自動生成ファイルは$PATH_A他のすべてのドキュメントは$PATH_Bに関連しています使用中halメカニズムが関連付けられています。したがって、クライアントとサーバーの実装を直接参照しないでください。CPPそれ以外のもの。この要件を満たすには、HIDLと生成された共有ライブラリへのリンクのみを含めます。

パススルーモードでは、コンパイルHIDLファイルの場合、IFoo.h通信ヘッダー以外にヘッダーファイルが使用されますgetService追加のパススルーヘッダーファイルも生成されますregisterAsServiceこのヘッダーは、実行される内容を定義しますregisterForNotifications操作の機能。ストレートスルーのためBinder呼び出されたのと同じプロセスで実行されるため、ほとんどの場合、パススルーメソッドは直接関数呼び出し(同じスレッド)によって呼び出されます。 A HIDLメソッドは待機する必要がないため、独自のスレッドで実行されますIInterface::registerAsServiceメソッドを処理する(つまり、パススルーモードで使用するBinderすべてのメソッドdefaultスレッドにとって安全でなければなりません)。 A HIDLファイルはandroid::hardware::IInterface::getInterfaceVersionに似ていますが、必要な関数は直接呼び出され、使用されませんBinder転送呼び出しBinder。将来HAL実装は、HALなどの複数の実装結果を提供する可能性がありますhwservicemanagerで。この場合、システムは追加の実装結果ごとにファイルを作成します(たとえば、defaultPassthroughServiceImplementationregisterPassthroughServiceImplementation)。

getService文法

getStub ture
  • Interface:完全修飾名
  • registerAsService:生成された言語パックを指定します
  • hwservicemanagerhwservicemanagerファイルパス

ファイルパスマッピング

Binderすべてのファイルは、パッケージのルートディレクトリマッピングとその完全修飾名から見つけることができます。パッケージのルートディレクトリはパラメータ化されていますHIDLフォームはIFooServiceに割り当てられます。例えば:

IFooService foo_service
  • ルートディレクトリパラメータはgetService('foo_service')です。
    意味default対応するディレクトリパスは次のとおりです。
    getService
  • ソフトウェアパッケージはgetService
    インターフェイスファイルを配置する必要があることを示します.halディレクトリパスの下IServiceManager.halインターフェイスstatic ::android::sp getService(const std::string &serviceName='default', bool getStub=false)バージョンの下.halファイル、すなわち:
    .cpp

パッケージパスマッピングは、たとえば、同時に存在する場合は複製しないでくださいgetService getStub Then falseと等しくなければなりませんdefaultServiceManagerこの方法でのみ、一貫したインターフェイスディレクトリを実現できます(これにより、インターフェイスのバージョン管理も容易になります)。

コードファイルの生成

  • 定義trueファイルグループ

    getPassthroughServiceManager hidl_death_recipient
  • ヘッダーファイルを生成する

    libhidl libhidlbase, libhidltransport, libhidlmemory
  • 生成libhidlbaseファイル

    hidl libhidlmemory

memory新しいサービス機能

IMapperサービスはコードで自動的に生成され、libhidltransportなどの各サービスに対応するヘッダーファイルが自動的に追加されます。

IServiceManager.hal libhwbinder
  • libhwbinder:サービスを受ける
  • .hal:登録サービス
  • Binder:登録通知監視イベント、サービス登録が成功した後に通知が送信されます

サービスの登録と取得

サーバー登録hwservicemanagerサービス

hwservicemanagerインターフェースの使用HIDL登録するlibhidlサービスの場合、登録名はインターフェースまたはソフトウェアパッケージ名に関連している必要はありません。名前が指定されていない場合、デフォルトはlibhidlbaseです。 ; libhidlbaseインターフェース呼び出しHidlInternal現在のインターフェースのバージョンを確認できます。

hidl hal

HidlSupportストレートスルー

最初に理解するhidlストレートスルーC++, Java 、参照MQDescriptoサーバー登録方法:サーバーを簡単にロードして送信しますfmq関数を使用してサービスを登録しますStatus登録に来てください:

hidl SynchronizedQueue

以下は、ソースコード分析です。

TaskRunner SynchronizedQueue

libhidlmemory関数では、in libhidlmemory When、パラメータmapping For hidl_memoryストレートスルーでサーバーをロードするストレートスルーサーバーを取得するIMemoryその後、合格libhidlmemoryに向けてsystem/libhidl/transport/memoryサービスに登録します。
サーバーの現在のプロセスをクライアントのサービスプロセスとしてロードすることですtransport/memoryサーバーを見つけて渡すことができますandroid.hidl.*サービスプロセスと通信します。

クライアントがサービスを受ける

system/libhidl/transport/*インターフェースにはバージョンの違いがあるため、各インターフェースファイルは個別で一意であると見なすことができます。したがって、android.hidl.*バージョン1.1およびhidl両方のバージョン2.2をbaseおよび両方のインターフェースでIBase.halこのインターフェースのすべての登録済みサービスを取得できます。したがって、ほとんどの場合、登録または検出サービスは名前パラメーターを提供する必要はありません(つまり、名前はJava Object)。

Ibase.hal hal

クライアントは合格halサーバーを取得し、IBase毎回allocatorファイルがソースコードを自動的に生成すると、関数が自動的に追加されます。関数プロトタイプは次のとおりです(ここではIAllocator.hal例):
AshmemAllocator
ただし、インターフェイスファイルタイプが異なります。すべてmemoryファイルは同じコードを生成し、その実装は対応するIMapper.halファイル内にあります。

IMemory.hal AshmemMapper

IMemory主にパラメーターに基づいていますAshmemMemory値は、サーバーを取得する方法を決定します。

  • For manager時間
    by IServiceManager.halサーバーを取得します。 バウンド
  • For system/libhidl/ServiceManagement.cpp時間
    by libhidltransportサーバーを取得します。 まっすぐ通り抜ける

これら2つの機能について以下に詳しく説明します。

サービス死亡通知

クライアントはサービス終了通知レシーバーを登録する必要があります。サービスが終了すると、クライアントはレシーバーが継承する必要がある通知を受信しますsystem/hwservicemanager/ServiceManager.cppサブクラスと対応するメソッドを実装します。

hwservicemanager token

ソース構造

ソースコードディレクトリのクイックリファレンステーブル

ソースコードのパスは次のとおりです。

ITokenManager.hal hidl

token

主に3つのダイナミックライブラリが含まれています:hwservicemanagerそれらの中でhidl主にAshmem基本的なタイプは関連していますIServiceManagerカプセル化されていますIBase合格system/libhidl/transport/base/1.0/IBase.halマップへhalストレートスルーを含めるJava実現。

Object hidl

hal

対応する世代libhidltransportライブラリ、はいlibhidltransportファイル#include 通信関連ライブラリ。

defaultServiceManager IServiceManager

getPassthroughServiceManager

実行可能ファイルを生成するIServiceManager 、はいServiceManagement.cppバインドされたサービスの大きな家政婦。

fromBinder ProcessState::self()->getContextObject(NULL)

handle目次

IBinderライブラリ

handleライブラリに対応するソースコードリストは次のとおりです。

hwservicemanager hwservicemanager
  • ProcessState, IPCThreadState
    libhwbinder一部の内部で使用されるクラス、文字列定義など。AFramework Binderクライアント/サーバーは使用されません。
  • fromBinder
    HidlBinderSupport.hサポートされている基本データ型(含まれていません)BpHwServiceManagerの種類)。
  • BnHwServiceManager
    クイックメッセージキューIServiceManager関連するタイプ。
  • hwservicemanager
    意味ServiceManager成功、失敗、例外などの通信ステータスと戻り値。
  • PassthroughServiceManager
    キューを同期します。
  • get
    無限にループするタスクのバックグラウンド。openLibsキューを使用してタスクを保存します。

.halライブラリ

IFoo-impl.soライブラリに対応するソースコードリストは次のとおりです。

HAL_LIBRARY_PATH_SYSTEM IFoo-impl.so

有効なドキュメントIFoo.hal”、対応するヘッダーファイル:

Foo.cpp HIDL_FETCH_IFoo

関数関数は1つだけ含まれています:openLibsメモリマッピング後、対応するHIDL_FETCH_IFooを返します。new Foo()ライブラリは正しいFooカプセル化、openLibs具体的な実現です。

IFoo-impl.soソフトウェアパッケージ

HIDL_FETCH_IFooディレクトリの下に5つのソフトウェアパッケージがあります。Foo最初はPassthrough HAL基本的なソフトウェアパッケージです:

  • Treble
    定義HALその機能は似ていますHIDLつまりHALすべてですdlopenファイルの親クラス。各libhwbinderファイルはソースコードが自動的に生成されるときに自動的に追加されますlibhwbinderの関数とそのデフォルトの実装。
  • hwbinder
    メモリ割り当てインターフェイスを定義しますFramework Binderメモリ割り当ての具体的な実装はlibhwbinderです。 。
  • Framework Binder
    メモリマップドインターフェイスを定義しますBp, Bn Binderおよびメモリインターフェイス/dev/hwbinderメモリマッピングの特定の実装はhwBinderメモリブロックBpHwRefBase特定の実装はmRemote
  • BpHwBinder
    定義BpHwBinder関連する機能インターフェイスには2つの実装があります。ストレートスルーはin mHandle実装済み、対応BHwBinderライブラリバインディングタイプはin Binder Driver実装済み、対応IBase実行可能ファイル。
  • IBase
    インターフェースを定義しますHIDL可能性がありますBnHwBaseインターフェースの変換_hidl_mImplインターフェースが含まれるプロセス間で転送するのに便利ですHIDLで実現されます。

ProcessState関連するメモリ割り当てとマッピングはすべて匿名の共有メモリメカニズムで使用されますProcessStategetContextObjectサービス管理は、ストレートスルーとバインディングに分けられ、さまざまなファイルに実装されます。

ProcessStateファイルパスは/dev/hwbinderすべてですBinder基本的なインターフェースはsetThreadPoolConfigurationに似ています真ん中mmapカテゴリ理由1MB書き換えやオーバーロードがないため、カスタムgetContextObjectファイル内の関数名を次のものと同じにすることはできません。

getStrongProxyForHandle(0) hwservicemanager

BpHwBinderライブラリ

Bp***Binderライブラリ内のヘッダーファイルhwservicemanagerクライアントが現在バインディングを使用しているか、サーバーを取得するためにストレートスルーを使用しているかを区別するためのいくつかの重要な関数が含まれています。

hwservicemanager HIDL
  • HIDL:結合されたサービス管理init
  • Binder:ストレートスルーサービス管理Framework Binder

それらはすべて含まれていますIInterface実装では、最初にバインディングソースコードを確認します。

IBinder BnBinder, BpBinder

そのコアコードはBnBinderこのテンプレート関数はここで注意が必要ですIInterfaceこのコードの意味は次のとおりです。GetBpBinder 0 is IInterface While BpBinder 0はyesを意味しますBnBinderデーモン、フォローアップBinder Driverプロセス中に詳細に紹介します。ここでFramework Binder待ってください、すべてが入っていますがservice_managerライブラリでは、実際にはIServiceManagerコードの多くは同じであり、実装された関数もほぼ同じです。
service_managerインIServiceManager.cppヘッダーファイルで定義:

service_manager Binder

テンプレートコードは、リモートアクセスの場合、新しく作成されたプロキシオブジェクトはaidl、つまり、クライアントがローカルコールの場合はサーバーのプロキシを保持し、直接IServiceManager.cppに変換されることを示しています。つまり、クライアントはサーバーそのものです。
リモートアクセスの場合、実際のapp投稿者IServiceManager.cpp進行中IServiceManager実現しました。

ストレートスルーのソースコードを見てください。

HIDL IServiceManager

パススルーモードがサーバーを取得すると、サーバーが直接返されますHIDLサーバーを取得するためのオブジェクトIBaseメソッドのソースコードは次のとおりです。

IServiceManager PassthroughServiceManager, ServiceManager

BnHwServiceManager最初に完全修飾名に従ってバージョン番号を解析し、_hidl_mImplインターフェース名、次にその実装ライブラリを見つけますIServiceManagerライブラリ。検索パスはServiceManager待機です。 、それらは次のように定義されます。

BpHwServiceManager BpHwRefBase

つまり、これらのパスmRemoteライブラリファイルを見つかるまで検索します。

BpHwBinder実装ドキュメントBpHwBinder含める必要がありますmHandle関数、これは含まれていますBHwBinderコードはハードコーディングされています。通常はBnHwServiceManager中、Bp**ビルドに来ますBn**オブジェクト。

サーバーをストレートスルーで取得するプロセス:最初のパスBinder実装ライブラリをロードする/dev/hwbinder再度呼び出すhwBinderメソッド、get hwBinderオブジェクト(つまり、サーバー) 。
つまり、ストレートスルーBinderクライアントは、サーバーのコードライブラリを現在のプロセスに直接ロードします。これもBinder Driverアーキテクチャの古いバージョンhwBinder互換性:in BnHw前に、IInterfaceすべてを通してBpHw直接ロードするようになります。

IInterface目次

BpHwライブラリディレクトリは主に実装されていますBnHw通信、その実装方法のほとんどは関連していますBinder Driver中国で一貫しています。参照してください。 Androidバインダーメカニズム
BpHw, BnHwディレクトリのコードは基本的にParcelコードがコピーされ、一部が変更されましたIFooAll.cpp名前とhwservicemanagerドライバファイル。

Framework Binderクラス図の構造

0110-android-hidl-class-uml-hwbinder.png

  • service_manager真ん中HIDL先のとがったServiceManager.cpp
  • ServiceManager真ん中hwservicemanagerを指すハンドルですServiceManagement.cppそれらの間hwservicemanager通信に来てください

ServiceManagementクラス図の構造

0110-android-hidl-class-uml-IBase.png

IServiceManagerすべてですServiceManagementサービスの基本クラスBpHwServiceManager真ん中BnHwServiceManagerポイントhwservicemanagerサービスの具体的な実装クラス。

Binder

ここでの主な紹介rcコンストラクターとhwservicemanager.rcの2つの関数があります

hwservicemanager main

service.cpp次の関数がコンストラクターに実装されています。

  • mainデバイス、ファイルノード、およびmain通信をオンにします
  • 初期構成によって駆動されるスレッドの最大数は0であり、その後にServiceManager変更することができます。
  • hwservicemanagerマップメモリ​​スペース、おそらくmap
TokenManager /dev/hwbinder

BnHwServiceManager関数で呼び出されますServiceManager、ハンドルが0で、ハンドルが0のエージェントに戻ると、家政婦にサービスを提供することを意味しますIServiceManager途中で詳しく説明します。
ハンドルが存在することがわかったら、新しいハンドルを作成しますioctlすべてですhwservicemanager親クラス。

BINDER_SET_CONTEXT_MGRプロセス

hwservicemanagerはいServiceManagerシステム内のすべての管理を担当する大規模なハウスキーパーにサービスを提供ServiceManager登録された製本サービスはmServiceMapによって提供されますプロセスが開始されます。

keyコミュニケーションの基礎知識

最初のレビューmServiceMapコミュニケーションの基本的な知識:

  • package::interface♦サーバーが提供できるサービスを表します
  • root@xxxxx::IServiceManagerクロスプロセス通信を実現するために使用され、mInstanceMapに分割されます

クライアントとサーバーの通信プロセス:

  • サーバーは合格default実現CameraProvider対応する機能
  • クライアントは合格します'legacy/0'転送mServiceMap対応する機能mInstanceMapはいmInstanceMapエージェント、エージェントの実現プロセスは次のとおりですdefault転送

Binder次の2つの重要な概念:

  • ServiceManagerプロセス:登録されたサービスを維持する責任があるのはサービスハウスキーパーです
  • mServiceMapクライアントとサーバーのクエリと登録サービス、それとaddクロスプロセス通信

hwbinderクライアントおよびサービスハウスキーパーとしてregisterAsServiceプロセスの採用IFooAll.cpp他の人とのコミュニケーションに来るregisterAsServiceクライアントとしてのサービスプロセスadd他の人の登録サービスBinderクライアントとしてのプロセスServiceManagerクエリサービス。

mServiceMapクラス図の構造

IServiceManagerクラス図の構造、拡大画像を表示

0110-android-hidl-class-uml-IServiceManager.png

このクラス図は、一般的なgetサービスのクラス構造を反映しています。

  • hwbinder標準と見なすことができますInterface::getServiceデフォルトで継承されるサービスdefaultServiceManager
  • IServiceManager 2つのサービス実装クラスがあります:get
  • mServiceMap中央hardware/interfaces/tests方向HIDL特定の実装クラス。これが特定のBinderです。
  • Binderプロキシクラス、親クラスBinder Driver真ん中kernel先のとがったCONFIG_ANDROID_BINDER_DEVICES='binder,hwbinder,vndbinder'/dev/binder真ん中Framework BinderポイントAIDLハンドル、ここでは実際にはそのサブクラスを参照していますservicemanager
  • /dev/hwbinderHIDL通過HIDLドライバーが通信し、デバイス名hwservicemanager

/dev/vndbinder簡単な説明

AIDL with vndservicemanagerモデルは基本的に同じであり、共有されていますHIDLデバイスのキーワードが異なるだけです。 A /dev/hwbinder途中でサーバーが保持Frameworkそして実現/dev/vndbinderクライアントが保持する特定の機能vendor転送vndservicemanager, servicemanager対応関数、service-manager.cはいAndroid.bpエージェント、経由HIDL連絡に来てください。 A cpp, java通信プロセス(読み取りと書き込み)vts)は自動的に生成されます

1 2 3 4 5 6 7 
で実現されます。
ELUGA_Ray_710:/system/bin # ls *wrapper-* -l lrwxr-xr-x 1 root shell 20 20*:56 ip-wrapper-1.0 -> netutils-wrapper-1.0 lrwxr-xr-x 1 root shell 20 20*:56 ip6tables-wrapper-1.0 -> netutils-wrapper-1.0 lrwxr-xr-x 1 root shell 20 20*:56 iptables-wrapper-1.0 -> netutils-wrapper-1.0 lrwxr-xr-x 1 root shell 20 20*:56 ndc-wrapper-1.0 -> netutils-wrapper-1.0 lrwxr-xr-x 1 root shell 20 20*:56 tc-wrapper-1.0 -> netutils-wrapper-1.0 -rwxr-xr-x 1 root shell 65248 20*:56 netutils-wrapper-1.0 
プロセス機能および
1 
真ん中
domain_auto_trans(VENDOR-DOMAIN-NAME, netutils_wrapper_exec, netutils_wrapper) 
プロセスは同じです
1 
サービスバトラーですが具体的です
c2hal -r android.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport -p root@xxxxx hardware/libhardware/include/hardware/nfc.h 
登録されたサービスを保存するには
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 
所属
ROOT = PACKAGE IMPORTS PREAMBLE { ITEM ITEM ... } // not for types.hal PREAMBLE = interface identifier EXTENDS | PACKAGE IMPORTS ITEM ITEM... // only for types.hal no method definitions ITEM = ANNOTATIONS? oneway? identifier(FIELD, FIELD ...) GENERATES? | struct identifier { SFIELD SFIELD ...} // Note - no forward declarations | union identifier { UFIELD UFIELD ...} | enum identifier: TYPE { ENUM_ENTRY, ENUM_ENTRY ... } // TYPE = enum or scalar | typedef TYPE identifier VERSION = integer.integer PACKAGE = package android.hardware.identifier[.identifier[...]]@VERSION PREAMBLE = interface identifier EXTENDS EXTENDS = | extends import_name // must be interface, not package GENERATES = generates (FIELD, FIELD ...) // allows the Binder interface to be used as a type // (similar to typedef'ing the final identifier) IMPORTS = [empty] | IMPORTS import import_name TYPE = uint8_t | int8_t | uint16_t | int16_t | uint32_t | int32_t | uint64_t | int64_t | float | double | bool | string | identifier // must be defined as a typedef, struct, union, enum or import // including those defined later in the file | memory | pointer | vec | bitfield // TYPE is user-defined enum | fmq_sync | fmq_unsync | TYPE[SIZE] FIELD = TYPE identifier UFIELD = TYPE identifier | struct identifier { FIELD FIELD ...} identifier | union identifier { FIELD FIELD ...} identifier SFIELD = TYPE identifier | struct identifier { FIELD FIELD ...} | union identifier { FIELD FIELD ...} | struct identifier { FIELD FIELD ...} identifier | union identifier { FIELD FIELD ...} identifier SIZE = // Must be greater than zero constexpr ANNOTATIONS = [empty] | ANNOTATIONS ANNOTATION ANNOTATION = | @identifier | @identifier(VALUE) | @identifier(ANNO_ENTRY, ANNO_ENTRY ...) ANNO_ENTRY = identifier=VALUE VALUE = 'any text including ' and other escapes' | constexpr | {VALUE, VALUE ...} // only in annotations ENUM_ENTRY = identifier | identifier = constexpr 
プロセスなので、通信プロセスは、直接関数呼び出しです。
クライアントとサーバーのパス
1 2 3 4 5 6 7 8 
来て
interface IBar extends IFoo { // IFoo is another interface // embedded types struct MyStruct {/*...*/} // interface methods create(int32_t id) generates (MyStruct s) close() } 
通信。 A
1 2 3 
バインディングまたはストレートスルーに従って返されます
import root@xxxxx // Import entire package import root@xxxxx::IQuux // Import interface file and types.hal import root@xxxxx::types // Only import the types defined in types.hal 
特定の実装:バインドされている場合、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 
保留
# Do not change this file except to add new interfaces. Changing # pre-existing interfaces will fail VTS and break framework-only OTAs # HALs released in Android O fc6c***da68 root@xxxxx::IAllocator bdda***0fd9 root@xxxxx::IBase 500e***7567 root@xxxxx::types 4d04***0d3f root@xxxxx::IServiceManager 5055***50fb root@xxxxx::IServiceNotification 2b88***27c8 root@xxxxx::IMapper 4632***a16b root@xxxxx::IMemory 7c9f***4b7c root@xxxxx::ITokenManager # HALs released in Android O-MR1 0b94***4ef6 root@xxxxx::IServiceManager 
(これは
1 2 3 4 5 6 7 8 
エージェントです)、
$ hidl-gen -L hash -r vendor.awesome:vendor/awesome/hardware/interfaces -r android.hardware:hardware/interfaces -r android.hidl:system/libhidl/transport root@xxxxx::types 9626fd18...f9d298a6 root@xxxxx::types $ hidl-gen -L hash -r vendor.awesome:vendor/awesome/hardware/interfaces -r android.hardware:hardware/interfaces -r android.hidl:system/libhidl/transport root@xxxxx::INfc 07ac2dc9...11e3cf57 root@xxxxx::INfc $ hidl-gen -L hash -r vendor.awesome:vendor/awesome/hardware/interfaces -r android.hardware:hardware/interfaces -r android.hidl:system/libhidl/transport root@xxxxx 9626fd18...f9d298a6 root@xxxxx::types 07ac2dc9...11e3cf57 root@xxxxx::INfc f2fe5442...72655de6 root@xxxxx::INfcClientCallback 
パス
1 
通信、クエリ、およびリターンサービスインターフェイスと通信します。

$ hidl-gen -L hash -r vendor.awesome:vendor/awesome/hardware/interfaces -r android.hardware:hardware/interfaces -r android.hidl:system/libhidl/transport root@xxxxx >> vendor/awesome/hardware/interfaces/current.txt 
ファイル

1 2 3 4 5 6 7 8 
ドキュメントの定義
// hardware/interfaces/current.txt c170***2d62f root@xxxxx::ICameraDevice 78e9***44076 root@xxxxx::ICameraDeviceCallback 28f0***44566 root@xxxxx::ICameraDevicePreviewCallback 4db4***352a3 root@xxxxx::types b32f***55918 root@xxxxx::ICameraDevice 63bf***b3b21 root@xxxxx::ICameraDeviceCallback 0fa3***7208e root@xxxxx::ICameraDeviceSession 
プロセスの開始方法:

1 2 
system/libfmq/include/fmq/MessageQueue.h system/libhidl/base/include/hidl/MQDescriptor.h 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 
メソッド

メインプロセスファイルは

// MQDescriptor.h enum MQFlavor : uint32_t { /* * represents the wait-free synchronized flavor of the * FMQ. It is intended to be have a single reader and single writer. * Attempts to overflow/underflow returns a failure. */ kSynchronizedReadWrite = 0x01, /* * represents the flavor of FMQ where writes always succeed. * This flavor allows one writer and many readers. A read operation * can detect an overwrite and reset the read counter. */ kUnsynchronizedWrite = 0x02 } 
です。 、対応する
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 
方法は次のとおりです。

#include using android::hardware::kSynchronizedReadWrite using android::hardware::kUnsynchronizedWrite using android::hardware::MQDescriptorSync using android::hardware::MQDescriptorUnsync using android::hardware::MessageQueue .... // For a synchronized non-blocking FMQ mFmqSynchronized = new (std::nothrow) MessageQueue (kNumElementsInQueue) // For an unsynchronized FMQ that supports blocking mFmqUnsynchronizedBlocking = new (std::nothrow) MessageQueue (kNumElementsInQueue, true /* enable blocking operations */) 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 

├── Android.bp ├── HidlInternal.cpp ├── HidlSupport.cpp ├── include │ └── hidl │ ├── HidlInternal.h │ ├── HidlSupport.h │ ├── MQDescriptor.h │ ├── Status.h │ ├── SynchronizedQueue.h │ └── TaskRunner.h ├── Status.cpp └── TaskRunner.cpp 2 directories, 11 files 
これらの関数は主に次の場所に実装されています。

  • 新規
    1 2 3 4 
    オブジェクトと登録
    struct hidl_death_recipient : public virtual RefBase { virtual void serviceDied(uint64_t cookie, const ::android::wp& who) = 0 } 
    中(登録プロセスは実際には
    1 2 3 4 5 6 7 8 9 
    中に保存されます)
  • 新規
    struct hidl_handle { ... // explicit conversion const native_handle_t *getNativeHandle() const private: ... details::hidl_pointer mHandle __attribute__ ((aligned(8))) } 
    オブジェクトとサービスとして登録
  • ポーリング
    1 2 3 4 5 6 7 8 9 10 11 
    デバイスファイル、イベントの監視
  • 新規
    struct hidl_string { ... const char *c_str() const size_t size() const bool empty() const ... private: details::hidl_pointer mBuffer uint32_t mSize // NOT including the terminating ''. ... } 
    目的と意志
    1 2 3 4 5 6 7 
    入ってくる行為
    struct hidl_memory { ... private: hidl_handle mHandle __attribute__ ((aligned(8))) uint64_t mSize __attribute__ ((aligned(8))) hidl_string mName __attribute__ ((aligned(8))) } 
    実現
  • 1 2 3 4 5 6 7 8 9 10 11 12 13 14 
    ドライバーにメッセージを送信します
    template struct hidl_array { ... private: T mBuffer[elementCount()] } // An array of T's. Assumes that T::operator=(const T &) is defined. template struct hidl_array { ... private: T mBuffer[SIZE1] } 
    処理し、ハンドル0
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 
    でドライバーをサービスハウスキーパーとして登録します(これがハンドル0が取得される理由であり、次のように表されます
    struct hidl_version { ... constexpr uint16_t get_major() const { return mMajor } constexpr uint16_t get_minor() const { return mMinor } private: uint16_t mMajor uint16_t mMinor } inline android::hardware::hidl_version make_hidl_version( uint16_t major, uint16_t minor) { return hidl_version(major,minor) } 

1 2 3 4 5 6 

// 1. Create a new directory root@xxxxx:~/**/hardware/interfaces/tests/$ mkdir -p myintere/1.0 // 2. Create a new .hal file root@xxxxx:~/**/hardware/interfaces/tests/myintere/1.0$ touch IMyCallback.hal IMyIntere.hal // 3. Execute update-makefiles.sh script in the root directory root@xxxxx:~/**/$ ./hardware/interfaces/update-makefiles.sh 
管理サービスの登録とクエリに使用されます
1 2 3 
サーバーの関連情報は完全修飾名で保存されます
system/tools/ ├── aidl └── hidl 
保存。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 
usage: hidl-gen [-p ] -o -L (-r )+ [-t] fqname+ -h: Prints this menu. -L : The following options are available: check : Parses the interface to see if valid but doesn't write any files. c++ : (internal) (deprecated) Generates C++ interface files for talking to HIDL interfaces. c++-headers : (internal) Generates C++ headers for interface files for talking to HIDL interfaces. c++-sources : (internal) Generates C++ sources for interface files for talking to HIDL interfaces. export-header : Generates a header file from @export enumerations to help maintain legacy code. c++-impl : Generates boilerplate implementation of a hidl interface in C++ (for convenience). c++-impl-headers: c++-impl but headers only c++-impl-sources: c++-impl but sources only java : (internal) Generates Java library for talking to HIDL interfaces in Java. java-constants : (internal) Like export-header but for Java (always created by -Lmakefile if @export exists). vts : (internal) Generates vts proto files for use in vtsd. makefile : (internal) Generates makefiles for -Ljava and -Ljava-constants. androidbp : (internal) Generates Soong bp files for -Lc++-headers and -Lc++-sources. androidbp-impl : Generates boilerplate bp files for implementation created with -Lc++-impl. hash : Prints hashes of interface in `current.txt` format to standard out. -o : Location to output files. -p : Android build root, defaults to $ANDROID_BUILD_TOP or pwd. -r : E.g., android.hardware:hardware/interfaces. -t: generate build scripts (Android.bp) for tests. 
  • 1 

    キーワードは完全修飾名です:
    hidl-gen -r vendor.awesome:some/device/independent/path/interfaces root@xxxxx::IFoo 
    次のようになります:
    1 2 3 4 5 6 7 
  • filegroup { name: 'root@xxxxx_hal', srcs: [ 'ICameraProvider.hal', 'ICameraProviderCallback.hal', ], } 

    キーワードはサービス名で、デフォルトは
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 
    サーバーは登録時にサービス名を指定することもできます。たとえば
    // hardware/interfaces/camera/provider/2.4/Android.bp genrule { name: 'root@xxxxx_genc++_headers', tools: ['hidl-gen'], cmd: '$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport root@xxxxx', srcs: [ ':root@xxxxx_hal', // hal file group ], out: [ 'android/hardware/camera/provider/2.4/ICameraProvider.h', 'android/hardware/camera/provider/2.4/IHwCameraProvider.h', 'android/hardware/camera/provider/2.4/BnHwCameraProvider.h', 'android/hardware/camera/provider/2.4/BpHwCameraProvider.h', 'android/hardware/camera/provider/2.4/BsCameraProvider.h', 'android/hardware/camera/provider/2.4/ICameraProviderCallback.h', 'android/hardware/camera/provider/2.4/IHwCameraProviderCallback.h', 'android/hardware/camera/provider/2.4/BnHwCameraProviderCallback.h', 'android/hardware/camera/provider/2.4/BpHwCameraProviderCallback.h', 'android/hardware/camera/provider/2.4/BsCameraProviderCallback.h', ], } 
    中国で登録する場合は、
    1 2 3 4 5 6 7 8 9 10 11 12 13 
    と指定します。 。

最初に完全修飾を使用するため

// hardware/interfaces/camera/provider/2.4/Android.bp genrule { name: 'root@xxxxx_genc++', tools: ['hidl-gen'], cmd: '$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport root@xxxxx', srcs: [ ':root@xxxxx_hal', // hal file group ], out: [ 'android/hardware/camera/provider/2.4/CameraProviderAll.cpp', 'android/hardware/camera/provider/2.4/CameraProviderCallbackAll.cpp', ], } 
フェッチ| _​​ + _ |完全修飾名には、ソフトウェアパッケージ、メジャーバージョン番号とマイナーバージョン番号、およびインターフェイス名が含まれます。完全修飾名は繰り返さないでください。したがって、取得できるのは一意の名前だけです。
1 2 3 4 5 6 7 8 9 
現時点では、サービス名に基づいてサーバーインターフェイスを取得する場合、サービス名はそれほど重要ではありません。したがって、サービス名で使用されるデフォルト名は通常
// Get service static ::android::sp getService( const std::string &serviceName='default', bool getStub=false) // Register service ::android::status_t registerAsService( const std::string &serviceName='default') // Notification after successful service registration static bool registerForNotifications( const std::string &serviceName, const ::android::sp ¬ification) 
です。 。

サービス登録

サーバーは合格

1 2 3 4 5 
登録、最終的には
sp myFoo = new Foo() status_t status = myFoo->registerAsService() // The default value is 'default' sp anotherFoo = new Foo() status_t anotherStatus = anotherFoo->registerAsService('another_foo_service') // display the specified service name 
実装および保存
1 2 
中。
注:
defaultPassthroughServiceImplementation( 'legacy/0', /*maxThreads*/ 6) 
サービスの登録に来てください。はい
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 
サーバーが使用するメカニズムによって内部的に使用されます
// LegacySupport.h namespace android { namespace hardware { /** * Registers passthrough service implementation. */ template __attribute__((warn_unused_result)) status_t registerPassthroughServiceImplementation( std::string name = 'default') { // Straight-through loading server sp service = Interface::getService(name, true /* getStub */) if (service == nullptr) { ALOGE(...) return EXIT_FAILURE } LOG_FATAL_IF(...) // Register service with hwservicemanager status_t status = service->registerAsService(name) if (status == OK) { ALOGI(...) } else { ALOGE(...) } return status } template __attribute__((warn_unused_result)) status_t defaultPassthroughServiceImplementation(std::string name, size_t maxThreads = 1) { configureRpcThreadpool(maxThreads, true) status_t result = registerPassthroughServiceImplementation(name) if (result != OK) { return result } joinRpcThreadpool() return 0 } template __attribute__((warn_unused_result)) status_t defaultPassthroughServiceImplementation(size_t maxThreads = 1) { return defaultPassthroughServiceImplementation( 'default', maxThreads) } 
登録してコードを自動的に生成します
1 2 3 4 5 6 7 8 
進行中
// C++ sp service = V1_1::IFooService::getService() sp alternateService = V1_1::IFooService::getService('another_foo_service') // Java V1_1.IFooService service = V1_1.IFooService.getService(true /* retry */) V1_1.IFooService alternateService = V1_1.IFooService.getService('another', true /* retry */) 
呼び出されたとき
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 
登録を完了するため。

// ServiceManagerAll.cpp ::android::sp IServiceManager::getService( const std::string &serviceName, const bool getStub) { using ::android::hardware::defaultServiceManager using ::android::hardware::getPassthroughServiceManager ... sp iface = nullptr // Get bound IServiceManager const sp sm = defaultServiceManager() if (sm == nullptr) { ALOGE('getService: defaultServiceManager() is null') return nullptr } ... for (int tries = 0 !getStub && (vintfHwbinder || (vintfLegacy && tries == 0)) tries++) { ... // Obtain the server by binding IServiceManager Return ret = sm->get(IServiceManager::descriptor, serviceName) ... sp base = ret ... // Forced conversion to the corresponding type of the server, here IServiceManager as an example Return castRet = IServiceManager::castFrom(base, true /* emitError */) ... iface = castRet ... return iface } if (getStub || vintfPassthru || vintfLegacy) { // Get straight-through IServiceManager const sp pm = getPassthroughServiceManager() if (pm != nullptr) { // Obtain the server through straight-through IServiceManager Return ret = pm->get(IServiceManager::descriptor, serviceName) if (ret.isOk()) { sp baseInterface = ret if (baseInterface != nullptr) { // Forced conversion to the corresponding type of the server, here IServiceManager as an example iface = IServiceManager::castFrom(baseInterface) // If getStub is false in pass-through mode, BsServiceManager is returned if (!getStub || trebleTestingOverride) { iface = new BsServiceManager(iface) } } } } } return iface } 
1 2 3 4 5 6 7 8 9 

登録プロセスは次のとおりです。

  • まず、完全修飾名とサービス名に従ってサービスが存在するかどうかを確認します
  • 存在しない場合は追加して保存し、更新する

サービスのお問い合わせ

問い合わせ

class IMyDeathReceiver : hidl_death_recipient { virtual void serviceDied(uint64_t cookie, wp& service) override { log('RIP service %d!', cookie) // Cookie should be 42 } } .... IMyDeathReceiver deathReceiver = new IMyDeathReceiver() m_importantService->linkToDeath(deathReceiver, 42) 
サービスは最終的には
1 2 3 
で実現されます、つまり
system/libhidl system/libhwbinder system/hwservicemanager 
で検索されます。
注:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 
クエリサービス、はい
libhidl/ ├── base │ ├── Android.bp │ ├── HidlInternal.cpp │ ├── HidlSupport.cpp │ ├── include │ ├── Status.cpp │ └── TaskRunner.cpp ├── libhidlmemory │ ├── Android.bp │ ├── include │ └── mapping.cpp ├── transport │ ├── allocator │ ├── Android.bp │ ├── base │ ├── current.txt │ ├── HidlBinderSupport.cpp │ ├── HidlTransportSupport.cpp │ ├── HidlTransportUtils.cpp │ ├── include │ ├── manager │ ├── memory │ ├── ServiceManagement.cpp │ ├── Static.cpp │ └── token └── ... 
クライアントがインターフェースを渡す必要があるメカニズムによって内部的に使用されます
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 
取得:最初に使用されます
libhwbinder/ ├── Android.bp ├── Binder.cpp ├── BpHwBinder.cpp ├── BufferedTextOutput.cpp ├── Debug.cpp ├── IInterface.cpp ├── include │ └── hwbinder ├── IPCThreadState.cpp ├── MODULE_LICENSE_APACHE2 ├── NOTICE ├── OWNERS ├── Parcel.cpp ├── PREUPLOAD.cfg ├── ProcessState.cpp ├── Static.cpp ├── TextOutput.cpp └── vts ├── OWNERS └── performance 
取得する
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 
次に、
hwservicemanager/ ├── AccessControl.cpp ├── AccessControl.h ├── Android.bp ├── HidlService.cpp ├── HidlService.h ├── hwservicemanager.rc ├── hwservicemanagerTest.cpp ├── MODULE_LICENSE_APACHE2 ├── NOTICE ├── OWNERS ├── service.cpp ├── ServiceManager.cpp ├── ServiceManager.h ├── TokenManager.cpp ├── TokenManager.h ├── Vintf.cpp └── Vintf.h 
メソッドを呼び出します。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 
base/ ├── Android.bp ├── HidlInternal.cpp ├── HidlSupport.cpp ├── include │ └── hidl │ ├── HidlInternal.h │ ├── HidlSupport.h │ ├── MQDescriptor.h │ ├── Status.h │ ├── SynchronizedQueue.h │ └── TaskRunner.h ├── Status.cpp └── TaskRunner.cpp 

クエリプロセスは非常に単純です。from

1 2 3 4 5 6 
完全修飾名とサービス名で検索します。

libhidlmemory/ ├── Android.bp ├── include │ └── hidlmemory │ └── mapping.h └── mapping.cpp 
簡単なものがあります
1 2 3 4 5 6 7 8 9 10 11 12 13 
サービスの例:

// mapping.h namespace android { namespace hardware { /** * Returns the IMemory instance corresponding to a hidl_memory object. * If the shared memory cannot be fetched, this returns nullptr. */ sp mapMemory( const hidl_memory &memory) } // namespace hardware } // namespace android 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 

概要

package root@xxxxx interface IBase { // Test whether the service is running ping() /* * Provides run-time type information for this object. * For example, for the following interface definition: * package root@xxxxx * interface IParent {} * interface IChild extends IParent {} * return:interfaceChain on an IChild object must yield the following * ['root@xxxxx::IChild', * 'root@xxxxx::IParent' * 'root@xxxxx::IBase'] */ interfaceChain() generates (vec descriptors) /* * Provides run-time type information for this object. * For example, for the following interface definition: * package root@xxxxx * interface IParent {} * interface IChild extends IParent {} * Calling interfaceDescriptor on an IChild object must yield * 'root@xxxxx::IChild' * * @return descriptor a descriptor of the run-time type of the * object (the first element of the vector returned by * interfaceChain()) */ interfaceDescriptor() generates (string descriptor) oneway notifySyspropsChanged() linkToDeath(death_recipient recipient, uint64_t cookie) generates (bool success) unlinkToDeath(death_recipient recipient) generates (bool success) oneway setHALInstrumentation() getDebugInfo() generates (DebugInfo info) debug(handle fd, vec options) /* * For example, for the following interface definition: * package root@xxxxx * interface IParent {} * interface IChild extends IParent {} * return:interfaceChain on an IChild object must yield the following * [(hash of IChild.hal), * (hash of IParent.hal) * (hash of IBase.hal)]. * * SHA-256 is used as the hashing algorithm. Each hash has 32 bytes * according to SHA-256 standard. * * @return hashchain a vector of SHA-1 digests */ getHashChain() generates (vec hashchain) } 
総括する

1 2 3 4 5 6 7 
3つのドメインがありますが、それらはすべて共有されています
// ServiceManagement.h // These functions are for internal use by hidl. If you want to get ahold // of an interface, the best way to do this is by calling IFoo::getService() sp defaultServiceManager() sp defaultServiceManager1_1() sp getPassthroughServiceManager() sp getPassthroughServiceManager1_1() 
デバイスファイル名が異なるだけです(
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 
コンパイル構成で設定
// ServiceManagement.cpp sp defaultServiceManager() { return defaultServiceManager1_1() } sp defaultServiceManager1_1() { { AutoMutex _l(details::gDefaultServiceManagerLock) if (details::gDefaultServiceManager != NULL) { return details::gDefaultServiceManager } if (access('/dev/hwbinder', F_OK|R_OK|W_OK) != 0) { // HwBinder not available on this device or not accessible to // this process. return nullptr } waitForHwServiceManager() while (details::gDefaultServiceManager == NULL) { details::gDefaultServiceManager = fromBinder( ProcessState::self()->getContextObject(NULL)) if (details::gDefaultServiceManager == NULL) { LOG(ERROR) << '...' sleep(1) } } } return details::gDefaultServiceManager } 
):

  • 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 

    標準
    // HidlBinderSupport.h template sp fromBinder(const sp& binderIface) { using ::android::hidl::base::V1_0::IBase using ::android::hidl::base::V1_0::BnHwBase if (binderIface.get() == nullptr) { return nullptr } if (binderIface->localBinder() == nullptr) { return new ProxyType(binderIface) } sp base = static_cast(binderIface.get())->getImpl() if (details::canCastInterface(base.get(), IType::descriptor)) { StubType* stub = static_cast(binderIface.get()) return stub->getImpl() } else { return nullptr } } 
    使用
    1 2 3 4 5 6 7 8 9 
    サービスハウスキーパーが対応するインターフェース
    // ServiceManagement.cpp sp getPassthroughServiceManager() { return getPassthroughServiceManager1_1() } sp getPassthroughServiceManager1_1() { static sp manager( new PassthroughServiceManager()) return manager } 
    プロセス。
  • 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 

    struct PassthroughServiceManager : IServiceManager1_1 { static void openLibs( const std::string& fqName, std::function eachLib) { //fqName looks like root@xxxxx::IFoo size_t idx = fqName.find('::') ... std::string packageAndVersion = fqName.substr(0, idx) std::string ifaceName = fqName.substr(idx + strlen('::')) const std::string prefix = packageAndVersion + '-impl' // The hardcode server must include a function starting with HIDL_FETCH_ const std::string sym = 'HIDL_FETCH_' + ifaceName const int dlMode = RTLD_LAZY void *handle = nullptr ... std::vector paths = {HAL_LIBRARY_PATH_ODM, HAL_LIBRARY_PATH_VENDOR, HAL_LIBRARY_PATH_VNDK_SP, HAL_LIBRARY_PATH_SYSTEM} ... for (const std::string& path : paths) { std::vector libs = search(path, prefix, '.so') for (const std::string &lib : libs) { const std::string fullPath = path + lib // Find the library file and return the handle after opening if (path != HAL_LIBRARY_PATH_SYSTEM) { handle = android_load_sphal_library( fullPath.c_str(), dlMode) } else { handle = dlopen(fullPath.c_str(), dlMode) } // If not found, continue to loop if (handle == nullptr) { const char* error = dlerror() LOG(ERROR)... continue } // Call back the incoming function if (!eachLib(handle, lib, sym)) { return } } } } Return get(const hidl_string& fqName, const hidl_string& name) override { sp ret = nullptr openLibs(fqName, [&](void* handle, const std::string &lib, const std::string &sym) { IBase* (*generator)(const char* name) *(void **)(&generator) = dlsym(handle, sym.c_str()) if(!generator) { const char* error = dlerror() LOG(ERROR)... dlclose(handle) return true } ret = (*generator)(name.c_str()) if (ret == nullptr) { dlclose(handle) return true } registerReference(fqName, name) return false }) return ret } ... } 
    サービス関連、使用
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 
    サービスハウスキーパーが対応するインターフェース
    // HidlInternal.h #define HAL_LIBRARY_PATH_SYSTEM_64BIT '/system/lib64/hw/' #define HAL_LIBRARY_PATH_VNDK_SP_64BIT '/system/lib64/vndk-sp/hw/' #define HAL_LIBRARY_PATH_VENDOR_64BIT '/vendor/lib64/hw/' #define HAL_LIBRARY_PATH_ODM_64BIT '/odm/lib64/hw/' #define HAL_LIBRARY_PATH_SYSTEM_32BIT '/system/lib/hw/' #define HAL_LIBRARY_PATH_VNDK_SP_32BIT '/system/lib/vndk-sp/hw/' #define HAL_LIBRARY_PATH_VENDOR_32BIT '/vendor/lib/hw/' #define HAL_LIBRARY_PATH_ODM_32BIT '/odm/lib/hw/' #if defined(__LP64__) #define HAL_LIBRARY_PATH_SYSTEM HAL_LIBRARY_PATH_SYSTEM_64BIT #define HAL_LIBRARY_PATH_VNDK_SP HAL_LIBRARY_PATH_VNDK_SP_64BIT #define HAL_LIBRARY_PATH_VENDOR HAL_LIBRARY_PATH_VENDOR_64BIT #define HAL_LIBRARY_PATH_ODM HAL_LIBRARY_PATH_ODM_64BIT #else #define HAL_LIBRARY_PATH_SYSTEM HAL_LIBRARY_PATH_SYSTEM_32BIT #define HAL_LIBRARY_PATH_VNDK_SP HAL_LIBRARY_PATH_VNDK_SP_32BIT #define HAL_LIBRARY_PATH_VENDOR HAL_LIBRARY_PATH_VENDOR_32BIT #define HAL_LIBRARY_PATH_ODM HAL_LIBRARY_PATH_ODM_32BIT #endif 
    プロセス。
  • 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 

    サプライヤー間のコミュニケーションには、
    // ProcessState.cpp // about 1 M #define BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2) #define DEFAULT_MAX_BINDER_THREADS 0 // The default maximum number of threads is 0 static int open_driver() { // Open the driver file int fd = open('/dev/hwbinder', O_RDWR | O_CLOEXEC) if (fd >= 0) { int vers = 0 status_t result = ioctl(fd, BINDER_VERSION, &vers) ... size_t maxThreads = DEFAULT_MAX_BINDER_THREADS // Set the default maximum number of threads result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads) if (result == -1) { ALOGE('...) } } else { ALOGW(...) } return fd } ProcessState::ProcessState() : mDriverFD(open_driver()) , mVMStart(MAP_FAILED) , ... { if (mDriverFD >= 0) { // mmap the binder, providing a chunk of virtual // address space to receive transactions. // Map memory space mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0) if (mVMStart == MAP_FAILED) { // *sigh* ALOGE('Using /dev/hwbinder failed...
    ') close(mDriverFD) mDriverFD = -1 } } else { ALOGE('...') } } 
    サービスハウスキーパーが対応するインターフェース
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 
    プロセスを使用します。

In

// ProcessState.cpp sp ProcessState::getContextObject(const sp& /*caller*/) { return getStrongProxyForHandle(0) } sp ProcessState::getStrongProxyForHandle(int32_t handle) { sp result AutoMutex _l(mLock) handle_entry* e = lookupHandleLocked(handle) if (e != NULL) { // We need to create a new BpHwBinder if there isn't currently // one, OR we are unable to acquire a weak reference on this // current one. See comment in getWeakProxyForHandle() // for more info about this. IBinder* b = e->binder if (b == NULL || !e->refs->attemptIncWeak(this)) { b = new BpHwBinder(handle) e->binder = b if (b) e->refs = b->getWeakRefs() result = b } else { // This little bit of nastyness is to allow us to add a // primary reference to the remote proxy when this // team doesn't have one but another team is // sending the handle to us. result.force_set(b) e->refs->decWeak(this) } } return result } 
サービスでの使用に加えて
1 2 3 4 5 6 7 8 9 10 11 
service hwservicemanager /system/bin/hwservicemanager user system disabled group system readproc critical onrestart setprop hwservicemanager.ready false onrestart class_restart hal onrestart class_restart early_hal writepid /dev/cpuset/system-background/tasks class animation shutdown critical 
外部通信も同時に使用できます
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 
// service.cpp int main() { configureRpcThreadpool(1, true /* callerWillJoin */) ServiceManager *manager = new ServiceManager() if (!manager->add(serviceName, manager)) { ALOGE('Failed to register hwservicemanager with itself.') } TokenManager *tokenManager = new TokenManager() if (!manager->add(serviceName, tokenManager)) { ALOGE('Failed to register ITokenManager with hwservicemanager.') } sp looper(Looper::prepare(0 /* opts */)) int binder_fd = -1 IPCThreadState::self()->setupPolling(&binder_fd) if (binder_fd flushCommands() sp cb(new BinderCallback) if (looper->addFd(binder_fd, Looper::POLL_CALLBACK, Looper::EVENT_INPUT, cb, nullptr) != 1) { ALOGE('Failed to add hwbinder FD to Looper. Aborting...') return -1 } // Tell IPCThreadState we're the service manager sp service = new BnHwServiceManager(manager) IPCThreadState::self()->setTheContextObject(service) // Then tell binder kernel ioctl(binder_fd, BINDER_SET_CONTEXT_MGR, 0) ... while (true) { looper->pollAll(-1 /* timeoutMillis */) } return 0 } 
通信:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 
struct ServiceManager : public IServiceManager, hidl_death_recipient { //Methods from::android::hidl::manager::V1_0::IServiceManager follow Return get(const hidl_string& fqName, const hidl_string& name) override Return add(const hidl_string& name, const sp& service) override ... using InstanceMap = std::map struct PackageInterfaceMap { ... private: InstanceMap mInstanceMap{} ... } /** * Access to this map doesn't need to be locked, since hwservicemanager * is single-threaded. * * e.x. * mServiceMap['root@xxxxx::IServiceManager']['manager'] * -> HidlService object */ std::map mServiceMap } 

ここで

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 
プロセスに対応するソースコードファイルはすべて
// ServiceManager.cpp Return ServiceManager::add(const hidl_string& name, const sp& service) { ... auto ret = service->interfaceChain( [&](const auto &interfaceChain) { ... for(size_t i = 0 i  setService(service, pid) } ifaceMap.sendPackageRegistrationNotification(fqName, name) } ... }) ... } 
ドキュメントであり、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 
でコンパイルの区別が行われました。

// ServiceManager.cpp Return ServiceManager::get(const hidl_string& fqName, const hidl_string& name) { pid_t pid = IPCThreadState::self()->getCallingPid() if (!mAcl.canGet(fqName, pid)) { return nullptr } auto ifaceIt = mServiceMap.find(fqName) if (ifaceIt == mServiceMap.end()) { return nullptr } const PackageInterfaceMap &ifaceMap = ifaceIt->second const HidlService *hidlService = ifaceMap.lookup(name) if (hidlService == nullptr) { return nullptr } return hidlService->getService() } 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 

ファローアップ

  • tests/ ├── Android.bp ├── bar ├── baz ├── expression ├── extension ├── foo ├── hash ├── inheritance ├── libhwbinder ├── memory ├── msgq ├── multithread ├── myintere └── pointer 
    個別に使用
    1 2 3 4 5 6 7 
    2つの例を実装する
  • // hardware/interfaces camera/provider/2.4/default/service.cpp:32: android::ProcessState::initWithDriver('/dev/vndbinder') cas/1.0/default/service.cpp:37: android::ProcessState::initWithDriver('/dev/vndbinder') drm/1.0/default/service.cpp:38: android::ProcessState::initWithDriver('/dev/vndbinder') gnss/1.0/default/service.cpp:15: android::ProcessState::initWithDriver('/dev/vndbinder') graphics/composer/2.1/default/service.cpp:31: android::ProcessState::initWithDriver('/dev/vndbinder') hal-server/hal-server.cpp:107:android::ProcessState::initWithDriver('/dev/vndbinder') 
    関連