1. freeBuffer:
用于释放空间。 2个用处:
1) buffer.ipcSetDataReference 作为释放函数传入
2) BR_REPLY: if no reply
作为释放函数传入时,分别在传入和传出有体现BR_TRANSACTION and BR_REPLY
if (parcel != NULL) parcel->closeFileDescriptors();
检查是否为空, noreply(2) 情况此值为空。 传入(1)此值为this, 当前parsel. 遍寻parsel结构体关闭所有 BINDER_TYPE_FD类型file .
IPCThreadState* state = self(); 得到当前线程的IPCThreadState, 其实也就是当前结构体
state->mOut.writeInt32(BC_FREE_BUFFER);
state->mOut.writeInt32((int32_t)data);
通过read write 写命令到驱动层,释放结构体。
2. threadDestructor
用于毁掉这个线程,应该包括各种释放
self->flushCommands(); ==〉
// 检查是否打开了底层驱动,如果没,直接返回
if (mProcess->mDriverFD <= 0)
return;
// 与底层交流,试图关闭驱动
talkWithDriver(false); 细节以后分析,不需要接受命令,但会把当前须传出的命令传下去
#if defined(HAVE_ANDROID_OS)
ioctl(self->mProcess->mDriverFD, BINDER_THREAD_EXIT, 0);
#endif
直接操纵底层驱动,从驱动层删除了这个线程
3. executeCommand 执行各种命令 命令基本来自驱动层
case BR_ERROR:
result = mIn.readInt32();
break;
从下层读一个32bit, 好象是下面发了个错误信号,上层去读为什么出问题
case BR_OK:
break;
蛋疼。。
case BR_ACQUIRE:
refs = (RefBase::weakref_type*)mIn.readInt32();
obj = (BBinder*)mIn.readInt32();
从底层拿这两个结构体上来。
obj->incStrong(mProcess.get());
真实工作
mOut.writeInt32(BC_ACQUIRE_DONE);
mOut.writeInt32((int32_t)refs);
mOut.writeInt32((int32_t)obj);
ref啥也没干,又放回去了
什么时候会调这个函数呢。。。似乎是一次binder函数结束时搞定
case BR_RELEASE:
mPendingStrongDerefs.push(obj); mPendingWeakDerefs.push(refs)
直接加到这个队列里,应该有个什么地方释放巴
BR_INCREFS:
refs->incWeak(mProcess.get());
可以看到refs终于干活了。记得传说,obj 讲的是服务,也就是本地进程,ref是客户端进程, 待严正
case BR_DECREFS:
mPendingWeakDerefs.push(refs)
另外一个队列
case BR_ATTEMPT_ACQUIRE
const bool success = refs->attemptIncStrong(mProcess.get());
这玩干什么的阿。。没找到谁调用的阿。goolge下说没实现。。 这个是用来变弱为强的阿,设计者在想什么啊
case BR_TRANSACTION:
正题~~
binder_transaction_data tr;
result = mIn.read(&tr, sizeof(tr));
从下面读上来的。这是要操作的数据马?
Parcel buffer;
buffer.ipcSetDataReference(
reinterpret_cast(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast(tr.data.ptr.offsets),
tr.offsets_size/sizeof(size_t), freeBuffer, this);
构造了个parcel, 然后传进来的数据被按进去了
const pid_t origPid = mCallingPid;
const uid_t origUid = mCallingUid;
mCallingPid = tr.sender_pid;
mCallingUid = tr.sender_euid;
调用者进程号线程号被记下来的,竟然是实名制。
int curPrio = getpriority(PRIO_PROCESS, mMyThreadId);
if (gDisableBackgroundScheduling) {
if (curPrio > ANDROID_PRIORITY_NORMAL) {
// We have inherited a reduced priority from the caller, but do not
// want to run in that state in this process. The driver set our
// priority already (though not our scheduling class), so bounce
// it back to the default before invoking the transaction.
setpriority(PRIO_PROCESS, mMyThreadId, ANDROID_PRIORITY_NORMAL);
}
} else {
if (curPrio >= ANDROID_PRIORITY_BACKGROUND) {
// We want to use the inherited priority from the caller.
// Ensure this thread is in the background scheduling class,
// since the driver won't modify scheduling classes for us.
// The scheduling group is reset to default by the caller
// once this method returns after the transaction is complete.
androidSetThreadSchedulingGroup(mMyThreadId,
ANDROID_TGROUP_BG_NONINTERACT);
}
}
如果启动了线程调控机制, androidSetThreadSchedulingGroup,否则单独设一个线程的优先级。 这里会涉及Linux 的调度概念,比如CFS(Completely Fair Scheduler)
Parcel reply;
if (tr.target.ptr) {
sp b((BBinder*)tr.cookie);
const status_t error = b->transact(tr.code, buffer, &reply, tr.flags);
if (error < NO_ERROR) reply.setError(error);
如果这个BBinder包含了一个可用的object, 即服务存在,则调用服务的transact
} else {
const status_t error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
if (error < NO_ERROR) reply.setError(error);
}
如果这个标志位为空,说明调用的是服务进程。service manager被调用。 transact 在这不深入
if ((tr.flags & TF_ONE_WAY) == 0) {
LOG_ONEWAY("Sending reply to %d!", mCallingPid);
sendReply(reply, 0);
} else {
LOG_ONEWAY("NOT sending reply to %d!", mCallingPid);
}
这个好理解,transact 的返回值被封装在reply再传回driver.
case BR_DEAD_BINDER
BpBinder *proxy = (BpBinder*)mIn.readInt32();
proxy->sendObituary();
mOut.writeInt32(BC_DEAD_BINDER_DONE);
mOut.writeInt32((int32_t)proxy);
出了个新概念,BpBinder~~ 传说他是跟BBinder对应的,不过这里他代表着一个Binder, 可惜这里表示的是个死binder
然后这个家伙发出讣告,通知所有的注册的deathnotifier~~~ 基本上是清理工作
case BR_CLEAR_DEATH_NOTIFICATION_DONE:
当前task取消订阅binder死亡通知成功之后的得到回复命令-- google said
还没看到相关细节
case BR_SPAWN_LOOPER:
mProcess->spawnPooledThread(false);
这个函数是用来注册用的阿,那参数如果是true 就是主函数,否则就是加入循环。 具体用法待分析
还有几个小case,没意义,不分析了
4. 往上看是个将就的表达,这 the_context_object全局变量表示的是总service,可笑的是竟然找不到谁调了这个setTheContextObject
如果不是这个方法被弃用了,就是什么特殊手段在某些地方定义的。。。 等以后碰到了再说吧
sp the_context_object;
void setTheContextObject(sp obj)
{
the_context_object = obj;
}
5. writeTransactionData 这个函数很重要啊,贯通与驱动的数据通信
如果没有问题,数据打包封装
if (err == NO_ERROR) {
tr.data_size = data.ipcDataSize();
tr.data.ptr.buffer = data.ipcData();
tr.offsets_size = data.ipcObjectsCount()*sizeof(size_t);
tr.data.ptr.offsets = data.ipcObjects();
} else if (statusBuffer) {
如果是状态传输,打包状态传输
tr.flags |= TF_STATUS_CODE;
*statusBuffer = err;
tr.data_size = sizeof(status_t);
tr.data.ptr.buffer = statusBuffer;
tr.offsets_size = 0;
tr.data.ptr.offsets = NULL;
} else {
return (mLastError = err);
}
最后是写下去
mOut.writeInt32(cmd);
mOut.write(&tr, sizeof(tr));
6. talkWithDriver 这个估计是这个文件里最重要的地方了
binder_write_read bwr; 负责通信的载体
const bool needRead = mIn.dataPosition() >= mIn.dataSize();
dataposition 是数据位置,size是终止位置,当没有数据时,他们应该相等
const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;
outavail 由2个因素决定,doreceive 是传进来的,不接受的时候,可以有数据输出
needread, 是上个函数算出来的,读buffer为空,没有数据在读进来
当地英文解释说,写操作力图避免与读操作同时发生
bwr.write_size = outAvail;
bwr.write_buffer = (long unsigned int)mOut.data();
写入的一次付值,如果write_size为0, 则不会有写的实际操作发生
if (doReceive && needRead) {
bwr.read_size = mIn.dataCapacity();
bwr.read_buffer = (long unsigned int)mIn.data();
} else {
bwr.read_size = 0;
bwr.read_buffer = 0;
} 如果需要读,且读buffer确实为空,则设置准备读
if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;
如果读写皆为0, 则返回
bwr.write_consumed = 0;
` bwr.read_consumed = 0;
status_t err;
do {
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
err = NO_ERROR;
else
err = -errno;
} while (err == -EINTR);
直接操作ioctl 与驱动层通信。
if (err >= NO_ERROR) {
if (bwr.write_consumed > 0) {
if (bwr.write_consumed < (ssize_t)mOut.dataSize())
mOut.remove(0, bwr.write_consumed);
else
mOut.setDataSize(0);
}
if (bwr.read_consumed > 0) {
mIn.setDataSize(bwr.read_consumed);
mIn.setDataPosition(0);
}
如果读写出错,这里做了下错误处理。没什么内容。
说道这里,就是说所有mOut写下去的数据都需要talkwithdriver 真正的写下去, mIn也是调完talk才可以用的
7.waitForResponse 用于传数据下去后,等待底层回复
while (1) 程序起手死循环,等确定条件发生时break
if ((err=talkWithDriver()) < NO_ERROR) break;
err = mIn.errorCheck();
if (err < NO_ERROR) break;
if (mIn.dataAvail() == 0) continue;
直接与底层交互,有错误推出,没数据传入继续等待
cmd = mIn.readInt32();
成功读入数据
switch (cmd) {
根据不同返回的命令进行相关工作
case BR_TRANSACTION_COMPLETE:
if (!reply && !acquireResult) goto finish;
这个逻辑应该有上下文,当传入的两个参数皆为空才返回。应该有些条件约束。不过他表达的是transaction 完成
case BR_DEAD_REPLY:
err = DEAD_OBJECT;
goto finish;
返回错误码,应该是服务线程已经不存在了
case BR_FAILED_REPLY:
err = FAILED_TRANSACTION;
返回错误码,传输失败
case BR_ACQUIRE_RESULT:
{
LOG_ASSERT(acquireResult != NULL, "Unexpected brACQUIRE_RESULT");
const int32_t result = mIn.readInt32();
if (!acquireResult) continue;
*acquireResult = result ? NO_ERROR : INVALID_OPERATION;
}
返回结果,暂时搞不懂下层在什么情况下返回这个,难道是某种状态查询?
case BR_REPLY:
{
binder_transaction_data tr;
err = mIn.read(&tr, sizeof(tr));
if (err != NO_ERROR) goto finish;
真的读进了个返回数据
if (reply) { // 参数
if ((tr.flags & TF_STATUS_CODE) == 0) {
reply->ipcSetDataReference(
reinterpret_cast(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast(tr.data.ptr.offsets),
tr.offsets_size/sizeof(size_t),
freeBuffer, this);
需要搞明白这是要干什么,不满足的情况都释放掉
} else {
err = *static_cast(tr.data.ptr.buffer);
freeBuffer(NULL,
reinterpret_cast(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast(tr.data.ptr.offsets),
tr.offsets_size/sizeof(size_t), this);
}
} else {
freeBuffer(NULL,
reinterpret_cast(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast(tr.data.ptr.offsets),
tr.offsets_size/sizeof(size_t), this);
continue;
}
}
goto finish;
这个要反过来再讲一讲
8. sendReply 这个函数用在BR_TRANSACTION, 当服务线程工作时,错误值,打包返回driver, 最后到client thread
err = writeTransactionData(BC_REPLY, flags, -1, 0, reply, &statusBuffer);
if (err < NO_ERROR) return err;
return waitForResponse(NULL, NULL);
9. clearDeathNotification/requestDeathNotification
相当于某种程度的注册,应该是binder死亡后的相关处理
10. transact
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
着要是调到这个函数。前面已经分析过
他增加了下对wait respond 的各种等待
11. joinThreadPool 这是这个线程的主逻辑 网上有很多文章分析这个
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
通过BC_ENTER_LOOPER 或者 BC_REGISTER_LOOPER确定是服务线程还是各个services.
androidSetThreadSchedulingGroup(mMyThreadId, ANDROID_TGROUP_DEFAULT);
设定策略层,线程调度策略
如果没有数据传入,清空那obj和ref对列
// When we've cleared the incoming command queue, process any pending derefs
if (mIn.dataPosition() >= mIn.dataSize()) {
size_t numPending = mPendingWeakDerefs.size();
if (numPending > 0) {
for (size_t i = 0; i < numPending; i++) {
RefBase::weakref_type* refs = mPendingWeakDerefs[i];
refs->decWeak(mProcess.get());
}
mPendingWeakDerefs.clear();
}
numPending = mPendingStrongDerefs.size();
if (numPending > 0) {
for (size_t i = 0; i < numPending; i++) {
BBinder* obj = mPendingStrongDerefs[i];
obj->decStrong(mProcess.get());
}
mPendingStrongDerefs.clear();
}
}
与驱动交互
result = talkWithDriver();
如果有数据传入,执行相关命令
if (result >= NO_ERROR) {
size_t IN = mIn.dataAvail();
if (IN < sizeof(int32_t)) continue;
cmd = mIn.readInt32();
IF_LOG_COMMANDS() {
alog << "Processing top-level Command: "
<< getReturnString(cmd) << endl;
}
result = executeCommand(cmd);
}
基本就是这个逻辑反复循环。。
到这,这里的基本内容就算理清了