写给运用开发的 Android Framework 教程是一个系列教程,现在已更新以下内容:
-
Android Framework 学习路线攻略
-
体系开发根底
-
AOSP 上手攻略
- AOSP 极速上手
- 体系开发工具引荐
- 增加 Product
- 增加 C/C++、Java 可履行程序
- 增加 C/C++、Java 库
- 增加配置文件与删去已有模块
- 体系 App 源码增加
- 运用 Android Studio 开发体系 App
- 增加开机自启动 Shell 脚本
-
学穿 Binder 系列
- Binder 基本原理
- Binder 程序示例之 C 言语篇
- Binder 服务注册进程情形剖析之C言语篇
- Binder 服务获取与运用进程情形剖析之C言语篇
- Binder C++ 程序示例
- Binder C++ 程序剖析之首要类解析
- Binder 服务注册进程情形剖析之 C++ 篇
- Binder 服务获取与运用进程情形剖析之 C++ 篇(本文)
-
HAL 与硬件服务
-
Kernel 下载与编译
-
Linux 驱动开发入门
-
本文根据 AOSP Android10 r41
源码环境
先看一下客户端主函数:
int main(int argc, char const *argv[])
{
//Binder 驱动初始化
sp<ProcessState> proc(ProcessState::self());
//获取 BpServiceManger 目标
sp<IServiceManager> sm = defaultServiceManager();
//获取服务
sp<IBinder> binder = sm->getService(String16("hello"));
//转成 BpHelloService
sp<IHelloService> service =
interface_cast<IHelloService>(binder);
if (binder == 0)
{
ALOGI("can't get hello service\n");
return -1;
}
//建议长途调用
service->sayHello();
int cnt = service->sayHelloTo("nihao");
ALOGI("client call sayhello_to, cnt = %d", cnt);
return 0;
}
首要的流程:
- 调用
ProcessState::self()
完成 Binder 的初始化 - 调用
defaultServiceManager()
获取到 BpServiceManger 目标 -
getService
获取到 hello 服务 - 建议长途调用
前两个阶段流程和 Binder 服务注册进程情形剖析之C++篇 相同,这儿不在重复
1. 获取服务
sp<IBinder> binder = sm->getService(String16("hello"));
getService
详细实现在 frameworks/native/libs/binder/IServiceManager.cpp
virtual sp<IBinder> getService(const String16& name) const
{
sp<IBinder> svc = checkService(name);
if (svc != nullptr) return svc;
//......
}
virtual sp<IBinder> checkService( const String16& name) const
{
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
return reply.readStrongBinder();
}
经过 remote 建议长途调用,remote 的调用细节和 Binder 服务注册进程情形剖析之C++篇 相同,这儿不在重复。
ServiceManager getService 回来的是一个整型 handle,经过 reply.readStrongBinder()
将 handle 包装为一个 IBinder 目标(实践是一个 BpBinder 目标)。转换进程会在后边 Parcel 解析的文章剖析。这儿知道其功能即可。
接着经过 interface_cast
将其转换为 BpHelloService 目标,流程和Binder 服务注册进程情形剖析之C++篇 中 defaultServiceManager
中的剖析相同。最终就是 new 一个 BpHelloService 目标,经过构造函数参数传入 BpBinder。
sp<IHelloService> service =
interface_cast<IHelloService>(binder);
2. 建议长途调用
有了 HpHelloService 目标就可以建议长途调用了,这儿剖析 sayHello 的实现,sayHelloto 就留给读者了
service->sayHello();
实现如下:
void BpHelloService::sayHello() {
Parcel data, reply;
data.writeInt32(0);
data.writeString16(String16("IHelloService"));
remote()->transact(HELLO_SVR_CMD_SAYHELLO, data, &reply);
}
经过 remote 建议长途调用,客户端阻塞,服务端被唤醒。咱们的服务端敞开了两个线程等候长途调用,内核会挑选一个线程唤醒(详细选哪个会在驱动剖析中阐明):
void IPCThreadState::joinThreadPool(bool isMain)
{
//......
do { //进入循环
//......
// now get the next command to be processed, waiting if necessary
//读数据,处理数据
result = getAndExecuteCommand();
} while (result != -ECONNREFUSED && result != -EBADF);
//......
}
status_t IPCThreadState::getAndExecuteCommand()
{
status_t result;
int32_t cmd;
//读数据
result = talkWithDriver();
if (result >= NO_ERROR) {
//......
//处理数据
result = executeCommand(cmd);
//......
}
return result;
}
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
if (mProcess->mDriverFD < 0) {
return -EBADF;
}
binder_write_read bwr;
// Is the read buffer empty?
const bool needRead = mIn.dataPosition() >= mIn.dataSize();
// We don't want to write anything if we are still reading
// from data left in the input buffer and the caller
// has requested to read the next data.
const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;
bwr.write_size = outAvail;
bwr.write_buffer = (uintptr_t)mOut.data();
// This is what we'll read.
if (doReceive && needRead) {
bwr.read_size = mIn.dataCapacity();
bwr.read_buffer = (uintptr_t)mIn.data();
} else {
bwr.read_size = 0;
bwr.read_buffer = 0;
}
// Return immediately if there is nothing to do.
if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;
bwr.write_consumed = 0;
bwr.read_consumed = 0;
status_t err;
do {
#if defined(__ANDROID__)
//从这儿唤醒
//读到数据 bwr
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
err = NO_ERROR;
else
err = -errno;
#else
err = INVALID_OPERATION;
#endif
if (mProcess->mDriverFD < 0) {
err = -EBADF;
}
} while (err == -EINTR);
if (err >= NO_ERROR) {
if (bwr.write_consumed > 0) {
if (bwr.write_consumed < mOut.dataSize())
LOG_ALWAYS_FATAL("Driver did not consume write buffer. "
"err: %s consumed: %zu of %zu",
statusToString(err).c_str(),
(size_t)bwr.write_consumed,
mOut.dataSize());
else {
mOut.setDataSize(0);
processPostWriteDerefs();
}
}
//将收到的数据写到 mIn 中
if (bwr.read_consumed > 0) {
mIn.setDataSize(bwr.read_consumed);
mIn.setDataPosition(0);
}
return NO_ERROR;
}
return err;
}
//
status_t IPCThreadState::executeCommand(int32_t cmd)
{
BBinder* obj;
RefBase::weakref_type* refs;
status_t result = NO_ERROR;
switch ((uint32_t)cmd) {
case BR_TRANSACTION_SEC_CTX:
case BR_TRANSACTION:
{
binder_transaction_data_secctx tr_secctx;
binder_transaction_data& tr = tr_secctx.transaction_data;
if (cmd == (int) BR_TRANSACTION_SEC_CTX) {
result = mIn.read(&tr_secctx, sizeof(tr_secctx));
} else {
//读出刚才写入到 mIn 中的数据
result = mIn.read(&tr, sizeof(tr));
tr_secctx.secctx = 0;
}
if (result != NO_ERROR) break;
Parcel buffer;
buffer.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);
const void* origServingStackPointer = mServingStackPointer;
mServingStackPointer = __builtin_frame_address(0);
const pid_t origPid = mCallingPid;
const char* origSid = mCallingSid;
const uid_t origUid = mCallingUid;
const bool origHasExplicitIdentity = mHasExplicitIdentity;
const int32_t origStrictModePolicy = mStrictModePolicy;
const int32_t origTransactionBinderFlags = mLastTransactionBinderFlags;
const int32_t origWorkSource = mWorkSource;
const bool origPropagateWorkSet = mPropagateWorkSource;
// Calling work source will be set by Parcel#enforceInterface. Parcel#enforceInterface
// is only guaranteed to be called for AIDL-generated stubs so we reset the work source
// here to never propagate it.
clearCallingWorkSource();
clearPropagateWorkSource();
mCallingPid = tr.sender_pid;
mCallingSid = reinterpret_cast<const char*>(tr_secctx.secctx);
mCallingUid = tr.sender_euid;
mHasExplicitIdentity = false;
mLastTransactionBinderFlags = tr.flags;
// ALOGI(">>>> TRANSACT from pid %d sid %s uid %d\n", mCallingPid,
// (mCallingSid ? mCallingSid : "<N/A>"), mCallingUid);
Parcel reply;
status_t error;
if (tr.target.ptr) {
// We only have a weak reference on the target object, so we must first try to
// safely acquire a strong reference before doing anything else with it.
if (reinterpret_cast<RefBase::weakref_type*>(
tr.target.ptr)->attemptIncStrong(this)) {
//tranact 履行到 onTranact,然后履行到 sayHello 函数
error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,
&reply, tr.flags);
reinterpret_cast<BBinder*>(tr.cookie)->decStrong(this);
} else {
error = UNKNOWN_TRANSACTION;
}
} else {
error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
}
//ALOGI("<<<< TRANSACT from pid %d restore pid %d sid %s uid %d\n",
// mCallingPid, origPid, (origSid ? origSid : "<N/A>"), origUid);
if ((tr.flags & TF_ONE_WAY) == 0) {
LOG_ONEWAY("Sending reply to %d!", mCallingPid);
if (error < NO_ERROR) reply.setError(error);
// b/238777741: clear buffer before we send the reply.
// Otherwise, there is a race where the client may
// receive the reply and send another transaction
// here and the space used by this transaction won't
// be freed for the client.
buffer.setDataSize(0);
constexpr uint32_t kForwardReplyFlags = TF_CLEAR_BUF;
sendReply(reply, (tr.flags & kForwardReplyFlags));
} else {
if (error != OK) {
std::ostringstream logStream;
logStream << "oneway function results for code " << tr.code << " on binder at "
<< reinterpret_cast<void*>(tr.target.ptr)
<< " will be dropped but finished with status "
<< statusToString(error);
if (reply.dataSize() != 0) {
logStream << " and reply parcel size " << reply.dataSize();
}
std::string message = logStream.str();
ALOGI("%s", message.c_str());
}
}
mServingStackPointer = origServingStackPointer;
mCallingPid = origPid;
mCallingSid = origSid;
mCallingUid = origUid;
mHasExplicitIdentity = origHasExplicitIdentity;
mStrictModePolicy = origStrictModePolicy;
mLastTransactionBinderFlags = origTransactionBinderFlags;
mWorkSource = origWorkSource;
mPropagateWorkSource = origPropagateWorkSet;
}
break;
//......
default:
ALOGE("*** BAD COMMAND %d received from Binder driver\n", cmd);
result = UNKNOWN_ERROR;
break;
}
if (result != NO_ERROR) {
mLastError = result;
}
return result;
}
从 ioctl 唤醒,解析出数据,经过 transact 办法调用到咱们自定义的 onTransact 函数,然后履行到 sayHello。