Android 跨进程通信-AIDL中的代理模式之源码分析

Posted 好人静

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 跨进程通信-AIDL中的代理模式之源码分析相关的知识,希望对你有一定的参考价值。

目录

 

前言

一 常见的几个类

1.IBinder

2.Binder

3.BinderProxy

4.AIDL接口

二 AIDL编译后的Java类—应用层跨进程服务的实现

1.接口类

2.内部类Stub

3.Stub.Proxy类

4.Stub.asInterface()

5.Server和Client过程处理

(1)两个过程

(2)小结

6.小结

二 ServiceManager跨进程通信实现

1.ServiceManagerNative—对应应用层的AIDL编译后的Java类

(1)IServiceManager—公共接口

(2)ServiceManagerNative—同Stub

(3)ServiceManagerNative.ServiceManagerProxy—同Stub.Proxy

(4)ServiceManagerNative.asInterface()—同Stub.asInterface()

2.Server和Client过程处理

(1)Server

(2)Client获取Binder驱动,获取对应接口方法的功能

3.与应用层的mRemote的区别

4.Binder.allowBlocking()

5 小结

三 总结


前言

Android 跨进程通信-(七)AIDL中的代理模式之创建AIDL实例只是简单的去创建了一个AIDL实例,那么和我们在前面提到的Client进程和Server进程是怎么借助Binder驱动进行通信的呢?在设计过程中,代理模式又是怎么体现的呢?

一 常见的几个类

先看几个常见的API代表的含义

1.IBinder

接口类,表示一种跨进程通信的能力。

public interface IBinder {
}

2.Binder

Framework层对Kernel的Binder驱动功能的封装。Server进程之所以能够和Client进程进行通信,都是依赖Binder驱动来实现IPC,那么这个Binder类就是在Server进程通过Binder类来访问到Binder驱动。

public class Binder implements IBinder {
    final class BinderProxy implements IBinder {
    }
}

3.BinderProxy

BinderProxy为Binder的内部类。为Server进程的Binder驱动的代理类,供Client进程通过该Binder驱动的代理对象来访问到Binder驱动,实现与Server进程的IPC。在实际IPC的时候,Binder驱动会自动完成两个对象的转换。

Binder和BinderProxy之间的关系如图:

4.AIDL接口

Server进程对Client进程提供哪些功能,是通过AIDL文件体现的。该文件需要自行定义,最终编译工具会将文件转换成一个java文件。

编译工具会将AIDL生成的java文件主要包括下面三部分的内容:

  • (1)Stub:抽象类,继承Binder。具有Binder驱动的功能,用来实现进程与Binder驱动的交互。通常在Server需要继承该Stub,用来完成AIDL接口实现的具体功能。
  • (2)Stub.Proxy:Stub的代理类。用来实现AIDL中的接口方法的RPC。
  • (3)Stub.asInterface():将Client进程接收到Server进程传过来的IBinder对象转换成具有AIDL接口方法功能的对象。根据Client和Server是否在同一进程来返回Stub(同一进程)还是Stub.Proxy(跨进程)的对象。

在Client中会通过传过来的IBinder,实际是是Server进程返回的BinderProxy对象。利用Stub.asInterface在同一个进程会返回就是Server的Stub子类对象;如果不在同一个进程,那么返回的Stub.Proxy,通过Stub.Proxy最终实现RPC。

二 AIDL编译后的Java类—应用层跨进程服务的实现

在应用层创建一个跨进程Service的时候,通常需要定义AIDL文件,该文件经过编译工具会生成一个Java类,是完成Client和Server进程跨进程通信的关键。编译之后的文件位于/app/build/generated/aidl_source_output_dir/debug/out/com/android/pattern/IBaiduPushMessageService.java,现在仅仅以其中一个方法来说明代理模式的体现。

1.接口类

