Binder 框架 -- binder 用户空间框架

Binder 框架 -- binder 用户空间框架

一 ServiceManager 启动

int main(int argc, char **argv)
{
    struct binder_state *bs;

    bs = binder_open(128*1024);
    if (!bs) {
        ALOGE("failed to open binder driver\n");
        return -1;
    }

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

    ......

    binder_loop(bs, svcmgr_handler);

    return 0;
}

1. 打开binder 设备

bs = binder_open(128*1024); 打开binder 设备驱动。相关的信息保存在binder_state 结构中。

struct binder_state
{
     int fd;                binder 设备的fd
     void *mapped;          映射到用户空间的地址
     size_t mapsize;        大小 
};

struct binder_state *binder_open(size_t mapsize)
{
    struct binder_state *bs;
    struct binder_version vers;

    bs = malloc(sizeof(*bs));
    if (!bs) {
        errno = ENOMEM;
        return NULL;
    }

    bs->fd = open("/dev/binder", O_RDWR | O_CLOEXEC);


    if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
        (vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {
        ......
    }

    bs->mapsize = mapsize;
    bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);


    return bs;
}

binder_open 中做的工作主要是打开binder 设备,然后通过mmap 将binder内核空间映射到用户空间。标准的linux 设备访问方法:

  1. open("/dev/binder", O_RDWR | O_CLOEXEC); 打开设备
  2. ioctl(bs->fd, BINDER_VERSION, &vers) ioctl 命令设置版本号。 在下面对binder 驱动的访问中主要是通过 ioctl 函数,没有用我们常见的 read write, 这个也是binder 驱动设计的一个特点
  3. mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0); 内核空间mapsize大小映射到用户空间,注意映射的空间是只读权限。
  4. 设备的文件描述符, 用户空间地址, 大小用binder_state结构体保存。

2. binder_become_context_manager 通知binder驱动成为管理者。

int binder_become_context_manager(struct binder_state *bs)
{
    return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}

注意最后一个参数为0;函数设计上可能是为了表示ServiceManager hander为0.但是在驱动中收到的消息为BINDER_SET_CONTEXT_MGR,已经表示是表示ServiceManager自己,直接把自己的 hander置为0,没有使用这个参数。ServiceManager 本身管理服务的特殊性,没有其它进程负责它的注册,ServiceManager需要自己完成注册,同时自己的handler 为0.

3. binder_loop 进入循环

binder_loop调用的时候同时传入回调函数。

  1. binder_write(bs, readbuf, sizeof(uint32_t)); 调用 ioctl(bs->fd, BINDER_WRITE_READ, &bwr); 通知binder 驱动进入循环。这次调用没有阻塞。
  2. 在 for 循环中的 res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); 阻塞,当有消息来得时候,读出数据,交给binder_parse解析同时指定svcmgr_handler func处理解析数据。
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;

    readbuf[0] =  ;
    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;
        }
    }
}

4. svcmgr_handler 处理信息

svcmgr_handler func 函数指针指向svcmgr_handler
信息主要有这几个类型:

  • SVC_MGR_GET_SERVICE 获取服务
  • SVC_MGR_CHECK_SERVICE 检查服务
  • SVC_MGR_ADD_SERVICE 添加服务,如mediaservice 添加就会到这里
  • SVC_MGR_LIST_SERVICES 主要是 service list 命令使用
int svcmgr_handler(struct binder_state *bs,
                   struct binder_transaction_data *txn,
                   struct binder_io *msg,
                   struct binder_io *reply)
{
    struct svcinfo *si;
    uint16_t *s;
    size_t len;
    uint32_t handle;
    uint32_t strict_policy;
    int allow_isolated;

    if (txn->target.ptr != BINDER_SERVICE_MANAGER)
        return -1;

    if (txn->code == PING_TRANSACTION)
        return 0;
    ......

