Android Framework原理 -- service_manager服务获取流程分析

1,227 阅读10分钟

在上一节中,我们对于Binder底层驱动源码做了具体分析,当service_manager服务启动之后,打开了binder驱动,并做了内存映射关系,那么接下来我们继续关注service_manager源码,看如何注册服务并传递数据的。

1 service_manager注册流程分析

我们再次回到service_manager的入口函数中,前面我们分析了binder_open主要做了什么 ,我们继续往下看

int main(int argc, char** argv)
{
    struct binder_state *bs;
    union selinux_callback cb;
    char *driver;

    if (argc > 1) {
        driver = argv[1];
    } else {
        driver = "/dev/binder";
    }

    bs = binder_open(driver, 128*1024);
    //......

    if (binder_become_context_manager(bs)) {
        ALOGE("cannot become context manager (%s)\n", strerror(errno));
        return -1;
    }

    cb.func_audit = audit_callback;
    selinux_set_callback(SELINUX_CB_AUDIT, cb);
    cb.func_log = selinux_log_callback;
    selinux_set_callback(SELINUX_CB_LOG, cb);

#ifdef VENDORSERVICEMANAGER
    sehandle = selinux_android_vendor_service_context_handle();
#else
    sehandle = selinux_android_service_context_handle();
#endif
    selinux_status_open(true);

    if (sehandle == NULL) {
        ALOGE("SELinux: Failed to acquire sehandle. Aborting.\n");
        abort();
    }

    if (getcon(&service_manager_context) != 0) {
        ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n");
        abort();
    }


    binder_loop(bs, svcmgr_handler);

    return 0;
}

打开Binder驱动之后,返回一个句柄bs,然后调用了binder_become_context_manager,将service_manager设置为了大管家,我们看下binder_become_context_manager具体做了什么?

1.1 binder_become_context_manager源码分析

int binder_become_context_manager(struct binder_state *bs)
{
    //调用binder驱动方法
    return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}

在binder_become_context_manager方法中,我们看到只是调用了ioctl方法,看到这个我们就知道,肯定是调用了binder驱动的binder_ioctl方法。

static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
   //.....

   switch (cmd) {
   case BINDER_WRITE_READ:
      ret = binder_ioctl_write_read(filp, cmd, arg, thread);
      if (ret)
         goto err;
      break;
   case BINDER_SET_MAX_THREADS:
      if (copy_from_user(&proc->max_threads, ubuf, sizeof(proc->max_threads))) {
         ret = -EINVAL;
         goto err;
      }
      break;
   case BINDER_SET_CONTEXT_MGR:
      ret = binder_ioctl_set_ctx_mgr(filp);
      if (ret)
         goto err;
      ret = security_binder_set_context_mgr(proc->tsk);
      if (ret < 0)
         goto err;
      break;
   case BINDER_THREAD_EXIT:
      binder_debug(BINDER_DEBUG_THREADS, "%d:%d exit\n",
              proc->pid, thread->pid);
      binder_free_thread(proc, thread);
      thread = NULL;
      break;
   case BINDER_VERSION: {
      struct binder_version __user *ver = ubuf;

      if (size != sizeof(struct binder_version)) {
         ret = -EINVAL;
         goto err;
      }
      if (put_user(BINDER_CURRENT_PROTOCOL_VERSION,
              &ver->protocol_version)) {
         ret = -EINVAL;
         goto err;
      }
      break;
   }
   default:
      ret = -EINVAL;
      goto err;
   }
   ret = 0;
}

在service_manager中传入的cmd命令是BINDER_SET_CONTEXT_MGR,那么我们可以直接从上面的代码中找到,是调用了binder_ioctl_set_ctx_mgr方法:

static int binder_ioctl_set_ctx_mgr(struct file *filp)
{
   int ret = 0;
   struct binder_proc *proc = filp->private_data;
   //......
   binder_context_mgr_node = binder_new_node(proc, 0, 0);
   if (binder_context_mgr_node == NULL) {
      ret = -ENOMEM;
      goto out;
   }
   binder_context_mgr_node->local_weak_refs++;
   binder_context_mgr_node->local_strong_refs++;
   binder_context_mgr_node->has_strong_ref = 1;
   binder_context_mgr_node->has_weak_ref = 1;
out:
   return ret;
}

