Framework系列-Binder通信流程(二)

Framework系列-Binder通信流程(一)

上篇文章写道Binder调用到了驱动层,这篇写服务端怎么执行后续流程

一、涉及源码

\frameworks\base\core\java\android\content\ContextWrapper.java
\frameworks\base\core\java\android\app\ContextImpl.java
\frameworks\base\core\java\android\app\ActivityManager.java
\frameworks\base\core\java\android\os\ServiceManagerNative.java
\frameworks\base\core\java\android\app\IActivityManager.aidl
\frameworks\base\core\java\android\os\Binder.java

\frameworks\base\core\jni\android_util_Binder.cpp
\frameworks\native\libs\binder\BpBinder.cpp
\frameworks\base\core\jni\AndroidRuntime.cpp
\frameworks\base\cmds\app_process\app_main.cpp
\frameworks\native\libs\binder\Binder.cpp

\frameworks\native\libs\binder\IPCThreadState.cpp
\frameworks\native\libs\binder\ProcessState.cpp

\drivers\staging\android\binder.c

二、回到用户空间

用户进程在fork之后,会调用ZygoteInit.zygoteInit方法做一些初始化操作,SystemServer进程启动之后也是这样调用

2.1、app_main的onZygoteInit方法

//ZygoteInit
public static final void zygoteInit(int targetSdkVersion, String[] argv,
        ClassLoader classLoader) throws Zygote.MethodAndArgsCaller {
   ...
    RuntimeInit.commonInit();
    ZygoteInit.nativeZygoteInit(); //1
    RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}

private static final native void nativeZygoteInit();


//AndroidRuntime.cpp
static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
    gCurRuntime->onZygoteInit();
}

//app_main.cpp
virtual void onZygoteInit()
{
    sp<ProcessState> proc = ProcessState::self(); //1 获取ProcessState对象
    proc->startThreadPool(); //2 启动新binder线程
}

可以看到启动进程时候,会调到app_main的onZygoteInit方法,ProcessState也是一个单例,一个进程对应一个实例。

2.2、ProcessState


sp<ProcessState> ProcessState::self()
{
    Mutex::Autolock _l(gProcessMutex);
    if (gProcess != NULL) {
        return gProcess;
    }
    gProcess = new ProcessState("/dev/binder");
    return gProcess;
}

ProcessState::ProcessState(const char *driver)
    : mDriverName(String8(driver))
    , mDriverFD(open_driver(driver))
    , mVMStart(MAP_FAILED)
    , mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
    , mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
    , mExecutingThreadsCount(0)
    , mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
    , mStarvationStartTimeMs(0)
    , mManagesContexts(false)
    , mBinderContextCheckFunc(NULL)
    , mBinderContextUserData(NULL)
    , mThreadPoolStarted(false)
    , mThreadPoolSeq(1)
{
    if (mDriverFD >= 0) {
        // mmap the binder, providing a chunk of virtual address space to receive transactions.
        mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
        //...
    }

    //...
}

这里可以看到调用open_driver()打开/dev/binder,再通过mmap映射一块物理空间到内核空间和进程空间,将Binder驱动的fd赋值ProcessState的mDriverFD,用于交互操作

2.3、proc->startThreadPool()

void ProcessState::startThreadPool()
{
    AutoMutex _l(mLock);
    if (!mThreadPoolStarted) {
        mThreadPoolStarted = true;
        spawnPooledThread(true);
    }
}

void ProcessState::spawnPooledThread(bool isMain)
{
    if (mThreadPoolStarted) {
        String8 name = makeBinderThreadName();
        //创建了一个PoolThread
        sp<Thread> t = new PoolThread(isMain);
        t->run(name.string());
    }
}

class PoolThread : public Thread
{
public:
    explicit PoolThread(bool isMain)
        : mIsMain(isMain)
    {
    }
    
protected:
    virtual bool threadLoop()
    {
        IPCThreadState::self()->joinThreadPool(mIsMain);
        return false;
    }
    
    const bool mIsMain;
};

可以看到startThreadPool(),里面创建了一个PoolThread线程池,然后创建了一个IPCThreadState,调用它的joinThreadPool方法

2.4、IPCThreadState::self()->joinThreadPool

void IPCThreadState::joinThreadPool(bool isMain)
{

    mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);

    status_t result;
    do {
        processPendingDerefs();
        // now get the next command to be processed, waiting if necessary
        result = getAndExecuteCommand();  
		.....
    } while (result != -ECONNREFUSED && result != -EBADF);

   //...
    talkWithDriver(false);
}

