Binder機制在Android系統中地位毋庸置疑,system_server就經過Binder來實現進程間的通訊,從而達到管理、調用一系列系統服務的能力。本文就AIDL來解讀一下Binder機制的。 先了解一下以下幾個概念:java
還有一點須要說明一下:當一個Service向AMS進行註冊時,傳遞的過去的以及保存在AMS中的是一個Binder對象。當Client須要跟Service進行通訊,經過AMS查詢到實際上是一個BinderProxy,由於能夠有多個Client同時跟Service進行通訊。固然若是Service和Client在同一進程,AMS返回的仍是一個Binder對象,畢竟沒有必要進行IPC。在進行IPC時,Binder Drivder會在中間幫忙轉換Binder和BinderProxy。android
仍是按照Android Service詳解(二)的例子來解釋app
如今咱們來看一下系統自動生成的aidl文件具體有些什麼:ide
/* * This file is auto-generated. DO NOT MODIFY. * Original file: /Users/lebens/Development/WorkSpace/jxx_workspace/Server/app/src/main/aidl/jxx/com/server/aidl/IServerServiceInfo.aidl */
package jxx.com.server.aidl;
public interface IServerServiceInfo extends android.os.IInterface {
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements jxx.com.server.aidl.IServerServiceInfo {
private static final java.lang.String DESCRIPTOR = "jxx.com.server.aidl.IServerServiceInfo";
/** Construct the stub at attach it to the interface. */
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/** * Cast an IBinder object into an jxx.com.server.aidl.IServerServiceInfo interface, * generating a proxy if needed. */
public static jxx.com.server.aidl.IServerServiceInfo asInterface(android.os.IBinder obj) {
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof jxx.com.server.aidl.IServerServiceInfo))) {
return ((jxx.com.server.aidl.IServerServiceInfo)iin);
}
return new jxx.com.server.aidl.IServerServiceInfo.Stub.Proxy(obj);
}
@Override public android.os.IBinder asBinder() {
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
java.lang.String descriptor = DESCRIPTOR;
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(descriptor);
return true;
}
case TRANSACTION_getServerInfo:
{
data.enforceInterface(descriptor);
jxx.com.server.aidl.ServerInfo _result = this.getServerInfo();
reply.writeNoException();
if ((_result!=null)) {
reply.writeInt(1);
_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
return true;
}
case TRANSACTION_setServerInfo:
{
data.enforceInterface(descriptor);
jxx.com.server.aidl.ServerInfo _arg0;
if ((0!=data.readInt())) {
_arg0 = jxx.com.server.aidl.ServerInfo.CREATOR.createFromParcel(data);
}
else {
_arg0 = null;
}
this.setServerInfo(_arg0);
reply.writeNoException();
if ((_arg0!=null)) {
reply.writeInt(1);
_arg0.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
return true;
}
default:
{
return super.onTransact(code, data, reply, flags);
}
}
}
private static class Proxy implements jxx.com.server.aidl.IServerServiceInfo {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder() {
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
@Override public jxx.com.server.aidl.ServerInfo getServerInfo() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
jxx.com.server.aidl.ServerInfo _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getServerInfo, _data, _reply, 0);
_reply.readException();
if ((0!=_reply.readInt())) {
_result = jxx.com.server.aidl.ServerInfo.CREATOR.createFromParcel(_reply);
}
else {
_result = null;
}
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override public void setServerInfo(jxx.com.server.aidl.ServerInfo serverinfo) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((serverinfo!=null)) {
_data.writeInt(1);
serverinfo.writeToParcel(_data, 0);
}
else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_setServerInfo, _data, _reply, 0);
_reply.readException();
if ((0!=_reply.readInt())) {
serverinfo.readFromParcel(_reply);
}
}
finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_getServerInfo = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_setServerInfo = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
public jxx.com.server.aidl.ServerInfo getServerInfo() throws android.os.RemoteException;
public void setServerInfo(jxx.com.server.aidl.ServerInfo serverinfo) throws android.os.RemoteException;
}
複製代碼
關於Stub再來看幾點:post
以getServerInfo()爲例來分析一下onTransact傳遞過程。 首先咱們在Proxy的實現是這樣的this
@Override public jxx.com.server.aidl.ServerInfo getServerInfo() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
jxx.com.server.aidl.ServerInfo _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(IServerServiceInfo.Stub.TRANSACTION_getServerInfo, _data, _reply, 0);
_reply.readException();
if ((0!=_reply.readInt())) {
_result = jxx.com.server.aidl.ServerInfo.CREATOR.createFromParcel(_reply);
}
else {
_result = null;
}
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
複製代碼
從上面的分析能夠知道,這裏的mRemote實際上是一個BinderProxy對象,咱們去看一下這個方法spa
/** * Default implementation rewinds the parcels and calls onTransact. On * the remote side, transact calls into the binder to do the IPC. */
public final boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException {
if (false) Log.v("Binder", "Transact: " + code + " to " + this);
if (data != null) {
data.setDataPosition(0);
}
boolean r = onTransact(code, data, reply, flags);
if (reply != null) {
reply.setDataPosition(0);
}
return r;
}
複製代碼
最終調用的是Binder內的onTransact(),也就是Stub的onTransact(),咱們來看一下線程
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
java.lang.String descriptor = DESCRIPTOR;
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(descriptor);
return true;
}
case TRANSACTION_getServerInfo:
{
data.enforceInterface(descriptor);
jxx.com.server.aidl.ServerInfo _result = this.getServerInfo();
reply.writeNoException();
if ((_result!=null)) {
reply.writeInt(1);
_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
return true;
}
case TRANSACTION_setServerInfo:
{
data.enforceInterface(descriptor);
jxx.com.server.aidl.ServerInfo _arg0;
if ((0!=data.readInt())) {
_arg0 = jxx.com.server.aidl.ServerInfo.CREATOR.createFromParcel(data);
}
else {
_arg0 = null;
}
this.setServerInfo(_arg0);
reply.writeNoException();
if ((_arg0!=null)) {
reply.writeInt(1);
_arg0.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
return true;
}
default:
{
return super.onTransact(code, data, reply, flags);
}
}
複製代碼
在內部能夠看到case TRANSACTION_getServerInfo 下的操做其實也是很簡單,就是把Client須要的結果經過reply傳遞迴Client代理
經過上面的代碼分析,AIDL咱們能夠快速實現IPC,咱們來總結一下:code
經過這個例子的分析,其實系統的AMS管理各類系統服務也是一樣的套路,經過2個Binder創建通訊。
還有一點須要注意: Binder或者BinderProxy都是運行在他們本身的Binder池中的,也就是直接經過Binder通訊的話,須要注意線程切換