从Java层理解Android Binder(一):AIDL

Android Binder是个很复杂的机制,底层是Binder Driver注册了一个模拟硬件为/dev/binder,通过内存复制的方式实现了进程间数据共享,并在这套机制上提供了ServiceManager等实现。

本文不去解读C++的那些实现,而是从Java层分析理解Binder的主要类结构,目的是使读者理解Binder涉及到的类的作用。

本文首先从AIDL涉及到的类讲起,然后参照AIDL来说明ServiceManager的结构,会发现两者是很类似的。

想实现进程通信,我们需要先定义一个aidl文件,比如ITimerServer.aidl,目的是返回服务端时间:    

package cn.techtick.abp.aidl;

interface ITimeServer {
    long getTime();
}

系统会帮助我们生成一个复杂的Java类,首先是ITimeServer自身,这个很容易理解:.

public interface ITimeServer extends android.os.IInterface {

public long getTime() throws android.os.RemoteException;
}

从Java层理解Android Binder(一):AIDL_第1张图片

它继承了IInterface ,这个接口里只有一个asBinder方法,先忽略。

另外生成了IInterface.Stub

public static abstract class Stub extends android.os.Binder implements cn.techtick.abp.aidl.ITimeServer {
}

这个Stub继承自Binder,并实现了我们的业务接口ITimeServer

从Java层理解Android Binder(一):AIDL_第2张图片

Stub一方面实现了我们的业务接口,但它是个抽象类,它没有实现getTime方法;另一方面它继承自Binder,从而具备了进程间通信的能力。

Binder中调用了系统的封装,实现了跨进程通信,详细内容可以先不看。主要关注transact和onTransact方法,可以理解为模版设计模式。transact是骨架,onTransact是算法具体实现。这两个是传输数据用的,先知道这个就够了。

我们需要实现ITimeServer业务接口,比如叫MyServer,那么让它继承ITimeServer.Stub就行。

从Java层理解Android Binder(一):AIDL_第3张图片

到这里就能实现同一个进程内的通信了,使用bindService可以获得MyServer对象。

但是如果是跨进程的话,MyServer对象在另一个进程无法直接访问,这时就需要使用Proxy类。

它同样实现了我们的业务接口,其实是一个比较标准的代理设计模式,属于远程代理。

从Java层理解Android Binder(一):AIDL_第4张图片

Proxy不是抽象类了,它实现了getTime方法,里面会调用到IBinder.transact,再进一步调用到MyServer.getTime。

那么Proxy具体是在哪里使用的呢?我们在客户端bindService时,使用ServiceConnection收到如下回调:

public void onServiceConnected(ComponentName name, IBinder service) {
            mTimeServer = ITimeServer.Stub.asInterface(service);
}
          

这里使用了Stub的asInterface方法,里面会判断,如果是跨进程通信,会使用Stub.Proxy。

整体类图如下:



下一篇分析ServiceManager的代码结构。

你可能感兴趣的:(Android)