Java Binder 之 BinderProxy

BinderProxy是Native IBinder对象的Java代理。由native javaObjectforIBinder函数分配和构造。不允许直接从Java代码侧分配。

native层部分可查阅android_util_Binder.cpp。

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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
// frameworks/base/core/java/android/os/BinderProxy.java
public final class BinderProxy implements IBinder {
// 创建binder时默认的进程范围值。
volatile boolean mWarnOnBlocking = Binder.sWarnOnBlocking;
private static volatile Binder.ProxyTransactListener sTransactListener = null;
public static void setTransactListener(@Nullable Binder.ProxyTransactListener listener) {
sTransactListener = listener;
}
// 从longs映射到BinderProxy,仅保留对BinderProxies的弱引用。
// 需要在访问过程中延迟删除WeakReferences,以避免积累WeakReference对象垃圾。WeakHashMap很难使用,需要weak values而不是keys。
// 哈希表不会调整大小,但是条目的数量是无限的。随着MAIN_INDEX_SIZE的显着增加,性能会有所下降。
// 它不是线程安全的。客户端需要确保一次只有一个有访问权限。
private static final class ProxyMap {
private static final int LOG_MAIN_INDEX_SIZE = 8;
// 1左移8位即100000000(256)
private static final int MAIN_INDEX_SIZE = 1 << LOG_MAIN_INDEX_SIZE;
// 256-1=255
private static final int MAIN_INDEX_MASK = MAIN_INDEX_SIZE - 1;
// 如果映射条目的数量超过以下数量,则debug版本将抛出AssertionError。
private static final int CRASH_AT_SIZE = 20_000;
// 当超过此bucket大小时会发出警告。
private int mWarnBucketSize = 20;
// 每次警告时会将mWarnBucketSize增大10。
private static final int WARN_INCREMENT = 10;
// 专门针对native指针的哈希函数。返回值小于MAIN_INDEX_SIZE。
private static int hash(long arg) {
return ((int) ((arg >> 2) ^ (arg >> (2 + LOG_MAIN_INDEX_SIZE)))) & MAIN_INDEX_MASK;
}
// 返回映射对的总数。
private int size() {
int size = 0;
for (ArrayList<WeakReference<BinderProxy>> a : mMainIndexValues) {
if (a != null) {
size += a.size();
}
}
return size;
}
// 返回包含尚未清除的值的映射对的总数
private int unclearedSize() {
int size = 0;
for (ArrayList<WeakReference<BinderProxy>> a : mMainIndexValues) {
if (a != null) {
for (WeakReference<BinderProxy> ref : a) {
if (ref.get() != null) {
++size;
}
}
}
}
return size;
}
// 从哈希bucket中删除第ith个条目。
private void remove(int hash, int index) {
Long[] keyArray = mMainIndexKeys[hash];
ArrayList<WeakReference<BinderProxy>> valueArray = mMainIndexValues[hash];
// KeyArray中可能包含其它元素。
int size = valueArray.size();
// 将最后一个条目移到空slot中,并在最后截断。
if (index != size - 1) {
keyArray[index] = keyArray[size - 1];
valueArray.set(index, valueArray.get(size - 1));
}
valueArray.remove(size - 1);
}
// 查找有用的key。若有未清除的条目,需返回它。
BinderProxy get(long key) {
int myHash = hash(key);
Long[] keyArray = mMainIndexKeys[myHash];
if (keyArray == null) {
return null;
}
ArrayList<WeakReference<BinderProxy>> valueArray = mMainIndexValues[myHash];
int bucketSize = valueArray.size();
for (int i = 0; i < bucketSize; ++i) {
long foundKey = keyArray[i];
if (key == foundKey) {
WeakReference<BinderProxy> wr = valueArray.get(i);
BinderProxy bp = wr.get();
if (bp != null) {
return bp;
} else {
remove(myHash, i);
return null;
}
}
}
return null;
}
// 用于生成“随机”索引的计数器。
private int mRandom;
// 向映射中添加键值对。当之前映射中不包含该键值对时。
void set(long key, @NonNull BinderProxy value) {
int myHash = hash(key);
ArrayList<WeakReference<BinderProxy>> valueArray = mMainIndexValues[myHash];
if (valueArray == null) {
valueArray = mMainIndexValues[myHash] = new ArrayList<>();
mMainIndexKeys[myHash] = new Long[1];
}
int size = valueArray.size();
WeakReference<BinderProxy> newWr = new WeakReference<>(value);
// 首先要找出被删除的引用。这样可以确保ArrayList的大小受该bucket的最大占用量限制。
for (int i = 0; i < size; ++i) {
if (valueArray.get(i).get() == null) {
valueArray.set(i, newWr);
Long[] keyArray = mMainIndexKeys[myHash];
keyArray[i] = key;
if (i < size - 1) {
// “随机”检查[i+1,size)中的其余条目,以便最终移除不需要的long bucket。
int rnd = Math.floorMod(++mRandom, size - (i + 1));
if (valueArray.get(i + 1 + rnd).get() == null) {
remove(myHash, i + 1 + rnd);
}
}
return;
}
}
valueArray.add(size, newWr);
Long[] keyArray = mMainIndexKeys[myHash];
if (keyArray.length == size) {
// 因为一开始会分配一个元素,所以size需要大于1。
Long[] newArray = new Long[size + size / 2 + 2];
System.arraycopy(keyArray, 0, newArray, 0, size);
newArray[size] = key;
mMainIndexKeys[myHash] = newArray;
} else {
keyArray[size] = key;
}
if (size >= mWarnBucketSize) {
final int totalSize = size();
Log.v(Binder.TAG, "BinderProxy map growth! bucket size = " + size
+ " total = " + totalSize);
mWarnBucketSize += WARN_INCREMENT;
if (Build.IS_DEBUGGABLE && totalSize >= CRASH_AT_SIZE) {
// 使用未清除的条目数来确定是否应该真正报告histogram和crash。不想修改调试进程的行为,因此仅当崩溃时才使用GC。
final int totalUnclearedSize = unclearedSize();
if (totalUnclearedSize >= CRASH_AT_SIZE) {
dumpProxyInterfaceCounts();
dumpPerUidProxyCounts();
Runtime.getRuntime().gc();
throw new AssertionError("Binder ProxyMap has too many entries: "
+ totalSize + " (total), " + totalUnclearedSize + " (uncleared), "
+ unclearedSize() + " (uncleared after GC). BinderProxy leak?");
} else if (totalSize > 3 * totalUnclearedSize / 2) {
Log.v(Binder.TAG, "BinderProxy map has many cleared entries: "
+ (totalSize - totalUnclearedSize) + " of " + totalSize
+ " are cleared");
}
}
}
}
private InterfaceCount[] getSortedInterfaceCounts(int maxToReturn) {
if (maxToReturn < 0) {
throw new IllegalArgumentException("negative interface count");
}
Map<String, Integer> counts = new HashMap<>();
final ArrayList<WeakReference<BinderProxy>> proxiesToQuery =
new ArrayList<WeakReference<BinderProxy>>();
synchronized (sProxyMap) {
for (ArrayList<WeakReference<BinderProxy>> a : mMainIndexValues) {
if (a != null) {
proxiesToQuery.addAll(a);
}
}
}
for (WeakReference<BinderProxy> weakRef : proxiesToQuery) {
BinderProxy bp = weakRef.get();
String key;
if (bp == null) {
key = "<cleared weak-ref>";
} else {
try {
key = bp.getInterfaceDescriptor();
if ((key == null || key.isEmpty()) && !bp.isBinderAlive()) {
key = "<proxy to dead node>";
}
} catch (Throwable t) {
key = "<exception during getDescriptor>";
}
}
Integer i = counts.get(key);
if (i == null) {
counts.put(key, 1);
} else {
counts.put(key, i + 1);
}
}
Map.Entry<String, Integer>[] sorted = counts.entrySet().toArray(
new Map.Entry[counts.size()]);
Arrays.sort(sorted, (Map.Entry<String, Integer> a, Map.Entry<String, Integer> b)
-> b.getValue().compareTo(a.getValue()));
int returnCount = Math.min(maxToReturn, sorted.length);
InterfaceCount[] ifaceCounts = new InterfaceCount[returnCount];
for (int i = 0; i < returnCount; i++) {
ifaceCounts[i] = new InterfaceCount(sorted[i].getKey(), sorted[i].getValue());
}
return ifaceCounts;
}
// dump事务的最大数目是10。
static final int MAX_NUM_INTERFACES_TO_DUMP = 10;
// 将histogram dump到logcat。用于分析大的代理映射异常。
private void dumpProxyInterfaceCounts() {
final InterfaceCount[] sorted = getSortedInterfaceCounts(MAX_NUM_INTERFACES_TO_DUMP);
Log.v(Binder.TAG, "BinderProxy descriptor histogram "
+ "(top " + Integer.toString(MAX_NUM_INTERFACES_TO_DUMP) + "):");
for (int i = 0; i < sorted.length; i++) {
Log.v(Binder.TAG, " #" + (i + 1) + ": " + sorted[i]);
}
}
// 将每个uid的binder代理数dump到locat。
private void dumpPerUidProxyCounts() {
SparseIntArray counts = BinderInternal.nGetBinderProxyPerUidCounts();
if (counts.size() == 0) return;
Log.d(Binder.TAG, "Per Uid Binder Proxy Counts:");
for (int i = 0; i < counts.size(); i++) {
final int uid = counts.keyAt(i);
final int binderCount = counts.valueAt(i);
Log.d(Binder.TAG, "UID : " + uid + " count = " + binderCount);
}
}
// 以下两个数组中的对应ArrayList始终具有相同的大小。
// 它们不包含任何空条目。但是值ArrayLists中的WeakReferences可能已清除。mMainIndexKeys[i][j]对应于mMainIndexValues[i].get(j)。
// 值ArrayList具有适当的size(),相应的键数组始终至少相同,但可能更大。如果特定的键数组或对应的值ArrayList为null,则它们都是。
private final Long[][] mMainIndexKeys = new Long[MAIN_INDEX_SIZE][];
private final ArrayList<WeakReference<BinderProxy>>[] mMainIndexValues =
new ArrayList[MAIN_INDEX_SIZE];
}
@GuardedBy("sProxyMap")
private static final ProxyMap sProxyMap = new ProxyMap();
// 在进程中,用于存储binder代理接口数量的简单对值类。
public static final class InterfaceCount {
private final String mInterfaceName;
private final int mCount;
InterfaceCount(String interfaceName, int count) {
mInterfaceName = interfaceName;
mCount = count;
}
@Override
public String toString() {
return mInterfaceName + " x" + Integer.toString(mCount);
}
}
// 获取一个排序后的数组,其中包含将代理接口名称映射到具有这些名称的实时代理数量的条目。
// 参数num:返回的最大代理接口数。使用Integer.MAX_VALUE检索。
public static InterfaceCount[] getSortedInterfaceCounts(int num) {
return sProxyMap.getSortedInterfaceCounts(num);
}
// 返回进程中binder代理数。
public static int getProxyCount() {
synchronized (sProxyMap) {
return sProxyMap.size();
}
}
// dump代理的debug信息。
public static void dumpProxyDebugInfo() {
if (Build.IS_DEBUGGABLE) {
sProxyMap.dumpProxyInterfaceCounts();
sProxyMap.dumpPerUidProxyCounts();
}
}
// 返回IBinder的BinderProxy。
// 如果先前已为同一iBinder返回了bp,而bp仍在使用中,则将返回相同的bp。
// 第一个参数nativeData:C++指向BinderProxyNativeData的指针(可能仍为空)。取得nativeData的所有权,或异常退出。若两者均不适用,则调用者会回收nativeData。
// 第二个参数iBinder:C++指向IBinder的指针。不拥有引用对象的所有权。
private static BinderProxy getInstance(long nativeData, long iBinder) {
BinderProxy result;
synchronized (sProxyMap) {
try {
result = sProxyMap.get(iBinder);
if (result != null) {
return result;
}
result = new BinderProxy(nativeData);
} catch (Throwable e) {
// 抛出了一个异常(可能是OOME)。不删除nativeData。
NativeAllocationRegistry.applyFreeFunction(NoImagePreloadHolder.sNativeFinalizer,
nativeData);
throw e;
}
NoImagePreloadHolder.sRegistry.registerNativeAllocation(result, nativeData);
// 注册表现在拥有nativeData,即使注册引发异常。
sProxyMap.set(iBinder, result);
}
return result;
}
private BinderProxy(long nativeData) {
mNativeData = nativeData;
}
// 与BinderProxy关联的native内存的测评指标。
// 包括基础的IBinder,关联的DeathRecipientList和指向的KeyedVector。该size可能很高,因为它包含一个可能内存不足的GlobalRef。
private static final int NATIVE_ALLOCATION_SIZE = 1000;
// 使用Holder可以在启动映像中静态初始化BinderProxy,并避免一些初始化顺序问题。
private static class NoImagePreloadHolder {
public static final long sNativeFinalizer = getNativeFinalizer();
public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
BinderProxy.class.getClassLoader(), sNativeFinalizer, NATIVE_ALLOCATION_SIZE);
}
// 如果宿主进程挂掉了则返回false。
public native boolean pingBinder();
// 如果宿主进程挂掉了则返回false。
public native boolean isBinderAlive();
// 查询本地接口-在代理的情况下始终为null。
public IInterface queryLocalInterface(String descriptor) {
return null;
}
// 在代理上执行binder事务。
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
if (mWarnOnBlocking && ((flags & FLAG_ONEWAY) == 0)) {
// 目前,至少在记录一次该接口后,通过禁用该功能来避免向日志发送垃圾邮件。
mWarnOnBlocking = false;
Log.w(Binder.TAG, "Outgoing transactions from this process must be FLAG_ONEWAY",
new Throwable());
}
final boolean tracingEnabled = Binder.isTracingEnabled();
if (tracingEnabled) {
final Throwable tr = new Throwable();
Binder.getTransactionTracker().addTrace(tr);
StackTraceElement stackTraceElement = tr.getStackTrace()[1];
Trace.traceBegin(Trace.TRACE_TAG_ALWAYS,
stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName());
}
// 确保在处理事务时监听器不会变更。
final Binder.ProxyTransactListener transactListener = sTransactListener;
Object session = null;
if (transactListener != null) {
final int origWorkSourceUid = Binder.getCallingWorkSourceUid();
session = transactListener.onTransactStarted(this, code);
// 允许监听器更新工作源的uid。如果uid被更新,需要更新请求头部信息。
final int updatedWorkSourceUid = Binder.getCallingWorkSourceUid();
if (origWorkSourceUid != updatedWorkSourceUid) {
data.replaceCallingWorkSourceUid(updatedWorkSourceUid);
}
}
try {
return transactNative(code, data, reply, flags);
} finally {
if (transactListener != null) {
transactListener.onTransactEnded(session);
}
if (tracingEnabled) {
Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
}
}
}
// 返回native结束函数。
private static native long getNativeFinalizer();
// 获取接口描述符。
public native String getInterfaceDescriptor() throws RemoteException;
// transcact()代理的native实现。
public native boolean transactNative(int code, Parcel data, Parcel reply,
int flags) throws RemoteException;
public native void linkToDeath(DeathRecipient recipient, int flags)
throws RemoteException;
public native boolean unlinkToDeath(DeathRecipient recipient, int flags);
// 在remote对象上执行dump操作。
public void dump(FileDescriptor fd, String[] args) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeFileDescriptor(fd);
data.writeStringArray(args);
try {
transact(DUMP_TRANSACTION, data, reply, 0);
reply.readException();
} finally {
data.recycle();
reply.recycle();
}
}
// 在remote对象上执行异步dump操作。
public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeFileDescriptor(fd);
data.writeStringArray(args);
try {
transact(DUMP_TRANSACTION, data, reply, FLAG_ONEWAY);
} finally {
data.recycle();
reply.recycle();
}
}
// 在这个对象上执行一个shell命令。这可以从调用者异步执行; 完成时,实现必须始终调用resultReceiver。
public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
String[] args, ShellCallback callback,
ResultReceiver resultReceiver) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeFileDescriptor(in);
data.writeFileDescriptor(out);
data.writeFileDescriptor(err);
data.writeStringArray(args);
ShellCallback.writeToParcel(callback, data);
resultReceiver.writeToParcel(data, 0);
try {
transact(SHELL_COMMAND_TRANSACTION, data, reply, 0);
reply.readException();
} finally {
data.recycle();
reply.recycle();
}
}
// 发送java层binder死亡通知。
private static void sendDeathNotice(DeathRecipient recipient) {
if (false) Log.v("JavaBinder", "sendDeathNotice to " + recipient);
try {
recipient.binderDied();
} catch (RuntimeException exc) {
Log.w("BinderNative", "Uncaught exception from death notification",
exc);
}
}
// 指向BinderProxyNativeData的C++指针。它由指向native IBinder对象的强指针和DeathRecipientList组成。
private final long mNativeData;
}