public interface IBaiduPushMessageService extends android.os.IInterface{
  public void setBaiduMessageTitle(java.lang.String msg) throws android.os.RemoteException;
}

 通过编译生成的该Java类,本身是一个接口类,为代理模式的公共接口,为Service提供的功能提供标准接口。

2.内部类Stub

  /** Local-side IPC implementation stub class. */
  public static abstract class Stub extends android.os.Binder implements com.android.pattern.IBaiduPushMessageService{
  }

 该类为抽象类,继承Binder。说明该抽象类就是一个具有Binder驱动功能的Java类,Server进程通过该Stub来向kernel的Binder驱动传递数据。

同时该抽象类实现了代理模式中的公共接口,完成接口对应的具体功能,那么该类就是代理模式的被代理类

  • 小注:其实Stub这个类还是一个适配器模式

一个接口首先被一个抽象类继承,并在此抽象类中实现若干方法,以后的子类直接继承该抽象类,就可以有选择的去实现接口方法。该抽象类被成为适配器类。

遗留问题:确认是不是适配器模式:因为这里抽象类并没有实现任何一个方法,这样子还算是适配器模式吗?

答:这里的确是适配器模式,因为这里的IBaiduPushMessageService继承了IInterface,通过在Stub/StubProxy中实现了部分接口(IInterface中的已经实现),在子类中无需实现,只需要实现未实现的部分(即IBaiduPushMessageService)。

在Android中我觉得更突出的应用是BaseAdapter。这个后面去学习适配器模式的时候,在看看这个是不是适配器模式?(遗留问题:补充链接)

  • 引入一个小问题:抽象类和接口都能实现多态,但这里为什么使用抽象类来实现接口呢?

如果使用普通类来实现接口,需要实现接口中的所有方法;而抽象类来实现接口,可以实现部分或者无需实现接口,当子类在继承抽象类的时候,只需实现未实现的接口方法即可。

  • 抽象类表示一个模版;接口表示一种标准

3.Stub.Proxy类

 private static class Proxy implements com.android.pattern.IBaiduPushMessageService
    {
      private android.os.IBinder mRemote;
      Proxy(android.os.IBinder remote)
      {
        mRemote = remote;
      }
      @Override public void setBaiduMessageTitle(java.lang.String msg) throws android.os.RemoteException
      {
        android.os.Parcel _data = android.os.Parcel.obtain();
        android.os.Parcel _reply = android.os.Parcel.obtain();
        try {
          _data.writeInterfaceToken(DESCRIPTOR);
          _data.writeString(msg);
          boolean _status = mRemote.transact(Stub.TRANSACTION_setBaiduMessageTitle, _data, _reply, 0);
          if (!_status && getDefaultImpl() != null) {
            getDefaultImpl().setBaiduMessageTitle(msg);
            return;
          }
          _reply.readException();
        }
        finally {
          _reply.recycle();
          _data.recycle();
        }
      }
..........
}

该类实现代理模式的公共接口,在调用具体接口功能之前将数据封装到Parcel中,最终通过mRemote.transact() 完成IPC,最终调用到Stub的子类对应的实现功能的方法。所以该类为代理模式的代理类,是对Stub的代理类,对消息进行预处理,然后在将消息传递给被代理类。

编译工具生成的Java类就是在跨进程服务中的代理模式的体现。

4.Stub.asInterface()

在后面的部分中会介绍到Server端通过onBind()返回给Client的是IBinder,其实准确的说是一个BinderProxy对象。Stub提供了asInterface()让IBinder转换成IBaiduPushMessageService。

    public static com.android.pattern.IBaiduPushMessageService asInterface(android.os.IBinder obj)
    {
      if ((obj==null)) {
        return null;
      }
      android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
      if (((iin!=null)&&(iin instanceof com.android.pattern.IBaiduPushMessageService))) {
        return ((com.android.pattern.IBaiduPushMessageService)iin);
      }
      return new com.android.pattern.IBaiduPushMessageService.Stub.Proxy(obj);
    }

