Binder详解
16lz
2021-01-23
Binder 在 Android 中占有很重要的作用,这里就对 Binder 做个解析,也便于以后复习。
主要从以下几方面分析:
- Android 中的 IPC 机制
- AIDL 的使用及分析
- Binder 通信机制的分析
Android 中的 IPC 机制
Android 是基于 Linux 内核的,所以先看下 Linux 中的 IPC 机制
- 管道
- 信号
- 消息队列
- 信号灯
- 共享内存
- Socket
这个就不详细看了,以后有时间了再研究
Android 的 IPC 机制
- 通过文件共享
- Socket
- Messager
- ContentProvider
- AIDL
其中 Messager,ContentProvider,AIDL 都是基于 Binder,可以看出 Binder 的重要性,理解了 Binder 机制后感觉还是很巧妙的。
AIDL 的使用及分析
AIDL 的使用
- 创建 aidl 文件
- 在 aidl 文件中定义接口
package zy.com.uninstall.aidl;interface IMyAidlInterface { void set(int val); int get();}
- 构建工程生成 Java 文件
- 编写 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; }}
- 使用时在 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_servicemanager.pngBinder 通信过程
这里放一张图说明整个过程
binder_from_java_to_c_to_driver.png关于 Binder 的资料
关于 Binder 的资料有很多,这里放一些个人感觉很好的连接,这些博客资料都比本文写的要好也更详细,但还要写这篇的原因是方便自己以后复习看,个人认为把流程绘制成图更好理解一些,以后有更详细的分析也会加进来。
资料如下:
Binder源码分析
深入理解Binder
Binder机制,从Java到C
红茶一杯话Binder
更多相关文章
- C语言函数以及函数的使用
- Android应用程序键盘(Keyboard)消息处理机制分析(1)
- Android:apk文件结构
- Android Layout文件的属性说明
- Android - Android 的消息机制
- Android开发艺术探索——第二章:IPC机制(上)
- Android学习笔记:Android消息处理机制之Handler介绍
- 在Android中建立Android project没有R.java文件