Android IPC通讯之Binder机制分析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hexingen/article/details/82964512

优势

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

角色

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

交互过程

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

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

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

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

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();
        }
    };
}

猜你喜欢

转载自blog.csdn.net/hexingen/article/details/82964512