该方法主要就是根据Client和Server端是不是在同一进程,来确定返回哪个对象:

  • 如果是同一进程,则直接返回Stub,直接调用Server定义的Stub子类里面的方法来完成功能的调用;
  • 如果是不同进程,则返回Stub.Proxy,跨进程调用Server中定义的Stub子类的方法完成功能的调用,即RPC(远程过程调用)。

所以Stub.Proxy可以认为是一种跨进程的调用接口方法的体现,即RPC;而Stub里面的仅仅是同一进程的调用接口方法的方式。


5.Server和Client过程处理

(1)两个过程

前面只是介绍了每一部分的作用,通常在实现一个跨进程Sercice的时候,通常需要有自定义下面两个过程:

  • 1)在Server端需要继承该Stub,实现接口对应的具体功能,最后通过onBind()将该子类的对象返回给Client端。
public class BaiduPushMessageService extends Service {
    BaiduPushMessageBinder binder;

    @Override
    public void onCreate() {
        super.onCreate();
        binder = new BaiduPushMessageBinder();
    }
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }
    /**
     * 具体服务的功能实现
     */
    public class BaiduPushMessageBinder extends IBaiduPushMessageService.Stub {
        @Override
        public void setBaiduMessageTitle(String msg) throws RemoteException {
            sendMessageToHttpServer(msg);
        }
    .......
    }
}

通过这步操作Server就可以将数据发送到Binder驱动。 

  • 2)Client在ServiceConnection的onServiceConnected()可以获取到该Stub子类的对象,从而获取接口的具体功能。
    ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            baiduPushMessageService = IBaiduPushMessageService.Stub.asInterface(service);
            try {
                String title = baiduPushMessageService.getBaiduMessageTitle();
                refreshBaiduMessage(title, "");
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    .......
    };

详细的代码参见Android 跨进程通信-(七)AIDL中的代理模式之创建AIDL实例

通过这步,Client就会通过onServiceConnected()获取到Server返回的获取到BinderProxy,通过Stub.asInterface()将BinderProxy转换成具体的接口类对象,那么Client就可以调用到对应的方法来实现具体功能。 从IPC的角度来看,Server进程拥有Binder对象,Client进程拥有的BinderProxy对象,两者都是用来向Binder驱动来传递数据。Binder驱动会根据调用情况分别返回对应的Binder还是BinderProxy。

遗留问题:是怎么调用到onServiceConnected()将Server通过onBind()返回的IBinder赋值到onServiceConnected()

(2)小结

简单的总结下这个两端的过程:

  • Server通过onBind()将Stub的继承类返回给Client,Client得到的是BinderProxy对象,Client通过Stub.asInterface()转换成对应的接口类对象;
  • Client会将该BinderProxy对象传入到Stub.Proxy中的mRemote,通过该BinderProxy对象来将数据传递到Binder驱动。

简单的图示如下:

6.小结

AIDL文件最终通过编译工具会生成Java类,用来实现Client和Server的跨进程通信。

  • 1.编译生成的Java类就是一个接口类,定义了代理模式中的公共接口方法
  • 2.内部类Stub为一个Binder驱动类,实现了公共接口,需要在Server继承该抽象类,用来完成接口方法对应的具体功能,为代理模式中的被代理类
  • 3.在Server通过onBind() 将Stub返回给Client,Client得到的其实是BinderProxy,Client和Server都依赖Binder驱动进行通信;
  • 4.Stub.Proxy为Stub的代理类,用来完成在消息传递给Stub的时候,进行消息预处理,实现能够跨进程传递;
  • 5.由于Server返回给Client的为IBinder对象,所以Stub提供Stub.asInterface()将IBinder对象转换成对应具体功能的接口类对象;在这个方法中会根据是否在同一进程来返回Stub还是Stub.Proxy;
  • 6.Client在将IBinder对象转换成对应具体功能的接口类的对象的同时,还会将Server传过来的Stub(BinderProxy)传入到Stub.Proxy中,用来实现RPC。

