Binder详解

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 文件中定义接口

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

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    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 调用远程方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    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 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// IMyAidlInterface.java
package zy.com.uninstall.aidl;
// Declare any non-default types here with import statements
public 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_systemservice

Binder 通信过程

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

关于 Binder 的资料

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

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

热评文章