在这个方法中,首先获取到了当前进程的binder_proc对象,调用binder_new_node方法,创建了一个binder_node对象,并赋值给了binder_context_mgr_node,因为在Binder中会处处使用这个对象,因此为了快速查找到service_manager,而创建的一个全局对象

static struct binder_node *binder_new_node(struct binder_proc *proc,
                  binder_uintptr_t ptr,
                  binder_uintptr_t cookie)
{
   struct rb_node **p = &proc->nodes.rb_node;
   struct rb_node *parent = NULL;
   struct binder_node *node;

   while (*p) {
      parent = *p;
      node = rb_entry(parent, struct binder_node, rb_node);

      if (ptr < node->ptr)
         p = &(*p)->rb_left;
      else if (ptr > node->ptr)
         p = &(*p)->rb_right;
      else
         return NULL;
   }

   node = kzalloc(sizeof(*node), GFP_KERNEL);
   if (node == NULL)
      return NULL;
   binder_stats_created(BINDER_STAT_NODE);
   rb_link_node(&node->rb_node, parent, p);
   rb_insert_color(&node->rb_node, &proc->nodes);
   node->debug_id = ++binder_last_id;
   node->proc = proc;
   node->ptr = ptr;
   node->cookie = cookie;
   node->work.type = BINDER_WORK_NODE;
   INIT_LIST_HEAD(&node->work.entry);
   INIT_LIST_HEAD(&node->async_todo);
   binder_debug(BINDER_DEBUG_INTERNAL_REFS,
           "%d:%d node %d u%016llx c%016llx created\n",
           proc->pid, current->pid, node->debug_id,
           (u64)node->ptr, (u64)node->cookie);
   return node;
}

所以binder_become_context_manager做的主要工作就是:
(1)创建binder_node,目的为了快速查找到service_manager,达到大管家的目的;
(2)创建了work和async_todo队列,类似于MessageQueue

1.2 binder_loop源码分析

在将service_manager设置为大管家之后,调用了binder_loop方法,这个有点类似于Looper中的loop方法,看下源码:

void binder_loop(struct binder_state *bs, binder_handler func)
{
    int res;
    struct binder_write_read bwr;
    uint32_t readbuf[32];
    //初始化
    bwr.write_size = 0;
    bwr.write_consumed = 0;
    bwr.write_buffer = 0;
    //开启looper循环
    readbuf[0] = BC_ENTER_LOOPER;
    //①
    binder_write(bs, readbuf, sizeof(uint32_t));

    for (;;) {
        bwr.read_size = sizeof(readbuf);
        bwr.read_consumed = 0;
        bwr.read_buffer = (uintptr_t) readbuf;
        //②
        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);

        if (res < 0) {
            ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
            break;
        }

        res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
        if (res == 0) {
            ALOGE("binder_loop: unexpected reply?!\n");
            break;
        }
        if (res < 0) {
            ALOGE("binder_loop: io error %d %s\n", res, strerror(errno));
            break;
        }
    }
}

在binder_loop中,声明了一个读写结构体binder_write_read,并将其初始化;
①:然后调用了binder_write方法,执行了BC_ENTER_LOOPER命令

int binder_write(struct binder_state *bs, void *data, size_t len)
{
    struct binder_write_read bwr;
    int res;

    bwr.write_size = len;
    bwr.write_consumed = 0;
    bwr.write_buffer = (uintptr_t) data;
    bwr.read_size = 0;
    bwr.read_consumed = 0;
    bwr.read_buffer = 0;
    //这里执行了读写操作
    res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
    if (res < 0) {
        fprintf(stderr,"binder_write: ioctl failed (%s)\n",
                strerror(errno));
    }
    return res;
}

我们看到还是执行了底层驱动的binder_ioctl方法,命令为BINDER_WRITE_READ,所以对应执行了binder_ioctl_write_read方法

static int binder_ioctl_write_read(struct file *filp,
            unsigned int cmd, unsigned long arg,
            struct binder_thread *thread)
{
   int ret = 0;
   struct binder_proc *proc = filp->private_data;
   unsigned int size = _IOC_SIZE(cmd);
   void __user *ubuf = (void __user *)arg;
   struct binder_write_read bwr;

