Binder详解

purplefrog 发布于3年前

Binder 在 Android 中占有很重要的作用,这里就对 Binder 做个解析,也便于以后复习。
主要从以下几方面分析:

  1. Android 中的 IPC 机制

  2. AIDL 的使用及分析

  3. Binder 通信机制的分析

Android 中的 IPC 机制

Android 是基于 Linux 内核的,所以先看下 Linux 中的 IPC 机制

  • 管道

  • 信号

  • 消息队列

  • 信号灯

  • 共享内存

  • Socket
    这个就不详细看了,以后有时间了再研究

Android 的 IPC 机制

  • 通过文件共享

  • Socket

  • Messager

  • ContentProvider

  • AIDL

其中 Messager,ContentProvider,AIDL 都是基于 Binder,可以看出 Binder 的重要性,理解了 Binder 机制后感觉还是很巧妙的。

AIDL 的使用及分析

AIDL 的使用

  1. 创建 aidl 文件

  2. 在 aidl 文件中定义接口

    package zy.com.uninstall.aidl;interface IMyAidlInterface { void set(int val); int get();
    }
  3. 构建工程生成 Java 文件

  4. 编写 Service 并集成 IMyAidlInterface.Stub() 重写接口函数,在 onBind() 中返回

    public class MyServer extends Service { @Nullable
     @Override
     public IBinder onBind(Intent intent) {
         IMyAidlInterface binder = new IMyAidlInterface.Stub() {         @Override
             public void set(int val) throws RemoteException {
    
             }         @Override
             public int get() throws RemoteException {             return 0;
             }
         };     return null;
     }
    }
  5. 使用时在 onServiceConnected() 中获取到 IMyAidlInterface,之后就可以通过 binder 调用远程方法

     private void initService() throws RemoteException {
         ServiceConnection connection = new ServiceConnection() {         @Override
             public void onServiceConnected(ComponentName name, IBinder service) {
                 binder = IMyAidlInterface.Stub.asInterface(service);
             }         @Override
             public void onServiceDisconnected(ComponentName name) {
    
             }
         };
         Intent intent = new Intent(this, MyServer.class);
         bindService(intent, connection, BIND_AUTO_CREATE);
     }

aidl 生成 java 文件的分析

创建 aidl 文件构建工程后,会自动生成下面的 java 文件

// IMyAidlInterface.javapackage zy.com.uninstall.aidl;// Declare any non-default types here with import statementspublic interface IMyAidlInterface extends android.os.IInterface {    /**
     * Local-side IPC implementation stub class.
     */
    // service 方的 Binder
    public static abstract class Stub extends android.os.Binder implements zy.com.uninstall.aidl.IMyAidlInterface {        private static final java.lang.String DESCRIPTOR = "zy.com.uninstall.aidl.IMyAidlInterface";        /**
         * Construct the stub at attach it to the interface.
         */
        public Stub() {            this.attachInterface(this, DESCRIPTOR);
        }        /**
         * Cast an IBinder object into an zy.com.uninstall.aidl.IMyAidlInterface interface,
         * generating a proxy if needed.
         */
        public static zy.com.uninstall.aidl.IMyAidlInterface asInterface(android.os.IBinder obj) {            if ((obj == null)) {                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);            // 如果 client 和 service 是同一个进程,直接返回 Stub 本身
            if (((iin != null) && (iin instanceof zy.com.uninstall.aidl.IMyAidlInterface))) {                return ((zy.com.uninstall.aidl.IMyAidlInterface) iin);
            }            // 如果 client 和 service 不是同一个进程,返回代理类
            return new zy.com.uninstall.aidl.IMyAidlInterface.Stub.Proxy(obj);
        }        @Override
        public android.os.IBinder asBinder() {            return this;
        }        // 通过 Binder 调用服务器进程,会执行这个函数,通过 code 来区分调用的函数
        @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_set: { // 调用 set() 函数
                    data.enforceInterface(DESCRIPTOR);                    int _arg0;
                    _arg0 = data.readInt();                    this.set(_arg0); // 在 service 中实现
                    reply.writeNoException();                    return true;
                }                case TRANSACTION_get: { // 调用 get() 函数
                    data.enforceInterface(DESCRIPTOR);                    int _result = this.get(); // 在 service 中实现
                    reply.writeNoException();
                    reply.writeInt(_result);                    return true;
                }
            }            return super.onTransact(code, data, reply, flags);
        }        // Binder 的代理类,如果 client 和 service 不是同一个进程就会给 client 返回这个代理类
        private static class Proxy implements zy.com.uninstall.aidl.IMyAidlInterface {            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 void set(int val) 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.writeInt(val);                    // 调用服务器端的 transact() 函数,最终会调用到上面 Stub 中的 onTransact(),如果 service 端实现的方法耗时比较长,这个地方是会阻塞的
                    mRemote.transact(Stub.TRANSACTION_set, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }            @Override
            public int get() throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();                int _result;                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(Stub.TRANSACTION_get, _data, _reply, 0);                    // 获取到返回参数
                    _reply.readException();
                    _result = _reply.readInt();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }                return _result;
            }
        }        // 对接口中方法的标志
        static final int TRANSACTION_set = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);        static final int TRANSACTION_get = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    }    public void set(int val) throws android.os.RemoteException;    public int get() throws android.os.RemoteException;
}

上述代码在注释中对重要的地方做了解释,整体调用流程就是 service 中实现了 Stub 中的方法,并将 Binder 对象返回给 client,如果 client 和 service 在同一个进程,就返回 Stub 本身,否则返回 Proxy 对象,client 通过 Proxy 对象调用时,最终会调用到 Stub 的 onTransact() 函数,其中用 int 值来区分不同的函数。接下来详细分析下 Binder 的调用过程。

Binder 通信机制的分析

获取系统的 service

以后在写吧

ServiceManager 自身的注册和其他 service 的注册

这里放一张图说明整个过程

 

Binder 通信过程

这里放一张图说明整个过程

关于 Binder 的资料

关于 Binder 的资料有很多,这里放一些个人感觉很好的连接,这些博客资料都比本文写的要好也更详细,但还要写这篇的原因是方便自己以后复习看,个人认为把流程绘制成图更好理解一些,以后有更详细的分析也会加进来。

资料如下:
Binder源码分析
深入理解Binder
Binder机制,从Java到C
红茶一杯话Binder

 

查看原文: Binder详解