遗留问题:在应用层创建的Service进程都是在ActivityManagerService中管理。系统Service是有ServiceManager进行管理?需要验证这个理论是正确的吗?如果是需要看下两个是怎么进行管理的。

二 ServiceManager跨进程通信实现

前面的Android 跨进程通信-(二)Binder机制之ServiceManager中也提到了ServiceManager是用来注册和查询服务的。简单的分析一个系统Service是怎么完成注册过程。

ServiceManager单独在一个进程中,WindowManagerService的注册以及启动过程是在system_server进程进行的,这些系统Service在system_server进程的一些线程。所以这里应该就是ServiceManager进程与system_server进程之间的跨进程通信。并且system_server进程属于Client,而ServiceManager进程属于Server。

ServiceManager进程完成系统Service的注册和在应用层实现跨进程Service的过程是一样的,类比二 AIDL编译后的Java类—应用层跨进程服务的实现看下这个ServiceManager是怎么完成这个过程。

1.ServiceManagerNative—对应应用层的AIDL编译后的Java类

ServiceManager只是提供给Client调用的方法的封装,真正的跨进程通信的逻辑对应ServiceManagerNative,该文件位于frameworks/base/core/java/android/os/ServiceManagerNative.java,该ServiceManagerNative的功能功能等同于在应用层的AIDL编译之后的Java类。

(1)IServiceManager—公共接口

public interface IServiceManager extends IInterface{
}

接口类,为代理模式的公共接口。具体位于frameworks/base/core/java/android/os/IServiceManager.java。

(2)ServiceManagerNative—同Stub

public abstract class ServiceManagerNative extends Binder implements IServiceManager{
}

同Stub,ServiceManagerNative也为抽象类,继承了Binder,实现了公共接口。用来实现ServiceManager功能的同进程调用。为代理模式的被代理类

遗留问题1:需要补充具体功能的实现,是怎么调用到native的service_manager.c中的相应功能?

(3)ServiceManagerNative.ServiceManagerProxy—同Stub.Proxy

public abstract class ServiceManagerNative extends Binder implements IServiceManager
{
      .........
class ServiceManagerProxy implements IServiceManager {
    public ServiceManagerProxy(IBinder remote) {
        mRemote = remote;
    }

    public IBinder asBinder() {
        return mRemote;
    }

    public void addService(String name, IBinder service, boolean allowIsolated, int dumpPriority)
            throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IServiceManager.descriptor);
        data.writeString(name);
        data.writeStrongBinder(service);
        data.writeInt(allowIsolated ? 1 : 0);
        data.writeInt(dumpPriority);
        mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
        reply.recycle();
        data.recycle();
    }
    .........
    private IBinder mRemote;
}

同Stub.Proxy。为ServiceManagerNative的代理类,实现通过跨进程来调用到ServiceManager的具体功能,其实就是RPC。为代理模式的代理类

(4)ServiceManagerNative.asInterface()—同Stub.asInterface()

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

当然ServiceManagerNative也提供了asInterface()将IBinder对象转换成IServiceManager对象,供Client来调用。

这个ServiceManagerNative同二 AIDL编译后的Java类—应用层跨进程服务的实现。

2.Server和Client过程处理

同样我们需要找到对应的Server和Client的一个实现过程。

(1)Server

前面在二 AIDL编译后的Java类—应用层跨进程服务的实现的server进程中,通过onBind()将Stub(Binder)返回给Client进程,Client进程得到的是一个BinderProxy。那么对应ServceManager的Stub是怎么返回给Clint的呢?

具体在4.Binder.allowBlocking()已经详细说明,其实就是从Client进程中取得的BinderProxy,就是将在ServiceManager进程对应的BpBinder转换成BinderProxy。

遗留问题:应用层的BpBinder是怎么转换成BinderProxy?

(2)Client获取Binder驱动,获取对应接口方法的功能

