美文网首页
Android进程间通信(七)——客户端调用服务端onTrans

Android进程间通信(七)——客户端调用服务端onTrans

作者: Boahui | 来源:发表于2021-07-18 00:36 被阅读0次

    Android进程间通信(六)——普通进程的bindService流程介绍了普通的应用进程另一个进程的Service的流程。那么客户端获取到的IBinder对象是哪个类吶?客户端又怎么通过这个IBinder对象调用到服务端的onTransact方法中吶?源码github地址

    客户端收到的IBinder是什么

    我们看服务端调用了s.onBind获取了一个IBinder对象,这个IBinder对象就是一个Binder

    private void handleBindService(BindServiceData data) {
            Service s = mServices.get(data.token);//在handCreateService中创建完Service就保存到mService中了
            //s为通过bindService创建好的Service
            if (DEBUG_SERVICE)
                Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
            if (s != null) {
                try {
                    data.intent.setExtrasClassLoader(s.getClassLoader());
                    data.intent.prepareToEnterProcess();
                    try {
                        if (!data.rebind) {
                            IBinder binder = s.onBind(data.intent);
                            //跨进程调用toekn为客户端进程,binder为IBinder
                            ActivityManager.getService().publishService(
                                    data.token, data.intent, binder);
                        } else {
    

    也就是调用了远程服务RemoteService的onBind获取了一个ServerBinder对象

    
    public class RemoteService extends Service {
        public static final int TRANSAVTION_showMessage = IBinder.FIRST_CALL_TRANSACTION;
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return new ServerBinder();
        }
    
        static class ServerBinder extends Binder   {
            public ServerBinder() {
            }
    
            @Override
            protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException {
    
                switch (code) {
                    case TRANSAVTION_showMessage:
                        String message = data.readString();
                        Log.d("ServerBinder", "showMessage " + message);
                        if (ServerMainActivity.tvShowMessage != null) {
                            new Handler(Looper.getMainLooper()).post(new Runnable() {
                                @Override
                                public void run() {
                                    ServerMainActivity.tvShowMessage.setText(message);
                                }
                            });
                        }
                        if (reply != null) {
                            reply.writeNoException();
                        }
                        return true;
                }
                return super.onTransact(code, data, reply, flags);
            }
    
    
        }
    }
    
    

    ActivityManager.getService().publishService(data.token, data.intent, binder);

    我们先看一下AMS的addService

      public void addService(String name, IBinder service, boolean allowIsolated)
                throws RemoteException {//这个是代理类的调用addService的方法
            Parcel data = Parcel.obtain();
            Parcel reply = Parcel.obtain();
            data.writeInterfaceToken(IServiceManager.descriptor);
            data.writeString(name);//写入服务的名字
            data.writeStrongBinder(service);//写入服务的Binder ,后期获取的就是这个Binder调用Parcel的CPP方法,将binder写入
            data.writeInt(allowIsolated ? 1 : 0);
            mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
            reply.recycle();
            data.recycle();
        }
    
       public final void writeStrongBinder(IBinder val) {
            nativeWriteStrongBinder(mNativePtr, val);//调用android_os_Parcel将Java层的Binder对象转换为nativce层的对象
        }
    
    static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
    {
        Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
        if (parcel != NULL) {
            //将object  也就是Java层的Binder对象转换为nativce层的对象
            const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
            if (err != NO_ERROR) {
                signalExceptionForError(env, clazz, err);
            }
        }
    }
    
    
    sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
    {
        if (obj == NULL) return NULL;
    
        if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {//如果传入的是Binder.java实体对象
            JavaBBinderHolder* jbh = (JavaBBinderHolder*)
                env->GetLongField(obj, gBinderOffsets.mObject);
            return jbh != NULL ? jbh->get(env, obj) : NULL;//
        }
    
        if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {//如果传入的是BinderProxy.java
            return (IBinder*)
                env->GetLongField(obj, gBinderProxyOffsets.mObject);
        }
    
        ALOGW("ibinderForJavaObject: %p is not a Binder object", obj);
        return NULL;
    }
    

    JavaBBinderHolder

    //假设现在有一个类MyClass,如果要使用智能指针来引用这个类的对象,那么这个类需满足下列两个前提条件:
    //这个类是基类RefBase的子类或间接子类;
    class JavaBBinderHolder : public RefBase
    {
    public:
        sp<JavaBBinder> get(JNIEnv* env, jobject obj)
        {
            AutoMutex _l(mLock);
            sp<JavaBBinder> b = mBinder.promote();
            if (b == NULL) {
                b = new JavaBBinder(env, obj);
                mBinder = b;
                ALOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%" PRId32 "\n",
                     b.get(), b->getWeakRefs(), obj, b->getWeakRefs()->getWeakCount());
            }
    
            return b;
        }
    
        sp<JavaBBinder> getExisting()
        {
            AutoMutex _l(mLock);
            return mBinder.promote();
        }
    
    private:
        Mutex           mLock;
        wp<JavaBBinder> mBinder;
    };
    

    JavaBBinder

    lass JavaBBinder : public BBinder
    {
    public:
        JavaBBinder(JNIEnv* env, jobject object)
            : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object))//将Java层的object赋值给mObject
        {
            ALOGV("Creating JavaBBinder %p\n", this);
            android_atomic_inc(&gNumLocalRefs);
            incRefsCreated(env);
        }
    
        bool    checkSubclass(const void* subclassID) const
        {
            return subclassID == &gBinderOffsets;
        }
    
        jobject object() const
        {
            return mObject;
        }
    

    BBinder

    BBinder::BBinder()
    {
      atomic_init(&mExtras, static_cast<uintptr_t>(0));
    }
    
    bool BBinder::isBinderAlive() const
    {
        return true;
    }
    
    status_t BBinder::pingBinder()
    {
        return NO_ERROR;
    }
    
    const String16& BBinder::getInterfaceDescriptor() const
    {
        // This is a local static rather than a global static,
        // to avoid static initializer ordering issues.
        static String16 sEmptyDescriptor;
        ALOGW("reached BBinder::getInterfaceDescriptor (this=%p)", this);
        return sEmptyDescriptor;
    }
    
    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);
                break;
        }
    
        if (reply != NULL) {
            reply->setDataPosition(0);
        }
    
        return err;
    }
    BBinder* BBinder::localBinder()
    {
        return this;
    }
    

    ibinderForJavaObject(env, object)返回的是一个JavaBBinder ,JavaBBinder继承了BBinder,所以localBinder返回不为空

    
    status_t flatten_binder(const sp<ProcessState>& /*proc*/,
        const sp<IBinder>& binder, Parcel* out)
    {
        flat_binder_object obj;
    
        obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
        if (binder != NULL) {
            IBinder *local = binder->localBinder();//binder为BBinder返回不为空
            if (!local) {
                BpBinder *proxy = binder->remoteBinder();//Bpinder
                if (proxy == NULL) {
                    ALOGE("null proxy");
                }
                const int32_t handle = proxy ? proxy->handle() : 0;
                obj.type = BINDER_TYPE_HANDLE;//handle类型
                obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */
                obj.handle = handle;
                obj.cookie = 0;
            } else {
                obj.type = BINDER_TYPE_BINDER;//Binder类型
                obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
                obj.cookie = reinterpret_cast<uintptr_t>(local);
            }
        } else {
            obj.type = BINDER_TYPE_BINDER;
            obj.binder = 0;
            obj.cookie = 0;
        }
    
        return finish_flatten_binder(binder, obj, out);
    }
    

    flat_binder_object

    typedef __u32 binder_uintptr_t;
    
     */
    struct binder_object_header {
        __u32        type;
    }; 
    struct flat_binder_object {
        struct binder_object_header hdr;
        __u32               flags;
    
        /* 8 bytes of data. */
        union {
            binder_uintptr_t    binder; /* local object */
            __u32           handle; /* remote object */
        };
    
        /* extra data associated with local object */
        binder_uintptr_t    cookie;//指针,Binder实体
    };
    

    所以flat_binder_object中存储了服务端进程Native层Binder对象的指针,之后就是将这个数据拷贝到内核空间。下面这个图展示了addService到ServiceManager中,以及客户端如何获取AMS并跨进程调用相关方法


    客户端调用服务端onTransaction流程

    我们知道,客户端通过bindService获取到了服务端的IBinder 也就是BinderProxy,BinderProxy类持有BpBinder(handle)对象的native层指针,通过IBinder的transact调用到了BpBinder的transact方法

    status_t BpBinder::transact(//BpBinder通信
        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
    {
        // Once a binder has died, it will never come back to life.
        if (mAlive) {
    //mHandle指向客户端进程proc结构体保存的binder_ref,通过binder_ref就可以获取服务端的进程信息
            status_t status = IPCThreadState::self()->transact(
                mHandle, code, data, reply, flags);
            if (status == DEAD_OBJECT) mAlive = 0;
            return status;
        }
    
        return DEAD_OBJECT;
    }
    

    客户端最终调用驱动层的binder_transaction将数据拷贝到服务端进程的内核空间,唤醒服务端处理数据

    服务端进程启动后Binder一直等待客户端请求

    在app_main.cpp中

    class AppRuntime : public AndroidRuntime
    {
    public:
        AppRuntime(char* argBlockStart, const size_t argBlockLength)
            : AndroidRuntime(argBlockStart, argBlockLength)
            , mClass(NULL)
        {
        }
      virtual void onStarted()
        {
            sp<ProcessState> proc = ProcessState::self();
            ALOGV("App process: starting thread pool.\n");
            proc->startThreadPool();//应用启动线程池
    
    void ProcessState::startThreadPool()
    {
        AutoMutex _l(mLock);
        if (!mThreadPoolStarted) {
            mThreadPoolStarted = true;
            spawnPooledThread(true);
        }
    }
    void ProcessState::spawnPooledThread(bool isMain)
    {
        if (mThreadPoolStarted) {
            String8 name = makeBinderThreadName();
            ALOGV("Spawning new pooled thread, name=%s\n", name.string());
            sp<Thread> t = new PoolThread(isMain);
            t->run(name.string());//线程启动
        }
    }
    
    class PoolThread : public Thread
    {
    public:
        PoolThread(bool isMain)
            : mIsMain(isMain)
        {
        }
        
    protected:
        virtual bool threadLoop()
        {
            //开启循环等待客户端请求
            IPCThreadState::self()->joinThreadPool(mIsMain);
            return false;
        }
        
        const bool mIsMain;
    };
    
    

    getAndExecuteCommand

    void IPCThreadState::joinThreadPool(bool isMain)
    {
        LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid());
    
        mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
        
        // This thread may have been spawned by a thread that was in the background
        // scheduling group, so first we will make sure it is in the foreground
        // one to avoid performing an initial transaction in the background.
        set_sched_policy(mMyThreadId, SP_FOREGROUND);
            
        status_t result;
        do {
            processPendingDerefs();
            // now get the next command to be processed, waiting if necessary
            result = getAndExecuteCommand();
    
            if (result < NO_ERROR && result != TIMED_OUT && result != -ECONNREFUSED && result != -EBADF) {
                ALOGE("getAndExecuteCommand(fd=%d) returned unexpected error %d, aborting",
                      mProcess->mDriverFD, result);
                abort();
            }
            
            // Let this thread exit the thread pool if it is no longer
            // needed and it is not the main process thread.
            if(result == TIMED_OUT && !isMain) {
                break;
            }
        } while (result != -ECONNREFUSED && result != -EBADF);
    
        LOG_THREADPOOL("**** THREAD %p (PID %d) IS LEAVING THE THREAD POOL err=%p\n",
            (void*)pthread_self(), getpid(), (void*)result);
        
        mOut.writeInt32(BC_EXIT_LOOPER);
        talkWithDriver(false);
    }
    
    status_t IPCThreadState::getAndExecuteCommand()
    {
    status_t result;
        int32_t cmd;
    
        result = talkWithDriver();
        if (result >= NO_ERROR) {
            size_t IN = mIn.dataAvail();
            if (IN < sizeof(int32_t)) return result;
            cmd = mIn.readInt32();
            IF_LOG_COMMANDS() {
                alog << "Processing top-level Command: "
                     << getReturnString(cmd) << endl;
            }
    
            pthread_mutex_lock(&mProcess->mThreadCountLock);
            mProcess->mExecutingThreadsCount++;
            pthread_mutex_unlock(&mProcess->mThreadCountLock);
    
            result = executeCommand(cmd);
    
    }
    
    status_t IPCThreadState::talkWithDriver(bool doReceive)
    {
     
        binder_write_read bwr;
        const bool needRead = mIn.dataPosition() >= mIn.dataSize();//false
        const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0; //doReceive = true needRead =false
        //所以outAvail  =0
        
        bwr.write_size = outAvail;//bwr.write_size=0
        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;
        }
       
        bwr.write_consumed = 0;
        bwr.read_consumed = 0;
    #if defined(HAVE_ANDROID_OS)
            if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)//开始读取数据,并挂起
                err = NO_ERROR;
    

    binder.c

    /读取数据
    static int binder_thread_read(struct binder_proc *proc,
                      struct binder_thread *thread,
                      binder_uintptr_t binder_buffer, size_t size,
                      binder_size_t *consumed, int non_block){
    
    wait_event_freezable_exclusive//挂起线程
    //被客户端进程唤醒
    while (1) {
            uint32_t cmd;
            struct binder_transaction_data tr;
            struct binder_work *w;
            struct binder_transaction *t = NULL;
    
            if (!list_empty(&thread->todo)) {/
                w = list_first_entry(&thread->todo, struct binder_work,
                             entry);//w不为空
        if (t->buffer->target_node) {
                struct binder_node *target_node = t->buffer->target_node;
    
                tr.target.ptr = target_node->ptr;
                tr.cookie =  target_node->cookie;
                t->saved_priority = task_nice(current);
                if (t->priority < target_node->min_priority &&
                    !(t->flags & TF_ONE_WAY))
                    binder_set_nice(t->priority);
                else if (!(t->flags & TF_ONE_WAY) ||
                     t->saved_priority > target_node->min_priority)
                    binder_set_nice(target_node->min_priority);
                cmd = BR_TRANSACTION;//关键设置cmd为BR_TRANSACTION
    if (copy_to_user(ptr, &tr, sizeof(tr)))//拷贝数据给
    
    //executeCommand方法
       case BR_TRANSACTION:
            {
                binder_transaction_data tr;
                result = mIn.read(&tr, sizeof(tr));
                Parce buffer;
                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)) {  
                        //调用到服务端native层的BBinder的transat,BBinder的子类为JavaBBindner 所以调用了android-util_Binder.JavaBBinder C++的onTransact->Binder.java的execTransact->onTransact,最终实现了跨进程通信
                        error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,
                                &reply, tr.flags);
                        reinterpret_cast<BBinder*>(tr.cookie)->decStrong(this);
                    } else {
                        error = UNKNOWN_TRANSACTION;
                    }
    
    

    相关文章

      网友评论

          本文标题:Android进程间通信(七)——客户端调用服务端onTrans

          本文链接:https://www.haomeiwen.com/subject/auuvpltx.html