   if (size != sizeof(struct binder_write_read)) {
      ret = -EINVAL;
      goto out;
   }
   if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {
      ret = -EFAULT;
      goto out;
   }
   binder_debug(BINDER_DEBUG_READ_WRITE,
           "%d:%d write %lld at %016llx, read %lld at %016llx\n",
           proc->pid, thread->pid,
           (u64)bwr.write_size, (u64)bwr.write_buffer,
           (u64)bwr.read_size, (u64)bwr.read_buffer);

   if (bwr.write_size > 0) {
      ret = binder_thread_write(proc, thread,
                 bwr.write_buffer,
                 bwr.write_size,
                 &bwr.write_consumed);
      trace_binder_write_done(ret);
      if (ret < 0) {
         bwr.read_consumed = 0;
         if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
            ret = -EFAULT;
         goto out;
      }
   }
   if (bwr.read_size > 0) {
      ret = binder_thread_read(proc, thread, bwr.read_buffer,
                bwr.read_size,
                &bwr.read_consumed,
                filp->f_flags & O_NONBLOCK);
      trace_binder_read_done(ret);
      if (!list_empty(&proc->todo))
         wake_up_interruptible(&proc->wait);
      if (ret < 0) {
         if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
            ret = -EFAULT;
         goto out;
      }
   }
   binder_debug(BINDER_DEBUG_READ_WRITE,
           "%d:%d wrote %lld of %lld, read return %lld of %lld\n",
           proc->pid, thread->pid,
           (u64)bwr.write_consumed, (u64)bwr.write_size,
           (u64)bwr.read_consumed, (u64)bwr.read_size);
   if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {
      ret = -EFAULT;
      goto out;
   }
out:
   return ret;
}

我们看到Binder驱动读写操作是根据读写结构体的write_size或者read_size是否大于0来进行读写,因为在binder_write中,我们看到write_size > 0,因此执行写操作,对应执行binder_thread_write方法,这个方法中同样是根据命令来执行,我们只需要看BC_ENTER_LOOPER对应的代码块。

case BC_ENTER_LOOPER:
   binder_debug(BINDER_DEBUG_THREADS,
           "%d:%d BC_ENTER_LOOPER\n",
           proc->pid, thread->pid);
   if (thread->looper & BINDER_LOOPER_STATE_REGISTERED) {
      thread->looper |= BINDER_LOOPER_STATE_INVALID;
      binder_user_error("%d:%d ERROR: BC_ENTER_LOOPER called after BC_REGISTER_LOOPER\n",
         proc->pid, thread->pid);
   }
   thread->looper |= BINDER_LOOPER_STATE_ENTERED;
   break;

这个时候,就是设置了一个状态BINDER_LOOPER_STATE_ENTERED,告诉驱动已经进入了looper循环的状态了。