    switch(txn->code) {
    case SVC_MGR_GET_SERVICE:
    case SVC_MGR_CHECK_SERVICE:
        s = bio_get_string16(msg, &len);
        if (s == NULL) {
            return -1;
        }
        handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid);
        if (!handle)
            break;
        bio_put_ref(reply, handle);
        return 0;

    case SVC_MGR_ADD_SERVICE:
        s = bio_get_string16(msg, &len);
        if (s == NULL) {
            return -1;
        }
        handle = bio_get_ref(msg);
        allow_isolated = bio_get_uint32(msg) ? 1 : 0;
        if (do_add_service(bs, s, len, handle, txn->sender_euid,
            allow_isolated, txn->sender_pid))
            return -1;
        break;

    case SVC_MGR_LIST_SERVICES: {
        uint32_t n = bio_get_uint32(msg);

        if (!svc_can_list(txn->sender_pid)) {
            ALOGE("list_service() uid=%d - PERMISSION DENIED\n",
                    txn->sender_euid);
            return -1;
        }
        si = svclist;
        while ((n-- > 0) && si)
            si = si->next;
        if (si) {
            bio_put_string16(reply, si->name);
            return 0;
        }
        return -1;
    }
    default:
        ALOGE("unknown code %d\n", txn->code);
        return -1;
    }

    bio_put_uint32(reply, 0);
    return 0;
}

5 servicemanager 是一单线程,

可能因为是工作不太繁忙,不需要多线程加班。
ps -t | grep servicemanager
system 2450 1761 10228 752 ffffffff f7685976 S /system/bin/servicemanager

servicemanager 已经启动,并且在一个while 循环中阻塞,等待唤醒。

ProcessState

ProcessState 是单例模式,每个进程只有一个实例。ProcessState在构造函数中会打开binder 驱动获取文件描述符mDriverFD,设置binder的参数,为进程进行binder 通信准备必要的条件。

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

ProcessState::ProcessState()
    : mDriverFD(open_driver())
    , mVMStart(MAP_FAILED)
    , mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
    , mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
    , mExecutingThreadsCount(0)
    , mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
    , mManagesContexts(false)
    , mBinderContextCheckFunc(NULL)
    , mBinderContextUserData(NULL)
    , mThreadPoolStarted(false)
    , mThreadPoolSeq(1)
{
     if (mDriverFD >= 0) {
         mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
    }
 }

static int open_driver()
{
    int fd = open("/dev/binder", O_RDWR | O_CLOEXEC);
    if (fd >= 0) {
        int vers = 0;
        status_t result = ioctl(fd, BINDER_VERSION, &vers);
        
        size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
        result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
        }
    } else {
    
    }
    return fd;
}

open_driver 函数和binder_open 差不多,打开设备驱动,设置版本号并检查, 然后设置BINDER_SET_MAX_THREADS ,支持的最大线程数。

  1. open("/dev/binder", O_RDWR | O_CLOEXEC);
  2. octl(fd, BINDER_VERSION, &vers);
  3. ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
  4. 最后在构造函数中mmap。 为什么不在 open_driver 中一起把这个事情给做了呢?从API调用的角度放在一起比较合适吧。

startThreadPool 函数

从名字上看启动一个线程池,创建一个新的线程,spawnPooledThread isMain 参数为true,new了一个PoolThread,然后run函数 启动threadLoop(),在threadLoop 调用 IPCThreadState::self()->joinThreadPool(mIsMain); 对线程调用的封装,具体可以参考线程使用的方法。

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;
};

IPCThreadState

IPCThreadState 是一个线程单例模式

IPCThreadState 是一个看似单例却不是单例的类。主要涉及了线程的局部存储,看下self 的实现:
第一次进来 gHaveTLS == false 所以走下边的代码:

  1. if (pthread_key_create(&gTLS, threadDestructor) != 0)
    创建线程的局部存储然后goto 到 restart;
  2. 调用pthread_getspecific,由于线程的局部key k还没有关联变量这是返回值为空;所以
    new IPCThreadState;看到这里很疑惑,创建了线程的局部存储key 却没有变量存储到线程的局部存储里面,直接new 了一个IPCThreadState,和self 函数名也不匹配,搞什么鬼呢。
  3. 继续看IPCThreadState的构造函数:这下明白了 在构造函数里面IPCThreadState把自己作为线程的局部存储
    pthread_setspecific(gTLS, this);
  4. 如果是第二次进来 gHaveTLS == true.直接pthread_getspecific 获取IPCThreadState自身。