在system_server进程启动的过程中,ActivityManagerService等这些系统Service只是运行在system_server进程的一些线程,system_server进程会将各种系统Service通过ServiceManager.addService(),通知ServiceManager进程管理Serivce。

  • 1)在system_server进程调用addService

简单看下WindowManagerService和ActivityManagerService是怎么调用ServiceManager.addService()。

注册在WindowManagerService的代码调用逻辑如下:

           wm = WindowManagerService.main(context, inputManager,
                    mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
                    !mFirstBoot, mOnlyCore, new PhoneWindowManager());
            ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
                    DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);

详细代码路径为frameworks/base/core/java/android/os/SystemServer.java 。

而WindowManagerService继承IWindowManager.Stub,是一个WindowManagerService的功能的具体实现。这个IWindowManager.Stub相对于调用该服务的进程为Server。

在看一个ActivityManagerService。

和WindowManagerService稍微有些区别,在SystemServer中的startBootstrapServices()将ActivityManagerService启动之后,通过调用mActivityManagerService.setSystemProcess()的时候,通过ServiceManager.addService()将该ActivityManagerService添加到ServiceManager中,在ActivityManagerService的简答的代码逻辑如下:

 public void setSystemProcess() {
        try {
            ServiceManager.addService(Context.ACTIVITY_SERVICE, this, /* allowIsolated= */ true,DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PROTO);
    .......
}

详细代码路径为frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java。

ActivityManagerService本身继承IActivityManager.Stub,为ActivityManagerService的功能的具体实现。这个IWindowManager.Stub相对于调用该服务的进程为Server。

  • 2)ServiceManager处理addService逻辑

主要就是调用的ServiceManager.addService()的方法,我们可以看到addService()的时候,不仅需要传入该Service一个字符串的名字,还需要将Service的Stub(遗留问题:将这个信息传入用处是什么?)传入到ServiceManager中。哪个进程调用ServiceManager.addService(),哪个进程相对于ServiceManager进程就是Client,那么现在是system_server进程就是Client,

其中ServiceManager.addService()代码如下:

   public static void addService(String name, IBinder service, boolean allowIsolated,
            int dumpPriority) {
        try {
            getIServiceManager().addService(name, service, allowIsolated, dumpPriority);
        } catch (RemoteException e) {
            Log.e(TAG, "error in addService", e);
        }
    }
     private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }

        // Find the service manager
        sServiceManager = ServiceManagerNative
                .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
        return sServiceManager;
    }

详细代码路径为frameworks/base/core/java/android/os/ServiceManager.java 。

从源码中可以看出和之前在应用层实现一个AIDL服务一样,都是需要通过ServiceManagerNative.asInterface()来返回对应接口类的对象 ,然后通过该对象来实现具体的功能。

所以ServiceManager是对Client调用Server的对应接口方法功能的封装。Client不需要像二 AIDL编译后的Java类—应用层跨进程服务的实现中那样还需要获取到BinderProxy来完成与ServiceManager进程的数据交换(已经在ServiceManager中已经获取封装BinderProxy的过程),只需要调用已经封装的对应方法的代码即可。

但是在传入到Stub.Proxy的mRemote的BinderProxy,相对于应用层的跨进程通信这里有一个区别,见3.与应用层的mRemote的区别

3.与应用层的mRemote的区别

先分别看下应用层和ServiceManager在传入BinderProxy的代码逻辑:

  • (1)应用层

二  AIDL编译后的Java类—应用层跨进程服务的实现中,在Client将Server返回的Stub(即BinderProxy)传入到Stub.Proxy的这个代理类,通过该Stub(即BinderProxy)来最终实现RPC。如图所示:

  • (2)ServiceManager

那么在system_server进程调用ServiceManager.addService()的时候,将Binder.allowBlocking(BinderInternal.getContextObject())返回值传入到Stub.Proxy中,用来实现RPC。那么这个返回值到底是什么呢?

下面就简单分析下这个返回值到底是什么,见4.Binder.allowBlocking()

