Binder底层原理,aidl.java文件分析

本文深入探讨了Android中AIDL的工作原理,详细介绍了Binder机制如何支撑不同进程间通信,包括客户端和服务端的角色定义、Binder驱动的功能及交互流程,并分析了IConnect.aidl编译后的IConnect.java文件。

之前写过aidl在androidstudio中的使用的博客http://blog.youkuaiyun.com/u010800708/article/details/72983482,现在根据之前的例子,探索aidl的原理。

先用一张图

这里写图片描述

在android系统中不同的app拥有不同的进程,每个进程都在各自的内存区域。相互不同通信,这是linux底层决定的。不同的进程之间想要通信,就需要通过Binder。

Binder驱动位于系统的底层,有一块共享内存区域,不同的进程想要相互通信,就需要通过Binder驱动,被访问的进程也就是服务端会在Binder驱动这块共享内存中产生一个引用。
客户端进程会持有同样的引用到这块共享内存中找到这个引用。所有的通信都是在这块共享内存中完成的。

进程A想访问进程B,进程A中aidl文件中的proxy会将数据写到底层Binder驱动里面,然后让Binder驱动里面的c、c++去访问进程B中aidl文件的Stub里面的函数。

进程A中aidl文件中的proxy相当于客户端,进程B中aidl文件中的Stub相当于服务端。

当进程A与进程B已经建立连接了,服务端进程B想要返回数据给进程A,就需要进程B中aidl文件中的proxy去写数据到Binder驱动,由Binder驱动去回调进程A中aidl文件中的Stub

总之就是,利用Stub存根接收Binder底层调用,利用roxy去主动连接Binder引用

这里写图片描述

获取系统服务也是通过IPC

这里写图片描述

现在分析IConnect.aidl,Build->Make Project编译之后会生成IConnect.java文件位于目录

这里写图片描述

打开这个文件

package com.aidl.server;

public interface IConnect extends android.os.IInterface {
    /**
     * Local-side IPC implementation stub class.
     */
    public static abstract class Stub extends android.os.Binder implements com.aidl.server.IConnect {
        private static final java.lang.String DESCRIPTOR = "com.aidl.server.IConnect";

        /**
         * Construct the stub at attach it to the interface.
         */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

        /**
         * Cast an IBinder object into an com.aidl.server.IConnect interface,
         * generating a proxy if needed.
         */
        public static com.aidl.server.IConnect asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.aidl.server.IConnect))) {
                return ((com.aidl.server.IConnect) iin);
            }
            return new com.aidl.server.IConnect.Stub.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_connect: {
                    data.enforceInterface(DESCRIPTOR);
                    java.lang.String _result = this.connect();
                    reply.writeNoException();
                    reply.writeString(_result);
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
        }

        private static class Proxy implements com.aidl.server.IConnect {
            private android.os.IBinder mRemote;

            Proxy(android.os.IBinder remote) {
                mRemote = remote;
            }

            @Override
            public android.os.IBinder asBinder() {
                return mRemote;
            }

            public java.lang.String getInterfaceDescriptor() {
                return DESCRIPTOR;
            }

            @Override
            public java.lang.String connect() throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                java.lang.String _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(Stub.TRANSACTION_connect, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readString();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
        }

        static final int TRANSACTION_connect = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    }

    public java.lang.String connect() throws android.os.RemoteException;
}

这个IConnect.java文件,可以包含两个部分,Stub(存根)、proxy

这里写图片描述

在IConnect.java文件中的
private static final java.lang.String DESCRIPTOR = “com.aidl.server.IConnect”;

这个DESCRIPTOR就是在Binder驱动中存入的aidl引用,是非常重要的

public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

上面的方法的作用是在生成Binder对象的时候把Binder描述DESCRIPTOR和Binder对象绑定起来。

在asInterface(IBinder ibinder)方法中有一处,在本地通过DESCRIPTOR描述查找Binder对象。是考虑到是在同一进程访问,没有跨进程。

android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);

如果是跨进程就  new com.aidl.server.IConnect.Stub.Proxy(obj)
Proxy实际上实现了aidl接口,Proxy implements com.aidl.server.IConnect

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

transact 通过native方法去连接IBinder驱动,根据描述去找到java层的进程B里面的aidl,然后去连接Stub,Stub会回调onTransact方法返回数据
transact告诉进程B要调用connect(),但是函数不能传递进来,所以给aidl接口中的所有方法赋了一个常量值,Binder驱动只要告诉进程B调用哪个常量对应的方法即可。
static final int TRANSACTION_connect = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);

         @Override
        public java.lang.String connect() throws android.os.RemoteException {
            android.os.Parcel _data = android.os.Parcel.obtain();
            android.os.Parcel _reply = android.os.Parcel.obtain();
            java.lang.String _result;
            try {
                //把该aidl引用写入到Binder驱动中
               _data.writeInterfaceToken(DESCRIPTOR);
                //写入数据到Binder驱动,这行执行后,IBiner引用就会连接服务端
                mRemote.transact(Stub.TRANSACTION_connect, _data, _reply, 0);
               //读取异常
                 _reply.readException();
                读取返回的数据,如果接口方法由返回值的话
                _result = _reply.readString();
            } finally {
                _reply.recycle();
                _data.recycle();
            }
            return _result;
        }
    }

执行mRemote.transact(Stub.TRANSACTION_connect, _data, _reply, 0);之后,binder驱动通过IBinder引用找到服务端进程aidl引用,调用服务端aidl对象中的方法,通过onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)回调给客户端。


@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_connect: {

                   //验证DESCRIPTOR是否有错
                    data.enforceInterface(DESCRIPTOR);

                    //调用进程B返回的aidl对象的connect()方法
                    java.lang.String _result = this.connect();

                    reply.writeNoException();

                    //把返回值数据写到reply中
                    reply.writeString(_result);

                    return true;

  }
      }
            return super.onTransact(code, data, reply, flags);
        }

什么时候把AIDL引用写入到Binder驱动的,在构造函数初始化的时候,也会执行父类Binder的构造函数,在父类的构造函数中执行写入。
  public Stub() {
this.attachInterface(this, DESCRIPTOR);
  }
  public Binder(){
       //native方法
       init();

 }
  private native final void init();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值