②:然后进入死循环,又调用了一次ioctl方法,这个时候的
read_size > 0,read_consumed = 0
可以进行读操作,看下binder_thread_read方法

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)
{
   void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
   void __user *ptr = buffer + *consumed;
   void __user *end = buffer + size;

   int ret = 0;
   int wait_for_proc_work;

   if (*consumed == 0) {
      if (put_user(BR_NOOP, (uint32_t __user *)ptr))
         return -EFAULT;
      ptr += sizeof(uint32_t);
   }
    //这里wait_for_proc_work = true
    wait_for_proc_work = thread->transaction_stack == NULL &&
             list_empty(&thread->todo);
    //......
    if (wait_for_proc_work) {
       //......
       if (non_block) {
          if (!binder_has_proc_work(proc, thread))
             ret = -EAGAIN;
       } else
          ret = wait_event_freezable_exclusive(proc->wait, binder_has_proc_work(proc, thread));
    } else {
       if (non_block) {
          if (!binder_has_thread_work(thread))
             ret = -EAGAIN;
       } else
          ret = wait_event_freezable(thread->wait, binder_has_thread_work(thread));
    }

(1)因为进入死循环之后,设置了read_consumed = 0,因此在binder_thread_read中,会设置一个BR_NOOP标志;
(2)接着wait_for_proc_work这个变量,因为一开始队列里都没有任务,所以为true;
(3)然后有一系列判断完成,调用wait_event_freezable_exclusive进入了等待的状态,如果后续有消息发送进来就会处理。

所以binder_loop主要做了2件事:
(1)设置Looper的状态为BINDER_LOOPER_STATE_ENTERED,代表着已经进入了Looper循环中;
(2)进入死循环之后,去读数据,进入等待状态;

以上就代表着service_manager已经注册完成了。

image.png

2 获取service_manager流程分析

一般情况下,在native层注册服务到sm需要获取到sm,那么我们需要看一下,获取sm服务的流程。

2.1 native层

在native层获取sm服务,我们看下源码:

//http://androidxref.com/9.0.0_r3/xref/frameworks/native/libs/binder/IServiceManager.cpp

namespace android {

sp<IServiceManager> defaultServiceManager()
{
    if (gDefaultServiceManager != NULL) return gDefaultServiceManager;

    {
        AutoMutex _l(gDefaultServiceManagerLock);
        while (gDefaultServiceManager == NULL) {
            gDefaultServiceManager = interface_cast<IServiceManager>(
                ProcessState::self()->getContextObject(NULL));
            if (gDefaultServiceManager == NULL)
                sleep(1);
        }
    }

    return gDefaultServiceManager;
}

应用层向native层注册服务的时候,为了获取sm服务,就是调用defaultServiceManager这个方法,该方法是一个单例,如果gDefaultServiceManager是空的,那么会调用 interface_cast<IServiceManager>( ProcessState::self()->getContextObject(NULL))去获取。

2.1.1 ProcessState::self()

首先,我们先看下ProcessState这个参数具体做了什么

ProcessState::self()->getContextObject(NULL)

首先,我们看ProcessState的self方法,其实就是创建了一个ProcessState对象

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

在ProcessState的构造方法中,传入了/dev/binder路径,看到这个,我们肯定知道是要打开Binder驱动,然后设置一个最大线程数DEFAULT_MAX_BINDER_THREADS = 15;

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);
        if (mVMStart == MAP_FAILED) {
            // *sigh*
            ALOGE("Using %s failed: unable to mmap transaction memory.\n", mDriverName.c_str());
            close(mDriverFD);
            mDriverFD = -1;
            mDriverName.clear();
        }
    }

    LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened.  Terminating.");
}

因为defaultServiceManager是单例,因此每个进程只拥有一个ProcessState,打开Binder驱动之后,调用mmap向驱动层申请内存映射;

image.png

在此之前,我们看到sm服务开启之后,内核空间开辟的内存为128K,而普通服务来注册的时候,内核空间开辟的内存为BINDER_VM_SIZE 也就是 1M-8k

#define BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2)

总结:ProcessState::self()做了什么事?
(1)打开Binder驱动;
(2)设置最大Binder线程数15
(3)mmap内存映射,1M-8k

ProcessState::self()是每个服务来注册时候都需要创建一次,且仅有一次

2.2.2 getContextObject

sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
    return getStrongProxyForHandle(0);
}
//具体调用
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
    sp<IBinder> result;
    AutoMutex _l(mLock);
    handle_entry* e = lookupHandleLocked(handle);

    if (e != NULL) {
    
        IBinder* b = e->binder;
        if (b == NULL || !e->refs->attemptIncWeak(this)) {
            if (handle == 0) {
                Parcel data;
                status_t status = IPCThreadState::self()->transact(
                        0, IBinder::PING_TRANSACTION, data, NULL, 0);
                if (status == DEAD_OBJECT)
                   return NULL;
            }
            //核心点
            b = BpBinder::create(handle);
            e->binder = b;
            if (b) e->refs = b->getWeakRefs();
            result = b;
        } else {
            result.force_set(b);
            e->refs->decWeak(this);
        }
    }

    return result;
}

在创建ProcessState之后,调用了getContextObject方法,其实是调用了getStrongProxyForHandle,我们看下这个方法,核心点在于创建了BpBinder对象,并返回;

BpBinder我们可以将它看做是客户端的对象,尤其是方法名中带有一个Proxy,可以往这儿联想就是服务端的一个代理对象,也就是说

ProcessState::self()->getContextObject(NULL)

最终返回的就是一个BpBinder对象。

2.2.3 interface_cast

interface_cast<IServiceManager>(BpBinder);

接下来我们需要处理的就是interface_cast做了什么类型转换

template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
    return INTERFACE::asInterface(obj);
}

我们看到interface_cast其实是一个模板函数,然后通过定义我们知道,其实下面两行代码是等价的

interface_cast<IServiceManager>(BpBinder);
==
IServiceManager::asInterface(BpBinder);

再做一次具体的转换,最终得到的是BpServiceManager对象

