Android IPC通信之Binder机制分析

优点java

与Linux中的Pipe管道、信号Signal、消息队列Message、共享内存Share Memory、Socket插口等相比较,Binder在进程间传输数据,只须要执行一次拷贝操做。所以它不只提升了效率,并且节省了内存空间。android

角色web

  • Server: 提供服务的进程称为server进程。
  • Client: 使用服务的进程称为client进程。
  • Binder驱动: 提供设备文件/dev/binder与用户空间交互,Client、Server和Service Manager经过open和ioctl文件操做函数与Binder驱动程序进行通讯。Client和Server之间的进程间通讯经过Binder驱动程序间接实现。
  • Service Manager: 一个守护进程,用来管理Server,并向Client提供查询Server接口的能力

交互过程dom

1.Server进程,先经过ServiceManager注册服务,其实是写入Binder驱动和保存到serviceInfo(已经注册的服务列表)。ide

2.Client进程在访问Server服务以前,先经过ServiceManager查询获取到它的一个BinderProxyd对象,而后经过这个Binder代理接口向它发送进程间通信请求,调用transact(),写入相关信息。svg

3.在server进程中,每一个服务都对应一个Binder对象,它经过一个stub来等待Client进程发来进程间通信请求,触发onTransact(),获取到详细数据。函数

Binder机制分析以下:
在这里插入图片描述this

1. ServiceManager类的代理,实现注册和查询服务:代理

接下来查看,如何建立一个SericeManager的代理类,客户端经过该代理类进行通信:指针

查看ServiceManager源码:

public final class ServiceManager {
    
    private static IServiceManager sServiceManager;
    
    private static IServiceManager getIServiceManager() {
      if (sServiceManager != null) {
            return sServiceManager;
        }
        // 获取到代理对象
        sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
       return sServiceManager;
   }
   
}

查看,BinderInternal类

public class BinderInternal {
   //从native获取到对应的指针
   public static final native IBinder getContextObject();
}

查看,ServiceManagerNative源码:

public abstract class ServiceManagerNative extends Binder implements IServiceManager{
   /**
     * Cast a Binder object into a service manager interface, generating
    * a proxy if needed.
     */
    static public IServiceManager asInterface(IBinder obj){
        if (obj == null) {
            return null;
       }
       IServiceManager in =
            (IServiceManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }

        return new ServiceManagerProxy(obj);
    }
   public IBinder asBinder(){
        return this;
    }
}
class ServiceManagerProxy implements IServiceManager {
    private IBinder mRemote;
    public ServiceManagerProxy(IBinder remote) {
        mRemote = remote;
    }

    public IBinder asBinder() {
       return mRemote;
    }
    //......省略部分源码
}

ServiceManagerNative相似服务端的stub类,用于接受到Client端发来的数据,进行操做。

ServiceManagerProxy是客户端的proxy类,经过BinderProxy对象(即mRemote对象)进行远程通信。

Server进程经过ServiceManager进行addService()注册服务或者Client进程经过ServiceManager进行getService(String name) 查询服务等操做,实际上都是经过ServiceManagerProxy中的mRemote跨进程操做的。

这里不介绍Binder驱动,涉及 C++层比较繁琐,相关方面,自行百度理解。

编写常见的AIDL案例,分析Binder机制


编写一个aidl文件:

package com.xingen.remoteservice;

import com.xingen.remoteservice.bean.ProcessBean;

// Declare any non-default types here with import statements

//使用 Android Studio,增量编译几乎会当即生成 Binder 类

//在.aidl文件中定义一些方法
interface CommonAidlInterface {
    /**
     * 获取一个随机数的字符串
     */
    String getRandomNumberStr();
    /**
     * 获取远程服务返回的对象,注意点:须要import导入该对象
     */
    ProcessBean getRemoteServiceObject();

}

生成对应的java:

package com.xingen.remoteservice;
// Declare any non-default types here with import statements
//使用 Android Studio,增量编译几乎会当即生成 Binder 类
//在.aidl文件中定义一些方法

public interface CommonAidlInterface extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements CommonAidlInterface
{
private static final String DESCRIPTOR = "com.xingen.remoteservice.CommonAidlInterface";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
 * Cast an IBinder object into an com.xingen.remoteservice.CommonAidlInterface interface,
 * generating a proxy if needed.
 */
public static CommonAidlInterface asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof CommonAidlInterface))) {
return ((CommonAidlInterface)iin);
}
return new 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
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_getRandomNumberStr:
{
data.enforceInterface(DESCRIPTOR);
String _result = this.getRandomNumberStr();
reply.writeNoException();
reply.writeString(_result);
return true;
}
case TRANSACTION_getRemoteServiceObject:
{
data.enforceInterface(DESCRIPTOR);
com.xingen.remoteservice.bean.ProcessBean _result = this.getRemoteServiceObject();
reply.writeNoException();
if ((_result!=null)) {
reply.writeInt(1);
_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements CommonAidlInterface
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
@Override public String getRandomNumberStr() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getRandomNumberStr, _data, _reply, 0);
_reply.readException();
_result = _reply.readString();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
/**
     * 获取远程服务返回的对象,注意点:须要import导入该对象
     */
@Override public com.xingen.remoteservice.bean.ProcessBean getRemoteServiceObject() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
com.xingen.remoteservice.bean.ProcessBean _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getRemoteServiceObject, _data, _reply, 0);
_reply.readException();
if ((0!=_reply.readInt())) {
_result = com.xingen.remoteservice.bean.ProcessBean.CREATOR.createFromParcel(_reply);
}
else {
_result = null;
}
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_getRandomNumberStr = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_getRemoteServiceObject = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
public String getRandomNumberStr() throws android.os.RemoteException;
/**
     * 获取远程服务返回的对象,注意点:须要import导入该对象
     */
