Android的Binder的调用方面

从 Binder 的远程方法调用来看,Proxy 是调用端,Stub 是被调用端。 由 AIDL 的 Interface 实现类,可以看出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public java.util.List<com.leconio.aidlsender.Person> getPersons() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.util.List<com.leconio.aidlsender.Person> _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
boolean _status = mRemote.transact(Stub.TRANSACTION_getPersons, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
return getDefaultImpl().getPersons();
}
_reply.readException();
_result = _reply.createTypedArrayList(com.leconio.aidlsender.Person.CREATOR);
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}

先获取两个 Parcel,一个用于传递数据,一个用于接收数据。每个 Parcel 中都有一个mNativePtr,是个 long 类型,其实他是 JNI 中的 Parcel,由 reinterpret_cast 转换而来。也就是说,Java 层的 Parcel 包裹着 JNI 层的 Parcel。Parcel 是在一个 Parcel 池中获取,这个池大小是 6。
mNativePtr 会在 CPP 代码中 Parcel 初始化的时候被初始化。

1
2
3
4
5
6
static jlong android_os_Parcel_create(JNIEnv* env, jclass clazz)
{
sp<ParcelRef> parcelRef = ParcelRef::create();
parcelRef->incStrong(reinterpret_cast<const void*>(android_os_Parcel_create));
return reinterpret_cast<jlong>(static_cast<Parcel *>(parcelRef.get()));
}

上面代码中mRemote的实现类是 Java 层的ProxyBinder,这个地方就调用到了 ProxyBinder 中的transact

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
...
try {
return transactNative(code, data, reply, flags);
} finally {
AppOpsManager.resumeNotedAppOpsCollection(prevCollection);

if (transactListener != null) {
transactListener.onTransactEnded(session);
}

if (tracingEnabled) {
Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
}
}
}

调用到了 cpp 层的transactNative

1
2
3
4
5
6
7
8
9
10
11
// android_os_BinderProxy
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
jint code, jobject dataObj, jobject replyObj, jboolean replyObjOwnsNativeParcel,
jint flags) // throws RemoteException
{
...
IBinder* target = getBPNativeData(env, obj)->mObject.get(); // 获取BPBinder
...
status_t err = target->transact(code, *data, reply, flags); // 由BPBinder再次传递
...
}
1
2
3
4
5
6
7
8
// BpBinder.cpp
status_t BpBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
status_t status = IPCThreadState::self()->transact(
mHandle, code, data, reply, flags); // 由IPCThreadState传递给驱动

}

如果有 reply 的话

1
2
3
4
5
6
7
8
9
10
11
12
13
// BpBinder.cpp
status_t BpBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
...
if (reply) {
err = waitForResponse(reply); // 等待回复
} else {
Parcel fakeReply;
err = waitForResponse(&fakeReply);
}
...
}
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
// IPCThreadState.cpp
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
uint32_t cmd;
int32_t err;

while (1) { // 无限循环等待结果
if ((err=talkWithDriver()) < NO_ERROR) break;
err = mIn.errorCheck();
if (err < NO_ERROR) break;
if (mIn.dataAvail() == 0) continue;

cmd = (uint32_t)mIn.readInt32();

IF_LOG_COMMANDS() {
alog << "Processing waitForResponse Command: "
<< getReturnString(cmd) << endl;
}

switch (cmd) {
...
case BR_REPLY: // 如果返回消息
{
binder_transaction_data tr;
err = mIn.read(&tr, sizeof(tr));
ALOG_ASSERT(err == NO_ERROR, "Not enough command data for brREPLY");
if (err != NO_ERROR) goto finish;

if (reply) {
if ((tr.flags & TF_STATUS_CODE) == 0) {
reply->ipcSetDataReference(
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t),
freeBuffer); // 设置返回值
} else {
err = *reinterpret_cast<const status_t*>(tr.data.ptr.buffer);
freeBuffer(nullptr,
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t));
}
} else {
freeBuffer(nullptr,
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t));
continue;
}
}
goto finish;

default:
err = executeCommand(cmd);
if (err != NO_ERROR) goto finish;
break;

}
}
}

上面的 reply 是 Parcel。我们看看Parcel::ipcSetDataReference

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
// Parcel.cpp
void Parcel::ipcSetDataReference(const uint8_t* data, size_t dataSize,
const binder_size_t* objects, size_t objectsCount, release_func relFunc)
{
freeData();

mData = const_cast<uint8_t*>(data); // 设置值
mDataSize = mDataCapacity = dataSize;
mObjects = const_cast<binder_size_t*>(objects);
mObjectsSize = mObjectsCapacity = objectsCount;
mOwner = relFunc;

binder_size_t minOffset = 0;
for (size_t i = 0; i < mObjectsSize; i++) {
binder_size_t offset = mObjects[i];
if (offset < minOffset) {
ALOGE("%s: bad object offset %" PRIu64 " < %" PRIu64 "\n",
__func__, (uint64_t)offset, (uint64_t)minOffset);
mObjectsSize = 0;
break;
}
const flat_binder_object* flat
= reinterpret_cast<const flat_binder_object*>(mData + offset);
uint32_t type = flat->hdr.type;
if (!(type == BINDER_TYPE_BINDER || type == BINDER_TYPE_HANDLE ||
type == BINDER_TYPE_FD)) {
// We should never receive other types (eg BINDER_TYPE_FDA) as long as we don't support
// them in libbinder. If we do receive them, it probably means a kernel bug; try to
// recover gracefully by clearing out the objects, and releasing the objects we do
// know about.
android_errorWriteLog(0x534e4554, "135930648");
ALOGE("%s: unsupported type object (%" PRIu32 ") at offset %" PRIu64 "\n",
__func__, type, (uint64_t)offset);
releaseObjects();
mObjectsSize = 0;
break;
}
minOffset = offset + sizeof(flat_binder_object);
}
scanForFds();

}

上面代码中,设置了返回值 mData。


 Gitalk评论