4.Binder.allowBlocking()

在Binder.allowBlocking()的源码如下:

   public static IBinder allowBlocking(IBinder binder) {
        try {
            if (binder instanceof BinderProxy) {
                ((BinderProxy) binder).mWarnOnBlocking = false;
            } else if (binder != null && binder.getInterfaceDescriptor() != null
                    && binder.queryLocalInterface(binder.getInterfaceDescriptor()) == null) {
                Log.w(TAG, "Unable to allow blocking on interface " + binder);
            }
        } catch (RemoteException ignored) {
        }
        return binder;
    }

里面的逻辑很简单,主要就是BinderInternal.getContextObject() 获取的这个IBinder对象的mWarnOnBlocking的属性复制为false,然后直接返回。并且和在二 AIDL编译后的Java类—应用层跨进程服务的实现中的逻辑一致,Client拥有的是BinderProxy,通过BinderProxy来调用到Binder驱动对应的功能。

那么就看下在BinderInternal.getContextObject()是怎么获取一个BinderProxy对象的。源码如下:

   public static final native IBinder getContextObject();

很显然该方法为一个jni方法,最终调用的是frameworks/base/core/jni/android_util_Binder.cpp中的android_os_BinderInternal_getContextObject()

static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
   sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
    return javaObjectForIBinder(env, b);
}
  • (1) ProcessState::self()

回顾一下:

Android 跨进程通信-(三)Binder机制之Client的2.APP进程初始化章节中知道在APP进程由Zygote进程fork出来之后,最终会调用到app_main.cpp下的onZygoteInit()完成初始化过程。在APP进程初始化的时候就是通过 ProcessState::self()获取到"/dev/binder"的文件描述,完成内存映射,才和Binder驱动进行交互,并且每一个进程只有一个ProcessState对象。这个过程发生在APP进程创建的过程就会实例化该ProcessState对象。

同样system_server进程在初始化过程和APP进程初始化过程一致, 所以在这里在调用这个self()返回的就是之前在system_server进程初始化的过程中已经创建的ProcessState对象。

  • (2)getContextObject()
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
    return getStrongProxyForHandle(0);
}

这里调用的ProcessState中的getContextObject()最终调用的是getStrongProxyForHandle(),注意这里传入的0,即获取的是ServiceManager进程对应的BpBinder,仅贴部分源码如下,具体的详细代码可参见/frameworks/native/libs/binder/ProcessState.cpp:

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
   ......
            b = new BpBinder(handle);
            e->binder = b;
            if (b) e->refs = b->getWeakRefs();
            result = b;
         ......
}

从源码中可以看出返回一个ServiceManager对应的BpBinder给到Binder.allowBlocking(),然后将该对象传入到ServiceManagerNative.ServiceManagerProxy中。所以system_server进程传入的Stub.Proxy为ServiceManager对应的BpBinder,然后封装成Java可以识别的BinderProxy。这个和之前在应用层的逻辑是一致的。

遗留问题:既然这里可以通过getStrongProxyForHandle(0)得到ServceManager进程对应的BpBinder,那么其他应用Service进程的BpBinder又是什么得到,然后转换成BinderProxy返回给Client?或者说应用层的Service是怎么将BpBinder封装成BinderProxy返回给Client?或者说Binder驱动是怎么管理的这些BpBinder?

与在一 常见的几个类中的几个类的关系图如下:

遗留问题:Binder驱动在Server进程的Native的实现,后面研究完了,在补充。

  • (3)return javaObjectForIBinder(env, b)

返回的BpBinder对象,在Framework层是无法直接使用的,最后通过javaObjectForIBinder()将BpBinder转换成BinderProxy。

小结:通过Binder.allowBlocking()将ServiceManager进程对应的BinderProxy传入了Stub.Proxy,用来实现RPC

5 小结