IPCThreadState 是一个线程单例模式, 持有两个类型为Parcel 的变量

class IPCThreadState{

            ......        
private:
       Parcel              mIn;
       Parcel              mOut;
}

IPCThreadState* IPCThreadState::self()
{
    if (gHaveTLS) {
restart:
        const pthread_key_t k = gTLS;
        IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
        if (st) return st;
        return new IPCThreadState;
    }
    
    if (gShutdown) return NULL;
    
    pthread_mutex_lock(&gTLSMutex);
    if (!gHaveTLS) {
        if (pthread_key_create(&gTLS, threadDestructor) != 0) {
            pthread_mutex_unlock(&gTLSMutex);
            return NULL;
        }
        gHaveTLS = true;
    }
    pthread_mutex_unlock(&gTLSMutex);
    goto restart;
}

IPCThreadState::IPCThreadState()
    : mProcess(ProcessState::self()),
      mMyThreadId(gettid()),
      mStrictModePolicy(0),
      mLastTransactionBinderFlags(0)
{
    pthread_setspecific(gTLS, this);
    clearCaller();
    mIn.setDataCapacity(256);
    mOut.setDataCapacity(256);
}

IPCThreadState::joinThreadPool

在上面的ProcessState::startThreadPool() 中调用了IPCThreadState::joinThreadPool 那这个函数到底干了什么呢。

  1. 首先根据是否主线程 mOut.writeInt32,注意参数为BC_ENTER_LOOPER 或者BC_REGISTER_LOOPER 这个后边分析。
  2. 在一个循环中不停的getAndExecuteCommand。
  3. 在getAndExecuteCommand 首先talkWithDriver, 然后executeCommand,和ServiceManager 类似,在一个循环中不停的读取binder 驱动,然后解析数据。

到这里其实服务端和客户端的交互框架已经建立。在后边的MediaPlayerService中看下具体的细节。

void IPCThreadState::joinThreadPool(bool isMain)
{   
    mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
     
    status_t result;
    do {
        ......
        result = getAndExecuteCommand();
        ......
    } while (result != -ECONNREFUSED && result != -EBADF);

    ......
}

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();
 
        result = executeCommand(cmd);
        ......
        }
    }

    return result;
}

Binder 通信架构

Android 为了便于使用Binder 通信,提供了一套框架,只要继承这个框架的各个类,就能够实现一个Binder通信服务。主要分为代理端和服务端。代理端和服务端通的通信通过 IInterface BpInterface BnInterface IBinder BpBinder BBinder 这几个模板类进行。

binder 下的相关类类图:


binder 对象图

MediaPlayerService 启动

ServiceManager 单独运行在一个进程中,其它的Android系统服务如MediaPlayerService 如何启动和注册呢,在ServiceManager 的启动过程中分析到有一个 SVC_MGR_ADD_SERVICE 处理流程,在while 循环中已经阻塞。在上面分析IPCThreadState::joinThreadPool 的时候也会在循环中阻塞,根据linux 进程间通信的知识,双方应该互相发送数据唤醒对方。在这里就是MediaPlayerService 进程和ServiceManager 相互交互了,MediaPlayerService 对它的Client 来说是一个服务端,但是对ServiceManager 来说是一个客户端。
MediaPlayerService 同样基于上面的Binder通信框架,继承了相关的子类。
看一下MediaPlayerService 的启动代码。

