Binder底层原理,aidl.java文件分析
来源:互联网 发布:python webdriver 编辑:程序博客网 时间:2024/06/02 03:28
之前写过aidl在androidstudio中的使用的博客http://blog.csdn.net/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();
- Binder底层原理,aidl.java文件分析
- AIDL 和binder 原理
- Binder机制原理分析(Java层)
- Android笔记三:Android 接口定义语言 (AIDL)--Binder工作原理分析
- java中的Arrays.asList()底层原理分析
- Android Studio 创建AIDL以及Binder 原理
- Android底层原理之从Binder源码分析Android进程间通信过程
- 使用AIDL分析Binder的工作机制
- Android AIDL和Binder 简单分析
- 通过 AIDL 分析 Binder 的工作机制
- Android aidl 案例分析Binder机制
- 深入分析AIDL原理
- 深入分析AIDL原理
- AIDL原理分析
- 基于binder机制编写aidl接口文件
- Binder AIDL
- Binder&AIDL
- trait底层原理分析
- 7种形式的Android Dialog使用举例
- iptables
- C#中@的用法总结
- hadoop学习4 调测错误备案
- codeforces 814 D An overnight dance in discotheque
- Binder底层原理,aidl.java文件分析
- 欧几里得算法(辗转相除法)证明过程
- PopupWindow+ReycyclerView打造优雅的下拉列表
- spring的xml配置文件读取properties文件中的属性
- 分治法——主定理(Divide and Conquer
- 真正人工智能时代
- 为什么Java中类方法不能访问实例方法
- Ubuntu16.04配置
- 解决“Maven项目中的Dynamic Web Module 3.0 requires Java 1.6 or newer”问题