Binder は、Android 搭載デバイス上の 2 つのプロセスが通信できるようにするプロセス間通信のシステムです。Binder は、呼び出し元に対して完全に透過的な別のプロセスで関数呼び出しを実行する手段を提供します。
バインダーの用語では、呼び出しプロセスはクライアントとみなされ、そのエンドポイントはバインダー プロキシまたはプロキシと呼ばれます。逆に、呼び出されるプロセスはサーバーと呼ばれ、そのエンドポイントはバインダー ノードまたはノードと呼ばれます。
各ノードは独自のインターフェースを公開して実装できます。また、プロキシを使用することで、クライアントはローカル関数呼び出しのようにノード インターフェースでメソッドを実行できます。次の例は、メソッドが呼び出される様子を示しています。
int result = someNodeInterface.foo(a, b); // someNodeInterface is a proxy object
foo()
を呼び出すクライアントがプロセス A で実行され、foo()
を実装するサーバーがプロセス B で実行されているとします。図 1 は、この呼び出しの実行方法を示しています。
図 1. バインダー呼び出しの実行。
図 1 に示すように、別のプロセスでメソッドを実行するには、次の処理が行われます。
- プロセス A のクライアント コードが、プロセス A のプロキシコードを呼び出します。プロセス A のプロキシコードは、次の項目を含むトランザクションを作成します。
- ノードの識別子
- ノードの
foo()
メソッドの識別子 - 引数
a
とb
のコピーを含むバッファ
- トランザクションがバインダ カーネル ドライバに送信されます。
- バインダー カーネル ドライバは、プロセス B がノードをホストしていると判断します。
- カーネルはトランザクション全体をプロセス B のアドレス空間にコピーします。
- カーネルは、トランザクションを処理するプロセス B のスレッドを見つけ、トランザクションをそのスレッドに渡します。
- スレッドはトランザクションをアンパックし、ノードを見つけて、トランザクションをノード オブジェクトに送信します。
- ノード オブジェクトは、トランザクションから関数識別子を取得し、トランザクション バッファから
a
とb
をアンパックして、a
とb
をローカル変数に保存します。 - ノード オブジェクトは、プロセス B のサーバーコードで
foo(a, b)
を呼び出します。 - 呼び出しの結果は、返信トランザクションで返されます。これは、カーネル ドライバに渡され、プロセス A の呼び出し元プロキシに返されます。
- プロキシは、その結果をプロセス A の呼び出し元に返します。
Binder のユースケース
Binder は、異なるプロセス内のソフトウェア間で通信を行う必要があるさまざまなシナリオで使用できます。次に例を示します。
カメラアプリは、バインダを使用して別のプロセスのカメラサーバーと通信します。カメラ サーバーはバインダを使用して、別のプロセスでカメラ HAL と通信します。
アプリはバインダーを使用して、別のプロセス内のシステム サーバーと通信します。システム サーバーはバインダを使用して他のプロセスの HAL と通信します。
1 つのプロセス内のアプリがバインダーを使用して別のプロセス内の別のアプリと通信します。
アプリのインストール、更新、削除を担当するシステム デーモン(
installd
)は、バインダを使用して Android ランタイム デーモン(「artd」)と通信し、アプリをコンパイルします。