#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                       \
    const ::android::String16 I##INTERFACE::descriptor(NAME);           \
    const ::android::String16&                                          \
            I##INTERFACE::getInterfaceDescriptor() const {              \
        return I##INTERFACE::descriptor;                                \
    }                                                                   \
    ::android::sp<I##INTERFACE> I##INTERFACE::asInterface(              \
            const ::android::sp<::android::IBinder>& obj)               \
    {                                                                   \
        ::android::sp<I##INTERFACE> intr;                               \
        if (obj != NULL) {                                              \
            intr = static_cast<I##INTERFACE*>(                          \
                obj->queryLocalInterface(                               \
                        I##INTERFACE::descriptor).get());               \
            if (intr == NULL) {                                         \
                intr = new Bp##INTERFACE(obj);                          \
            }                                                           \
        }                                                               \
        return intr;                                                    \
    }                                                                   \
    I##INTERFACE::I##INTERFACE() { }                                    \
    I##INTERFACE::~I##INTERFACE() { }   

也就是说defaultServiceManager方法,最终拿到的就是BpServiceManager(BpBinder)

2.2.4 BpServiceManager

看下BpServiceManager的构造函数,是实现了BpInterface接口

explicit BpServiceManager(const sp<IBinder>& impl)
    : BpInterface<IServiceManager>(impl)
{
}

我们看BpInterface接口是将BpBinder作为BpRefBase的mRemote变量赋值,如果我们写过aidl通信,想必对于mRemote是比较熟悉了,它其实是一个BinderProxy(应用层),那么在native层,它就是BpBinder。

inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)
    : BpRefBase(remote)
{
}
class BpRefBase : public virtual RefBase
{
protected:
    explicit                BpRefBase(const sp<IBinder>& o);
    virtual                 ~BpRefBase();
    virtual void            onFirstRef();
    virtual void            onLastStrongRef(const void* id);
    virtual bool            onIncStrongAttempted(uint32_t flags, const void* id);

    inline  IBinder*        remote()                { return mRemote; }
    inline  IBinder*        remote() const          { return mRemote; }

private:
                            BpRefBase(const BpRefBase& o);
    BpRefBase&              operator=(const BpRefBase& o);

    IBinder* const          mRemote;
    RefBase::weakref_type*  mRefs;
    std::atomic<int32_t>    mState;
};

image.png

现在梳理一下在native层注册服务时,如何获取sm

(1)首先调用defaultServiceManager方法,在这个方法中,干的最主要的事就是创建了BpServiceManager,其内部封装了BpBinder;

(2)BpBinder是BpRefBase的一个成员变量,子类可以通过调用remote方法来获取mRemote对象,也就是能够获取到BpBinder对象,其中BpServiceManager继承自BpRefBase

3 从AIDL理解Stub和Proxy机制

在Android系统重,进程间通信的方式有很多,如果想要实现实时精准的进程间通信,往往使用aidl

interface IMyTransport {
    void send(String valiue);
}

在创建一个aidl接口之后,需要重新build一次工程,就能生成对应的类;使用aidl必然使用到服务,如果在进程内使用,那么onBind直接返回null即可;

class MyService : Service() {
    override fun onBind(intent: Intent?): IBinder? {
        return null
    }
}

如果需要跨进程通信,那么就需要返回一个Binder对象,这个对象是具备跨进程通信能力的

image.png

class MyService : Service() {
    override fun onBind(intent: Intent?): IBinder? {
        return MyBinder()
    }


    inner class MyBinder : IMyTransport.Stub(){
        override fun send(valiue: String?) {
            
        }
    }
}

那么既然要实现跨进程通信,那么客户端也需要持有这个aidl文件,而且包名必须要一致,因此需要拷贝一份到客户端。

findViewById<Button>(R.id.btn_start).setOnClickListener {
    //启动服务
    val intent = Intent()
    intent.setComponent(ComponentName("com.lay.mvi","com.lay.mvi.aidl.MyService"))
    bindService(intent, MyServiceConnection(),Context.BIND_AUTO_CREATE)
}

class MyServiceConnection : ServiceConnection{
    override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
        //拿到服务端代理对象
        val stub = IMyTransport.Stub.asInterface(service) as IMyTransport
        stub.send("你好,这是从客户端发送来的消息")
    }

    override fun onServiceDisconnected(name: ComponentName?) {

    }

}

