Binder在Java层的实现

2022-08-01,

通过Binder在native的实现可以知道Binder通信的本质就是通过Binder共享内存进行跨进程通信,所以Java层还是利用这个进行通信的,只是Client和Server内部的一些执行逻辑有变化,我们直接来看Java层是如何与Binder通信的就可以了。

 

Java系统服务的创建过程

 

Java系统服务在Android启动过程中由ServiceThread启动,以power系统服务为例,PowerManagerService继承自Stub类,Stub是定义在IPowerManager接口内部的抽象类,Stub继承自Binder类并实现了IPowerManager的接口,这样在创建PowerManagerServier的时候就会调用Binder的构造方法,虽然这是Java层的Binder,但是从名字就知道跟Binder驱动通信就是它做的。

、上图是从Java的PowerManagerService到Native的BBinder的引用过程,这里看一下native的JavaBBinder,看名字就知道它和BBinder还有Java有关,它继承BBinder,通过BBinder就能跟Binder驱动通信,它里面还保存的Java层Binder的引用,这里Java层Binder的实例是PowerManagerService。在native层,与Binder通信还是BBinder做的,JavaBBinder就是一个具备与java层通信能力的BBinder,在Java层是由Binder和Native的JavaBBinder进行通信,我们的服务继承了Binder,也继承了与JavaBBinder通信的能力,这样就通过Native的JavaBBinder和Java的Binder将服务与Binder关联了起来。

 

注册到ServiceManager

 

服务创建完就要注册到ServiceManager,在Native的Binder中是用一个持有BpBinder(0)引用的BpServiceManager做的,Java其实也是用的BpBinder(0),但是使用方式和Native层肯定是有区别的,这里是将Native的BpBinder(0)存入Java层BinderProxy对象中,然后将BinderProxy存入ServiceManagerProxy中, ServiceManagerProxy实现了IServiceManager接口,可以当做ServiceManager使用,并且持有BinderProxy,可以和Binder通信。因为通信的远离在Native中都已经知道了,我觉得了解一下各个模块层级的引用关系就知道整个架构了,如果对细节深究看源码就可以了。

addService也是通过BpBinder(0)与ServiceManager通信的。

 

Client获取服务代理

 

在Service注册的时候知道java层与Binder通信是BinderProxy做的,那么Client获取服务代理也就是通过ServiceManager的BinderProxy,这里得到服务的BinderProxy后需要将其封装成接口给Client使用,这里和ServiceManager是有区别的。

从图上看,整体结构关系都是一样的,只是普通服务的Proxy不像ServiceManagerProxy那样拥有姓名,名字都是Proxy,只是不同服务的Proxy是定义在在不同服务的内部类Stub中的,同时IPowerManager是不会公开在SDK中的,最终Client得到的是PowerManager,它通过IPowerManager来实现与PowerService通信。

将上面的两张图合在一起就是整体的通信过程。

如果了解了Binder的通信的实现原理,在通过这张图了解引用关系,就很容易理解Java层是如何利用Binder进行跨进程通信的。

 

AIDL

Android提供了AIDL(Android Interfce Definition Language)来定义C/S体系中的接口,当我们定义好AIDL接口后,AIDL工具会根据这个接口给我们自动创建好对应的Java文件。

以IPowerManager.aidl为例:

interface IPowerManager{
      boolean isScreenOn();
}

AIDL工具会将其转化为IPowerManager.java:

public interface IPowerManager extends android.os.IInterface{
          
           public static abstract class Stub extends android.os.Binder   implements android.os.IPowerManager{

                      public static android.os.IPowerManager asInterface(android.os.IBinder obj){
                                ........
                                return new android.os.IPowerManager.Stub.Proxy(obj);
                       }

                       public boolean  onTransact(int code,android.os.Parcel data,android.os.Parcel reply,int flags){
                                  switch(code){
                                            case TRANSACTION_isScreenOn:{
                                                    boolean _result = this.isScreenOn();
                                                    reply.writeInt(result);
                                            }
                                  }
                       }

                       private static class Proxy implements android.os.IPowerManager{
                                   private android.os.IBinder mRemote;//BinderProxy
                                   public boolean isScreenOn{
                                           mRemote.transact(Stub.TRANSACTION_isScreenOn,data,reply,0);
                                           return reply.readInt();
                                   }
                       }
           }

}

上面的Java文件省略了很多内容,我们可以看到会帮我们创建Stub和Proxy,在Stub的asInterface中返回Proxy,在Proxy中调用BinderProxy通信并返回结果,Server端只要继承Stub,实现IPowerManager中定义的方法即可。

 

本文地址:https://blog.csdn.net/wjtzc1990/article/details/107421944

《Binder在Java层的实现.doc》

下载本文的Word格式文档,以方便收藏与打印。