写给运用开发的 Android Framework 教程是一个系列教程,现在已更新以下内容:

  • Android Framework 学习路线攻略

  • 体系开发根底

    • Ubuntu 运用快速入门
    • Make 构建工具入门
    • 了解 Unicode UTF-8 UTF-16 UTF-32
    • Linux Shell 脚本编程入门——核心根底语法
    • SEAndroid 运用极速上手
    • 了解 C++ 的 Memory Order
  • 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。