int main(int argc __unused, char** argv)
{
        sp<ProcessState> proc(ProcessState::self());
        sp<IServiceManager> sm = defaultServiceManager();
        
        ALOGI("ServiceManager: %p", sm.get());
        AudioFlinger::instantiate();
        MediaPlayerService::instantiate();
        ResourceManagerService::instantiate();
        CameraService::instantiate();
        AudioPolicyService::instantiate();
        SoundTriggerHwService::instantiate();
        RadioService::instantiate();
        registerExtensions();
        
        ProcessState::self()->startThreadPool();
        IPCThreadState::self()->joinThreadPool();
}

defaultServiceManager

调用 sp<IServiceManager> sm = defaultServiceManager()获取ServiceManger 的代理; 函数定义在IServiceManager.cpp 中

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;
}

ProcessState::getStrongProxyForHandle

  1. 依次调用ProcessState 的 getContextObject ->
  2. getStrongProxyForHandle 函数,参数为0,
    首先查表 lookupHandleLocked。注意BpBinder.mHander = 0;

ProcessState 为单例模式,持有一个 Vector<handle_entry>mHandleToObject对象,进程中所有的Binder 对象都会添加到这个容器中。由于是是第一次查找,mHandleToObject为空,lookupHandleLocked会添加一个未初始化过的handle_entry对象,所以e->binder == NULL。

struct handle_entry {
    IBinder* binder;
    RefBase::weakref_type* refs;
};

ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle)
{
    const size_t N=mHandleToObject.size();
    if (N <= (size_t)handle) {
        handle_entry e;
        e.binder = NULL;
        e.refs = NULL;
        status_t err = mHandleToObject.insertAt(e, N, handle+1-N);
        if (err < NO_ERROR) return NULL;
    }
    return &mHandleToObject.editItemAt(handle);
}

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 = new BpBinder(handle); 
            e->binder = b;
            if (b) e->refs = b->getWeakRefs();
            result = b;
        } else {
            result.force_set(b);
            e->refs->decWeak(this);
        }
    }

    return result;
}

e->binder == NULL handle == 0 条件成立,经过下面两步调用

status_t status = IPCThreadState::self()->transact(0, IBinder::PING_TRANSACTION, data, NULL, 0);
b = new BpBinder(handle); 

变成了

gDefaultServiceManager = interface_cast<IServiceManager>(BpBinder(0));

其中ServiceManager 的hander 为0,
transact 函数第一个参数为0,表示的是传递给 handle 为0 的Service,就是ServiceManager,

interface_cast 以及DECLARE_META_INTERFACE IMPLEMENT_META_INTERFACE

interface_cast 以及DECLARE_META_INTERFACE IMPLEMENT_META_INTERFACE 这几个宏定义在
IInterface.h 中。

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

define DECLARE_META_INTERFACE(INTERFACE)                                \
    static const android::String16 descriptor;                          \
    static android::sp<I##INTERFACE> asInterface(                       \
            const android::sp<android::IBinder>& obj);                  \
    virtual const android::String16& getInterfaceDescriptor() const;    \
    I##INTERFACE();                                                     \
    virtual ~I##INTERFACE();                                            \


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() { }                                   \

替换掉INTERFACE 变成了, 这段代码变成了:

android::sp<IServiceManager> interface_cast<IServiceManager>(const sp<IBinder>& obj){
    return IServiceManager::asInterface(obj);
}
android::sp<IServiceManager> IServiceManager::asInterface(const android::sp<android::IBinder>& obj)
{
     android::sp<IServiceManager> intr;                                 
     if (obj != NULL) {                                              
         intr = static_cast<IServiceManager>(obj->queryLocalInterface(IServiceManager::descriptor).get());               
         if (intr == NULL) {                                         
                intr = new BpServiceManager(obj);                          
          }                                                           
      }                                                               
      return intr; 
}

BpBinder(0)->queryLocalInterface, queryLocalInterface 为IBinder 的虚函数,默认返回空值,BpBinder 继承IBinder,并且没有覆盖queryLocalInterface。所以sp<IServiceManager> sm = defaultServiceManager()实际是这个样子:

sp<IServiceManager> sm = new BpServiceManager(obj);