public com.xingen.remoteservice.bean.ProcessBean getRemoteServiceObject() throws android.os.RemoteException;
}

CommonAidlInterface接口

CommonAidlInterface接口是IInteface的子接口,用于Stub类和Proxy的通用父类接口。

Stub类

Stub类是Binder的子类,用于Server进程中,onTransact()方法中接收传递过来的信息。

Proxy类

Proxy中有一个IBinder类型的mRemote对象,它其实是一个BinderProxy对象(经过ServiceManager)。BinderProxy是一个Java服务代理对象,实现了IBinder接口。

2. Client端的Proxy代理(实际包含BinderProxy对象)信息传递:

private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            //Stub.asInterface(service)转成对应的服务接口
            remoteServiceInterface = CommonAidlInterface.Stub.asInterface(iBinder);
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            remoteServiceInterface = null;
        }
    };

绑定Service会返回一个IBinder对象,其实是BinderProxy类,该对象是查询ServiceManager获取到的。

public static CommonAidlInterface asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
//本地进程会走这一步
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof CommonAidlInterface))) {
return ((CommonAidlInterface)iin);
}
//远程进程会返回Proxy
return new Proxy(obj);
}
private static class Proxy implements CommonAidlInterface
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
   mRemote = remote;
}
    
}

Stub.asInterface(iBinder)是将BinderProxy对象封装到一个代理Proxy中,用于更好操做。

跨进程间的传递信息的调用:

remoteServiceInterface.getRemoteServiceObject();

实际上调用的是Proxy中的getRemoteServiceObject():

@Override public com.xingen.remoteservice.bean.ProcessBean getRemoteServiceObject() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
com.xingen.remoteservice.bean.ProcessBean _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getRemoteServiceObject, _data, _reply, 0);
_reply.readException();
if ((0!=_reply.readInt())) {
_result = com.xingen.remoteservice.bean.ProcessBean.CREATOR.createFromParcel(_reply);
}
else {
_result = null;
}
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}

会调用BinderProxy的transact()方法,传入数据和结果的parcel对象,会写入Binder驱动中。

3. Server端的Stub(Binder子类)接受到远程的信息

Binder驱动监听到Client端远程信息,会触发Binder中的onTransact()方法。

@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
switch (code)
case TRANSACTION_getRandomNumberStr:
{
data.enforceInterface(DESCRIPTOR);
//调用该方法
String _result = this.getRandomNumberStr();
reply.writeNoException();
//写入返回结果
reply.writeString(_result);
return true;
}
case TRANSACTION_getRemoteServiceObject:
{
data.enforceInterface(DESCRIPTOR);
com.xingen.remoteservice.bean.ProcessBean _result = this.getRemoteServiceObject();
reply.writeNoException();
if ((_result!=null)) {
reply.writeInt(1);
_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
return true;
}
}
return super.onTransact(code, data, reply, flags);
}

最后,响应到service中的Stub匿名内部类中,调用各类对应的方法。

public class CommonRemoteService extends Service {
    @Override
    public IBinder onBind(Intent intent) {
        Log.i(TAG,TAG+" 被绑定");
        return mBinder;
    }
    
    /**
     * 获取进程信息的对应实体
     * @return
     */
    private ProcessBean getProcessBean(){
        return ProcessUtils.getProcess(this.getApplicationContext(),ProcessUtils.getCurrentProcessId());
    }

    /**
     * 获取一个随机字符串
     * @return
     */
    private  String getRandomUUIDStr(){
        return  UUID.randomUUID().toString();
    }
    /**
     *  建立一个CommonAidlInterface.aidl对应的CommonAidlInterface.java中的Stub接口
     *
     *  用于与远程服务通信,这里是本类(CommonRemoteService)通信
     */
    private final CommonAidlInterface.Stub mBinder=new CommonAidlInterface.Stub() {
        @Override
        public String getRandomNumberStr() throws RemoteException {
            return CommonRemoteService.this.getRandomUUIDStr();
        }
        @Override
        public ProcessBean getRemoteServiceObject() throws RemoteException {
            return CommonRemoteService.this.getProcessBean();
        }
    };
}