status_t IPCThreadState::getAndExecuteCommand()
{
    status_t result;
    int32_t cmd;

    result = talkWithDriver();  //与binder驱动进程交互
    if (result >= NO_ERROR) {


        result = executeCommand(cmd);

       
    }

    return result;
}

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:
        {
            binder_transaction_data tr;
            result = mIn.read(&tr, sizeof(tr));
            ALOG_ASSERT(result == NO_ERROR,
                "Not enough command data for brTRANSACTION");
            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, this);

            const pid_t origPid = mCallingPid;
            const uid_t origUid = mCallingUid;
            const int32_t origStrictModePolicy = mStrictModePolicy;
            const int32_t origTransactionBinderFlags = mLastTransactionBinderFlags;

            mCallingPid = tr.sender_pid;
            mCallingUid = tr.sender_euid;
            mLastTransactionBinderFlags = tr.flags;

            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)) {
                    error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,
                            &reply, tr.flags);  //1
                    reinterpret_cast<BBinder*>(tr.cookie)->decStrong(this);
                } else {
                    error = UNKNOWN_TRANSACTION;
                }

            } else {
                error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
            }

            
            if ((tr.flags & TF_ONE_WAY) == 0) {
                if (error < NO_ERROR) reply.setError(error);
                sendReply(reply, 0);
            } else {
            }
          
        }
        break;

 //...
    }

    if (result != NO_ERROR) {
        mLastError = result;
    }

    return result;
}

在joinThreadPool方法中调用getAndExecuteCommand方法,在这个方法里面调用talkWithDriver与驱动交互,在binder_thread_read方法中,todo队列没有数据,等待被唤醒,由于binder_transaction方法里面调用wake_up_interruptible唤醒目标进程,binder_thread_read会走后面代码,走到getAndExecuteCommand方法。

关键代码在注释1处,会调用BBinder.transact方法

//\frameworks\native\libs\binder\Binder.cpp
status_t BBinder::transact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    data.setDataPosition(0);

    status_t err = NO_ERROR;
    switch (code) {
        case PING_TRANSACTION:
            reply->writeInt32(pingBinder());
            break;
        default:
            err = onTransact(code, data, reply, flags);  //1
            break;
    }

    if (reply != NULL) {
        reply->setDataPosition(0);
    }

    return err;
}
//\frameworks\base\core\jni\android_util_Binder.cpp
virtual status_t onTransact(
        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)
    {
        JNIEnv* env = javavm_to_jnienv(mVM);

        ALOGV("onTransact() on %p calling object %p in env %p vm %p\n", this, mObject, env, mVM);

        IPCThreadState* thread_state = IPCThreadState::self();
        const int32_t strict_policy_before = thread_state->getStrictModePolicy();

        //调用Binder.execTransact
        jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
            code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);

       ...
        return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION;
    }

在注释1处调用到onTransact()方法,里面会调用到java层的Binder.execTransact,这些对象的注册在AndroidRuntime::startReg过程,其中有一个过程便是register_android_os_Binder(),该过程会把gBinderOffsets.mExecTransact便是Binder.java中的execTransact()方法

//\frameworks\base\core\java\android\os\Binder.java
private boolean execTransact(int code, long dataObj, long replyObj,
            int flags) {
    Parcel data = Parcel.obtain(dataObj);
    Parcel reply = Parcel.obtain(replyObj);
//...
    try {
//...
//AMS.onTransact
        res = onTransact(code, data, reply, flags);
    } catch (RemoteException|RuntimeException e) {
//...
    } catch (OutOfMemoryError e) {
//...
    } finally {
        if (tracingEnabled) {
            Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
        }
    }
//...

    return res;
}


这里调用到了java层的execTransact,里面会调用onTransact,服务端重写了这个方法,回调到IActivityManager.Stub里面,最后会调用到AMS。到这里就完成了客户端写到服务端的过程。

三、Reply流程

前面IPC.waitForResponse()过程,对于非oneway的方式,还仍在一直等待system_server这边的响应呢,只有收到服务端的REPLY命令之后才会结束流程。

前面executeCommand执行完transact方法,会调用sendReply方法向客户端返回reply

status_t IPCThreadState::sendReply(const Parcel& reply, uint32_t flags)
{
    status_t err;
    status_t statusBuffer;
    err = writeTransactionData(BC_REPLY, flags, -1, 0, reply, &statusBuffer);
    if (err < NO_ERROR) return err;

    return waitForResponse(NULL, NULL);
}

上面写入了BC_REPLY命令,看客户端收到这个命令如何进行后续操作

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, this);   //1
                    } else {
                        err = *reinterpret_cast<const status_t*>(tr.data.ptr.buffer);
                        freeBuffer(NULL,
                            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), this);
                    }
                } else {
                //释放buffer
                    freeBuffer(NULL,
                        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), this);
                    continue;
                }
            }
            goto finish;

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

    return err;
}

客户端收到信息,就释放buffer,然后就结束了流程。

还是借助gityuan大佬的图来结束文章。

在这里插入图片描述

四、参考文章

Binder系列—开篇

彻底理解Android Binder通信架构

Android应用启动的实质(二)

Binder机制之一次响应的故事

Binder——从发起通信到talkWithDriver()

听说你Binder机制学的不错,来面试下这几个问题(一)

ZygoteInit从c到java

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值