和应用层的Server进程稍微有些区别:

  • system_server进程(Client)通过Binder.allowBlocking()来获取到ServiceMananger对应的BpBinder转换成BinderProxy;
  • system_server进程(Client)将该BinderProxy传入到ServiceManager进程的Stub.Proxy来实现RPC。

简单如图所示:

ServiceManagerNative为ServceManager进程作为Server的跨进程通信的关键。

  • 1.ServceManager类仅仅是对Client来访问Server的一个封装,不需要Client通过asInterface()将BinderProxy转换成IServiceManager接口类对象;
  • 2.IServiceManager同应用层的AIDL编译之后的java文件的接口类,用来制定Server端实现的标准,是代理模式的公共接口
  • 3.ServiceManagerNative同应用层的AIDL编译之后的java文件的Stub,Server进程需要继承(只不过这里对应的ServiceManager进程单独通过Native实现),实现具体的公共接口的功能,是代理模式的被代理类
  • 4.ServiceManagerNative.ServiceManagerNativeStub同应用层的AIDL编译之后的java文件的Stub.Proxy,是ServiceManagerNative代理类,负责与Binder驱动交互,实现RPC,是代理模式的代理类;
  • 5.ServceManager(Client)自己通过Binder.allowBlocking()获取ServceManager进程(Server)对应的BinderProxy;
  • 6.同样ServiceManagerNativeStub代理类也提供asInterface()将BinderProxy转换成IServiceManager接口类对象,调用对应提供的功能。

三 总结

不管是应用层的跨进程Servce还是ServiceManager,在实现Client进程和Server进程的时候都需要包括几部分:

  • 1.一个公共接口:用来制定Server进程需要实现功能的标准;为代理模式的公共接口
  • 2.Stub:一个继承了Binder的抽象类,用来实现Server进程与Binder驱动传递数据;为代理模式的被代理类
  • 3.Stub.Proxy:Stub的代理类,用来实现Client进程跨进程访问Server进程;为代理模式的代理类

Server进程和Client进程都需要通过Binder驱动才能相互传递数据:

  • 1.在Client进程中对应的为BinderProxy,为Binder的内部类,Client需要将BinderProxy传入到Stub.Proxy中,通过该对象来向Binder驱动传递数据;
  • 2.在Server进程中对应的为Binder,Server通过该对象向Binder驱动传递数据;

Binder驱动会自行返回对应的是BinderProxy还是Binder。

在应用层的Client进程中的BidnerProxy是有Service的onBind()返回的;而作为ServiceManager进程的Client的system_server进程是有Binder.allowBlocking()通过将ServiceManager对应的BpBinder转换成的BinderProxy。


system_server进程在Zygote进程fork出来的,然后会调用的Native的onZygoteInit()完成初始化过程。这个过程中会通过ProcessState:self()获取一个Binder驱动设备文件"/dev/binder"的文件描述符,才可以与Binder驱动进行交互,并完成内存映射。这个ProcessState在每个进程中为单例。


大胆的总结:在应用层要想实现两个进程之间的数据交换,我觉得只要具有这些要素就可以完成相关的操作,不限于在Service中,但是之所以使用Service,因为Service可以独立于Activity运行。后面添加一个例子尝试下

经过这个过程的梳理学习,发现有抛出了好多遗留问题,现在在看一部分的内容,比前段时间容易多了,好多地方逐渐的通了,后面继续学习,加油。这篇也主要总结的是代理模式的体现,那对于Client拿到的BinderProxy,Server拿到的Binder,到底又怎么调用到最底层的Binder驱动呢?后面在逐渐去研究。

 

以上是关于Android 跨进程通信-AIDL中的代理模式之源码分析的主要内容,如果未能解决你的问题,请参考以下文章

Android跨进程通信AIDL服务

Android跨进程通信Binder机制与AIDL实例

Android跨进程通信Binder机制与AIDL实例

Android跨进程通信——AIDL原理解析

Android AIDL 跨进程通信超详版

Android跨进程通信AIDL和messenger详解