当拿到了服务端的代理对象(IMyTransport.Stub.asInterface(service))之后,调用服务端的方法给服务端发送消息,这样就实现了简单的进程间通信。

3.1 应用层分析进程间通信

首先我们看下aidl是如何实现跨进程的:

image.png

本节开始提到的2个角色Stub和Proxy,其中Stub(我们可以把它看成是服务端)继承自Binder,并实现了我们自定义的aidl接口,这也就意味着服务端具备了跨进程的能力。

Proxy同样也实现了我们自定义的aidl接口,而且内部持有了一个IBinder对象(BinderProxy),我们可以认为持有的这个对象就是服务端的代理对象

private static class Proxy implements com.lay.mvi.IMyTransport
{
  private android.os.IBinder mRemote;
  Proxy(android.os.IBinder remote)
  {
    mRemote = remote;
  }
  @Override public android.os.IBinder asBinder()
  {
    return mRemote;
  }
  public java.lang.String getInterfaceDescriptor()
  {
    return DESCRIPTOR;
  }
}

我们看到,当客户端准备向服务端发送消息的时候,调用了IMyTransport.Stub.asInterface(service)方法,我们看下asInterface里面做了啥。

private static final java.lang.String DESCRIPTOR = "com.lay.mvi.IMyTransport"

/** Construct the stub at attach it to the interface. */
public Stub()
{
  this.attachInterface(this, DESCRIPTOR);
}
/**
 * Cast an IBinder object into an com.lay.mvi.IMyTransport interface,
 * generating a proxy if needed.
 */
public static com.lay.mvi.IMyTransport asInterface(android.os.IBinder obj)
{
  if ((obj==null)) {
    return null;
  }
  android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
  if (((iin!=null)&&(iin instanceof com.lay.mvi.IMyTransport))) {
    return ((com.lay.mvi.IMyTransport)iin);
  }
  return new com.lay.mvi.IMyTransport.Stub.Proxy(obj);
}

(1)在服务端进程创建Stub对象(也就是Binder对象)的时候,调用了attachInterface方法,将DESCRIPTOR信息与服务端绑定;
(2)在客户端进程中,调用Stub类的asInterface方法时,首先会调用queryLocalInterface方法,从本地查找DESCRIPTOR对应的服务端进程,如果是同进程内,那么一定是拿到的;因为现在是在客户端进程,那么取不到,iin = null,因此直接返回了一个Proxy对象;
(3)在Proxy的构造方法中,我们看到传入的是一个IBinder对象,这个远端对象其实就是服务端的代理对象,我们调用服务端对象的某个方法,便可以实现跨进程通信。

@Override public void send(java.lang.String valiue) throws android.os.RemoteException
{
  android.os.Parcel _data = android.os.Parcel.obtain();
  android.os.Parcel _reply = android.os.Parcel.obtain();
  try {
    _data.writeInterfaceToken(DESCRIPTOR);
    _data.writeString(valiue);
    //客户端调用
    boolean _status = mRemote.transact(Stub.TRANSACTION_send, _data, _reply, 0);
    if (!_status && getDefaultImpl() != null) {
      getDefaultImpl().send(valiue);
      return;
    }
    _reply.readException();
  }
  finally {
    _reply.recycle();
    _data.recycle();
  }
}

所以在客户端调用send方法的时候,其实就是调用了Proxy的send方法,在将传递的数据序列化之后,交由mRemote对象的transact方法,发送一个消息TRANSACTION_send给服务端

@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
  java.lang.String descriptor = DESCRIPTOR;
  switch (code)
  {
    case INTERFACE_TRANSACTION:
    {
      reply.writeString(descriptor);
      return true;
    }
    //在这里进行客户端数据的处理
    case TRANSACTION_send:
    {
      data.enforceInterface(descriptor);
      java.lang.String _arg0;
      _arg0 = data.readString();
      this.send(_arg0);
      reply.writeNoException();
      return true;
    }
    default:
    {
      return super.onTransact(code, data, reply, flags);
    }
  }
}

然后服务端接收到了这个消息之后,取出携带的数据,再次调用服务端的send方法,这样就拿到了客户端发送的消息,在MyService的send方法中,获取到数据。

image.png

在客户端发送消息的时候,其实是调用了Proxy的mRemote对象,在第2节中我们知道,这个mRemote在native层其实就是BpBinder