这段代码就是为了拿到ServiceManager的BpServiceManager. 当中在线程中做了记录,然后对引用计数做了处理,通过transact 通知了ServiceManager 。这样我们就拿到了ServiceManger 的客户端BpServiceManager。代码好绕,有没有看到其他的代码使用这个机制?

MediaPlayerService 注册到 ServiceManger

再回到MediaPlayerService 初始化的代码:

int main(int argc __unused, char** argv)
{
        ......
        
        AudioFlinger::instantiate();
        MediaPlayerService::instantiate();
        。。。。。。
        
        ProcessState::self()->startThreadPool();
        IPCThreadState::self()->joinThreadPool();
}

MediaPlayerService::instantiate

调用 MediaPlayerService::instantiate();

void MediaPlayerService::instantiate() {
    defaultServiceManager()->addService(
            String16("media.player"), new MediaPlayerService());
}

defaultServiceManager() 返回的结果就是BpServiceManager,所以这段代码变成了:

void MediaPlayerService::instantiate() {
    BpServiceManager()->addService(String16("media.player"), new MediaPlayerService());
}

BpServiceManager()->addService

 virtual status_t addService(const String16& name, const sp<IBinder>& service,
            bool allowIsolated)
{
        Parcel data, reply;
        data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
        data.writeString16(name);
        data.writeStrongBinder(service);
        data.writeInt32(allowIsolated ? 1 : 0);
        status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
        return err == NO_ERROR ? reply.readExceptionCode() : err;
}

在 remote 就是在new BpServiceManager 中穿进去的BpBinder(0)。

BpBinder 的 transact

BpBinder 的 transact 函数如下:

status_t BpBinder::transact(
    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) {
        status_t status = IPCThreadState::self()->transact(
            mHandle, code, data, reply, flags);
        if (status == DEAD_OBJECT) mAlive = 0;
        return status;
    }

    return DEAD_OBJECT;
}

IPCThreadState transact 先后调用了writeTransactionData 和 waitForResponse, writeTransactionData中把binder 相关的通信数据写入binder 驱动。然后呢,然后呢,其实在一开始ServiceManger 已经在binder_loop 中阻塞了,现在写入binder 驱动数据,binder_loop会被激活,读出数据 解析,然后ServiceManger 向bindr 驱动注册Service,将结果写入reply 参数。waitForResponse 读取reply 结果。通信完成,MediaPlayService 注册完成。

启动线程池

在最后先后调用了,根据上面的分析,startThreadPool 最后也调用了joinThreadPool。也就是启动了两个线程。

        ProcessState::self()->startThreadPool(); //启动子线程
        IPCThreadState::self()->joinThreadPool(); //主线程循环

在LoopThread 反复调用 joinThreadPool 函数做如下工作:

 result = talkWithDriver();
     if (result >= NO_ERROR) {
        size_t IN = mIn.dataAvail();
        if (IN < sizeof(int32_t)) return result;
        cmd = mIn.readInt32();
 
        result = executeCommand(cmd);
        ......
        }
    }

有一个疑问,为什么需要两个线程

总结:

  1. ProcessState.self() 建立实例
  2. defaultServiceManager()
  3. ProcessState::self()->getContextObject(nuLl)->ProcessState::self()->getStrongProxyForHandle(0)-> New BpBinder(0)
  4. interface_cast(BpBinder(0))->asInterface(BpBinder(0)) -> new BpServiceManager(BpBinder(0));
  5. 依次调用 BpServiceManger::addService ->BpBinder::transact->IPCThreadState::self()->transact 通知服务端
  6. IPCThreadState::waitForResponse 等待服务端返回。
  7. 启动线程池

调用序列图:

mediaservice 序列图
mediaservice 序列图
binder 调用过程图
binder 调用过程图

为什么需要两个线程,在需要用到回调函数的Binder通信中,在BnClass::doSome 是有callback ,而此时BpClass 进程中只有一个线程,这个线程正在waitRespose,而无法响应callback , 就会造成异常。

参考Binder 调用异常

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容