zoukankan      html  css  js  c++  java
  • 《深入理解Android(卷1)》笔记 5.第六章 深入理解Binder

    第六章 深入理解Binder

    我的简要总结:

    根据MediaServer的main函数来分析
    
    Main_mediaserver.cpp::main 
    
    int main(int argc, char** argv)
    {
        sp<ProcessState> proc(ProcessState::self()); //(1) 获得一个ProcessState实例
        sp<IServiceManager> sm = defaultServiceManager();//(2) 调用defaultServiceManager,得到一个IserviceManager
        LOGI("ServiceManager: %p", sm.get());
        AudioFlinger::instantiate();//初始化音频系统的AudioFlinger
        MediaPlayerService::instantiate();//(3) 多媒体系统的MediaPlayer服务,将以它作为主切入点
        CameraService::instantiate();
        AudioPolicyService::instantiate();
        ProcessState::self()->startThreadPool();//(4) 创建一个线程池
        IPCThreadState::self()->joinThreadPool();//(5) 将自己加入到上面创建的线程池中
    }
    1.sp<ProcessState> proc(ProcessState::self());//获得ProcessState实例
    作用:
    a.打开了binder设备
    b.分配内存来接收数据
    
    2.sp<IServiceManager> sm = defaultServiceManager();//返回一个IServiceManager对象,通过它,可以和ServiceManager交互
    流程:
    defaultServiceManager----->interface_cast<IServiceManager>ProcessState::self()->getContextObject(null);
    其中,getContextObject(null);----->getStrongProxyForHandle(0);---->返回BpBinder(0)
    所以,interface_cast<IServiceManager>ProcessState::self()->getContextObject(null);这条语句就变成了interface_cast<IServiceManager>BpBinder(0);​
    然后继续,interface_cast<IServiceManager>BpBinder(0);---->IServiceManager::asInterface(BpBinder(0));
    IServiceManager有两个重要的宏:
    DECLARE_META_INTERFACE:声明了asInterface函数
    IMPLEMENT_META_INTERFACE:实现了asInterface函数---->返回new BpServiceManager(BpBinder(0));
    
    总结作用:
    a.获得一个BpBinder对象,handle为0
    b.获得BpServiceManager对象(继承了IServiceManager,实现了IServiceManager的业务函数),它的mRemote为BpBinder。
    
    3.MediaPlayerService::instantiate(string , new service());
    ---->addService
    ---->BpBinder->transact
    ---->IPCThreadState::self()->transact
    
    分析IPCThreadState::self():返回一个IPCThreadState对象。
    分析IPCThreadState::transact():
    a.writeTransactionData:将请求信息写入到mOut中。
    b.waitForResponse:发送请求、接收回复。
    b1.talkWithDriver:与binder交互
    b2.cmd = mIn.readInt32:接收回复---->executeCommand(分析该命令中的两种情况)
    b21.case BR_Transaction:生成BBinder对象(该对象实际上就是实现了BnServiceXXX的那个对象)
    b22.case BR_SPAWN_Loop:创建了一个新线程,用于与Binder通信。
    
    4.ProcessState::self()->startThreadPool();
    ---->spawnPooledThread(true);
    ---->new PoolThread(isMain);
    ---->IPCThreadState::self()->joinThreadPool(mIsMain);
    
    可知,IPCThreadState和新创建的线程中都调用了该函数。​
    
    5.IPCThreadState::self()->joinThreadPool();
    分析得知,IPCThreadState主线程和新创建的线程都在talkWithDriver,它们通过joinThreadPool读取binder设备,查看是否有请求。​
    

      

    开始详细分析:

    Binder是Android系统提供的一种IPC机制。Android系统可以看作是一个基于Binder通信的C/S架构。Binder如同网络,将系统的各个部分连接在了一起。

    知识点1:在这个架构中,除了C/S架构所包括的Client端和Server端外,还有一个全局的ServiceManager端(其作用是管理系统中的各种服务(Service))。三者关系图如下:

    从图中分析得:

    (1)    Server进程要先在ServiceManager中注册Service,所以Server是ServiceManager的客户端。

    (2)    如果某个Client要使用某个Service,必须先到ServiceManager中获取该Service的相关信息,所以Client是ServiceManager的客户端。

    (3)    Client根据得到的Service信息和Service所在的Server进程建立通信的通路,然后就可以直接与Service交互了。所以Client是Service的客户端。

    (4)    The important point is 三者的交互都是基于Binder通信的。所以通过任意两者之间的关系,都可以揭示Binder的奥秘哦~

    知识点2:庖丁解MediaServer

    1.MediaServer中包括许多重要的Service。如下:

    AudioFlinger:           音频系统的核心服务。

    AudioPolicyService:  音频系统中关于音频策略的重要服务。

    MediaPlayerService:  多媒体系统中的重要服务。

    CameraService:       有关摄像/照相的重要服务。

    2.MediaServer入口函数[---->Main_mediaserver.cpp]

    Main_mediaserver.cpp::main
    int main(int argc, char** argv)
    {
        sp<ProcessState> proc(ProcessState::self()); //(1) 获得一个ProcessState实例
        sp<IServiceManager> sm = defaultServiceManager();//(2) 调用defaultServiceManager,得到一个IserviceManager
        LOGI("ServiceManager: %p", sm.get());
        AudioFlinger::instantiate();//初始化音频系统的AudioFlinger
        MediaPlayerService::instantiate();//(3) 多媒体系统的MediaPlayer服务,将以它作为主切入点
        CameraService::instantiate();
        AudioPolicyService::instantiate();
        ProcessState::self()->startThreadPool();//(4) 创建一个线程池
        IPCThreadState::self()->joinThreadPool();//(5) 将自己加入到上面创建的线程池中
    }

    (1) 独一无二的ProcessState  (每个进程都只有一个ProcessState)

    [---->Main_mediaserver.cpp]

    sp<ProcessState> proc(ProcessState::self()); //(2.1) 获得一个ProcessState实例

    (1.1) 单例的ProcessState [---->ProcessState.cpp]

    ProcessState::self()
    sp<ProcessState> ProcessState::self()
    {
        //gProcess是在Static.cpp中定义的一个全局变量。刚开始时,gProcess肯定为空。
        if (gProcess != NULL) return gProcess; 
        
    AutoMutex _l(gProcessMutex);
    //创建一个ProcessState对象,赋给gProcess
        if (gProcess == NULL) gProcess = new ProcessState;
        return gProcess;
    }

    ps: self()函数采用了单例模式,根据这个和Process State的名字,可以很明确的说明每个进程只有一个ProcessState对象。

    (1.2) ProcessState的构造函数 [---->ProcessState.cpp]  (它打开了Binder设备)

    ProcessState::ProcessState()
    ProcessState::ProcessState()
        : mDriverFD(open_driver())  //就是在这里打开了Binder设备
        , mVMStart(MAP_FAILED)   //映射内存的起始地址
        , mManagesContexts(false)
        , mBinderContextCheckFunc(NULL)
        , mBinderContextUserData(NULL)
        , mThreadPoolStarted(false)
        , mThreadPoolSeq(1)
    {
        if (mDriverFD >= 0) {
            // XXX Ideally, there should be a specific define for whether we
            // have mmap (or whether we could possibly have the kernel module
            // availabla).
    #if !defined(HAVE_WIN32_IPC)
            // 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*
                LOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
                close(mDriverFD);
                mDriverFD = -1;
            }
    #else
            mDriverFD = -1;
    #endif
        }
        if (mDriverFD < 0) {
            // Need to run without the driver, starting our own thread pool.
        }
    }

    (1.3) 打开Binder设备 [---->ProcessState.cpp]

    open_driver的作用就是打开/dev/binder这个设备,它是Android在内核中为完成进程间通信而专门设置的一个虚拟设备,实现如下:

    ProcessState::open_driver()
    static int open_driver()
    {
        if (gSingleProcess) {
            return -1;
        }
    
        int fd = open("/dev/binder", O_RDWR); //打开/dev/binder设备
        if (fd >= 0) {
            fcntl(fd, F_SETFD, FD_CLOEXEC);
            int vers;
    #if defined(HAVE_ANDROID_OS)
            status_t result = ioctl(fd, BINDER_VERSION, &vers);
    #else
            status_t result = -1;
            errno = EPERM;
    #endif
            if (result == -1) {
                LOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
                close(fd);
                fd = -1;
            }
            if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
                LOGE("Binder driver protocol does not match user space protocol!");
                close(fd);
                fd = -1;
            }
    #if defined(HAVE_ANDROID_OS)
            size_t maxThreads = 15;
            //通过ioct1方式告诉binder驱动,这个fd支持的最大线程数为15个。
            result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
            if (result == -1) {
                LOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
            }
    #endif
            
        } else {
            LOGW("Opening '/dev/binder' failed: %s\n", strerror(errno));
        }
        return fd;
    }

    至此,ProcessState::self()分析完毕。总结如下:

    (a) 打开/dev/binder设备。这就相当于与内核的Binder驱动有了交互的通道。

    (b) 对返回的fd使用mmap。这样Binder驱动就会分配一块内存来接收数据。

    (c)由于ProcessState具有唯一性,因此一个进程只打开设备一次。

    (2) 时空穿越魔术----defaultServiceManager [---->IServiceManager.cpp]

    该函数会返回一个IServiceManager对象,通过这个对象,我们可以与另一个进程ServiceManager进行交互。这就是穿越魔术。

    (2.1)魔术前的准备工作

    分析defaultServiceManager调用了哪些函数,返回的IServiceManager又是什么?源码如下:

    IServiceManager::defaultServiceManager()
    sp<IServiceManager> defaultServiceManager()
    {
        if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
        
    {
        //还是用了单例模式
            AutoMutex _l(gDefaultServiceManagerLock);
            if (gDefaultServiceManager == NULL) {
                gDefaultServiceManager = interface_cast<IServiceManager>(
                    ProcessState::self()->getContextObject(NULL));
            }
        }
        
        return gDefaultServiceManager;
    }

    分析可知,调用了ProcessState的getContextObject函数!其中参数为NULL。继续分析getContextObject函数。

    ProcessState::getContextObject
    sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)
    {
    //caller的值为NULL,函数返回值为IBinder。
    // supportsProcesses函数根据open_driver函数是否可成功打开设备来判断它是否支持process。实际设备肯定支持process。
        if (supportsProcesses()) {
            return getStrongProxyForHandle(0);//真实设备上肯定支持进程,所以会调用这个函数。
        } else {
            return getContextObject(String16("default"), caller);
        }
    }
    
    getStrongProxyForHandle函数源码如下:
    sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
    {
        sp<IBinder> result;
    
        AutoMutex _l(mLock);
        //根据索引查找对应的资源。如果lookupHandleLocked发现没有对应资源项,则会创建一个新的项并返回。这个新项的内容需要填充。
        handle_entry* e = lookupHandleLocked(handle);
    
        if (e != NULL) {
            // We need to create a new BpBinder if there isn't currently one, OR we
            // are unable to acquire a weak reference on this current one.  See comment
            // in getWeakProxyForHandle() for more info about this.
            IBinder* b = e->binder;
            if (b == NULL || !e->refs->attemptIncWeak(this)) {
                //对于新创建的资源项,它的binder为空,因此走这个分支。注意,handle的值为0
                b = new BpBinder(handle); //创建一个BpBinder
                e->binder = b; //填充entry的内容
                if (b) e->refs = b->getWeakRefs();
                result = b;
            } else {
                // This little bit of nastyness is to allow us to add a primary
                // reference to the remote proxy when this team doesn't have one
                // but another team is sending the handle to us.
                result.force_set(b);
                e->refs->decWeak(this);
            }
        }
    
        return result;  //返回BpBinder(handle),注意,handle的值为0
    }

    (2.2) 魔术表演的道具----BpBinder

    众所周知,表演魔术必须要有道具,这个穿越魔术的道具就是BpBinder。它是什么呢,它还有个孪生兄弟BBinder。Binder家族图谱如下:

    (a) BpBinder是客户端用来与Server交互的代理类,p即Proxy的意思。

    (b) BBinder是与Proxy相对的一端,它是Proxy交互的目的端。如果Proxy代表客户端,那么BBinder则代表服务端。BpBinder与BBinder一一对应,即BpBinderA只能和对应的BBinderA交互。

    question: 

    (a) 为什么创建的不是BBinder?

    因为我们是ServiceManager的客户端,当然得使用代理端与ServiceManager进行交互。

    (b) BpBinder如何标识它所对应的BBinder端呢?

    Binder系统通过handler来标识对应的BBinder。

    ps:我们给BpBinder的构造函数传递的参数handle的值为0。这个0在整个Binder系统中有重要含义----因为0代表的是ServiceManager所对应的BBinder。

    分析BpBinder的构造函数 

    BpBinder::BpBinder
    BpBinder::BpBinder(int32_t handle)
        : mHandle(handle) //handle是0
        , mAlive(1)
        , mObitsSent(0)
        , mObituaries(NULL)
    {
        LOGV("Creating BpBinder %p handle %d\n", this, mHandle);
    
    extendObjectLifetime(OBJECT_LIFETIME_WEAK);
    //另一个重要对象是IPCThreadState
        IPCThreadState::self()->incWeakHandle(handle);
    }

     从代码中看,BpBinder、BBinder这两个类没有任何地方操作/dev/binder设备。它们只是个道具。

    回顾BpBinder道具的出场:

    gDefaultServiceManager = interface_cast<IServiceManager>(ProcessState::self()->getContextObject(NULL));

    然后变成了

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

    分析interface_cast,它其实是一个障眼法。

    (2.3) 障眼法---- interface_cast

    第一眼是不是觉得interface_cast是强制类型转换的意思?错!!! (在下面的”(b)业务和通信的挂钩”中会分析这个问题)

    interface_cast的定义 [---->IInterface.h] 

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

    因此interface_cast<IServiceManager>()等价于

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

    又转移到IServiceManager中去了,到此为止,至少解除了障眼法。

    (2.4) 拨开云雾见月明----IServiceManager

    问题:因为BpBinder和BBinder是与通信业务有关的,所以业务层的逻辑是怎样巧妙地架构在Binder机制上的呢?

    解决方案:通过IServiceManager来解释这个问题。

    (a) 定义业务逻辑

    IServiceManager定义了ServiceManager所提供的服务。IServiceManager的定义在[---->IServiceManager.h]

    IServiceManager
    class IServiceManager : public IInterface
    {
    public:
        DECLARE_META_INTERFACE(ServiceManager);  //无比关键的宏!!!
    
        //下面是ServiceManager提供的业务函数
        /**
         * Retrieve an existing service, blocking for a few seconds
         * if it doesn't yet exist.
         */
        virtual sp<IBinder>         getService( const String16& name) const = 0;
    
        /**
         * Retrieve an existing service, non-blocking.
         */
        virtual sp<IBinder>         checkService( const String16& name) const = 0;
    
        /**
         * Register a service.
         */
        virtual status_t            addService( const String16& name,
                                                const sp<IBinder>& service) = 0;
    
        /**
         * Return list of all existing services.
         */
        virtual Vector<String16>    listServices() = 0;
    
        enum {
            GET_SERVICE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
            CHECK_SERVICE_TRANSACTION,
            ADD_SERVICE_TRANSACTION,
            LIST_SERVICES_TRANSACTION,
        };
    };

    (b)  业务和通信的挂钩

    Android通过DECLARE_META_INTERFACEIMPLEMENT_META_INTERFACE宏,将业务和通信牢牢地钩在一起。两个宏的定义都在[Iinterface.h]

    首先,看下DECLARE_META_INTERFACE宏的定义:

    #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();

    然后根据DECLARE_META_INTERFACE(ServiceManager)进行相应替换,得到

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

    然后,看下IMPLEMENT_META_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() { }                                   \

    IServiceManager.cpp中有如下一行代码:

    IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");

    因此宏展开,得到

    #define IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager")
    const android::String16 IServiceManager::descriptor("android.os.IServiceManager");
    //实现getInterfaceDescriptor函数
    const android::String16&IServiceManager::getInterfaceDescriptor() const {
    //返回字符串descriptor,值为"android.os.IServiceManager"
            return IServiceManager::descriptor;
    }
    //实现asInterface函数
        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) {     
        //obj是我们刚才创建的那个BpBinder(0)
                    intr = new BpServiceManager (obj);                          
                }    
            }                                                               
            return intr;                                                    
        }                                                                   
        IServiceManager::IServiceManager () { }                                    
        IServiceManager::~IServiceManager () { }     

    在asInterface函数中,根据代码intr = new BpServiceManager (obj);可知,asInterface函数的作用是利用BpBinder对象作为参数新建了一个BpServiceManager对象。

    看下IServiceManager家族图谱:

    图谱分析,得到

    (1) IServiceManager、BpServiceManager、BnServiceManager都与业务逻辑有关。

    (2) BnServiceManager同事从IServiceManager BBinder派生,表示它可以直接参与Binder通信。

    (3) BpServiceManager虽然从BpInterface中派生,但是与BpBinder没有关系。

    (4) BnServiceManager是一个虚类,它的业务最终需要子类来实现。

    问:既然BpServiceManager与Binder没有直接关系,那怎么与Binder交互呢?

    答:其父类BpRefBase中的mRemote变量就是BpBinder!!!

    不信么,分析下:

    BpServiceManager类源码 [---->IServiceManager.cpp] 

    class BpServiceManager : public BpInterface<IServiceManager>
    {
    public:
        // impl是IBinder类型,它实际上是BpBinder对象。先不管,继续分析
        //调用基类BpInterface的构造函数
    BpServiceManager(const sp<IBinder>& impl) : BpInterface<IServiceManager>(impl)
    {
    }
    ……
    }

    BpInterface的实现代码如下:[---->IInterface.h] 

    template<typename INTERFACE>
    inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)
        : BpRefBase(remote) // 基类构造函数
    {
    }

    [---->Binder.cpp::BpRefBase类] 

    BpRefBase::BpRefBase(const sp<IBinder>& o)
    //mRemote最终等于那个new出来的BpBinder(0)
        : mRemote(o.get()), mRefs(NULL), mState(0)
    {
        extendObjectLifetime(OBJECT_LIFETIME_WEAK);
    
        if (mRemote) {
            mRemote->incStrong(this);           // Removed on first IncStrong().
            mRefs = mRemote->createWeak(this);  // Held for our entire lifetime.
        }
    }

    最后分析得到的结果就是BpServiceManager的一个变量mRemote指向了BpBinder。

    到此,魔术结束了。总结一下,回顾defaultServiceManager函数,可以得到两个关键对象:

    (a) 有一个BpBinder对象,它的handle值为0.

    (b) 有一个BpServiceManager对象,它的mRemote值为BpBinder。

    BpServiceManager对象实现了IServiceManager的业务函数,现在又有了BpBinder作为通信的代表,接下来的工作就简单多了。

    下面,要通过分析MediaPlayerService的注册过程,进一步分析业务函数的内部是如何工作的。

    (3) 注册MediaPlayerService

    (3.1) 业务层的工作

    回到MS中,分析MediaPlayerService::instantiate();  

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

    根据之前分析,defaultServiceManager函数返回的是BpServiceManager对象,它是IServiceManager的子类。分析addService函数的源码:

        virtual status_t addService(const String16& name, const sp<IBinder>& service)
        {
            Parcel data, reply; //Parcel:可以当作一个数据包
            data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
            data.writeString16(name);
            data.writeStrongBinder(service);
            //remote函数返回的是mRemote变量,也就是BpBinder对象。
            status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
            return err == NO_ERROR ? reply.readExceptionCode() : err;
        }

    addService函数是一个业务层的函数,它将请求数据打包成data后,传给BpBinder的transact函数,这样就把通信的工作交给BpBinder了。

    到此,业务层的工作原理已经很清楚了。业务层的作用就是将请求信息打包,交给通信层处理。

    (3.2) 通信层的工作

    之前已经知道,BpBinder只是个工具,源码中没有与Binder设备交互的地方。那怎么交互呢?秘密就在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) {
            //BpBinder将自己的transact工作交给了IPCThreadState的transact函数!!!
            status_t status = IPCThreadState::self()->transact(
                mHandle, code, data, reply, flags);
            if (status == DEAD_OBJECT) mAlive = 0;
            return status;
        }
    
        return DEAD_OBJECT;
    }

    (3.2.1)深入分析IPCThreadState

    (a) 分析IPCThreadState::self()函数

    [---->IPCThreadState.cpp]

    IPCThreadState::self()
    IPCThreadState* IPCThreadState::self()
    {
        if (gHaveTLS) { //第一次进来为false
    restart:
            const pthread_key_t k = gTLS;
            /*
            TLS是现成本地存储空间的简称。
            ps:这种空间每个线程都有,而且线程间不共享这些空间。
            通过pthread_getspecific/ pthread_setspecific函数可以获取/设置这些空间中的内容
            从线程本地存储空间中获取保存在其中的IPCThreadState对象。
    */
            IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
            if (st) return st;
            //new一个对象,构造函数中会调用pthread_setspecific函数
            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::IPCThreadState()
    IPCThreadState::IPCThreadState()
        : mProcess(ProcessState::self()),
          mMyThreadId(androidGetTid()),
          mStrictModePolicy(0),
          mLastTransactionBinderFlags(0)
    {
        pthread_setspecific(gTLS, this);//把自己设置到线程本地存储空间中去
    clearCaller();
    //mIn和mOut是两个Parcel。把它看成是发送和接收命令的缓冲区即可
        mIn.setDataCapacity(256);
        mOut.setDataCapacity(256);
    }

    每个线程都有一个IPCThreadState,每个IPCThreadState中都有一个mIn和mOut。其中mIn是用来接收来自Binder设备的数据的,mOut是用来存储发送给Binder设备的数据的。

    (b) 分析IPCThreadState::transact函数

    //注意,handle的值为0,代表了通信的目的端

    IPCThreadState::transact
    status_t IPCThreadState::transact(int32_t handle,
                                      uint32_t code, const Parcel& data,
                                      Parcel* reply, uint32_t flags)
    {
        status_t err = data.errorCheck();
    
        flags |= TF_ACCEPT_FDS;
    
        IF_LOG_TRANSACTIONS() {
            TextOutput::Bundle _b(alog);
            alog << "BC_TRANSACTION thr " << (void*)pthread_self() << " / hand "
                << handle << " / code " << TypeCode(code) << ": "
                << indent << data << dedent << endl;
        }
        
        if (err == NO_ERROR) {
            LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(),
                (flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY");
            /*
            第一个参数BC_TRANSACTION是应用程序向binder设备发送消息的消息码;
    而binder设备向应用程序回复消息的消息码以BR_开头。
    消息码的定义在binder_module.h中。
    */
            err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
        }
        
        if (err != NO_ERROR) {
            if (reply) reply->setError(err);
            return (mLastError = err);
        }
        
        if ((flags & TF_ONE_WAY) == 0) {
            #if 0
            if (code == 4) { // relayout
                LOGI(">>>>>> CALLING transaction 4");
            } else {
                LOGI(">>>>>> CALLING transaction %d", code);
            }
            #endif
            if (reply) {
                err = waitForResponse(reply);
            } else {
                Parcel fakeReply;
                err = waitForResponse(&fakeReply);
            }
            #if 0
            if (code == 4) { // relayout
                LOGI("<<<<<< RETURNING transaction 4");
            } else {
                LOGI("<<<<<< RETURNING transaction %d", code);
            }
            #endif
            
            IF_LOG_TRANSACTIONS() {
                TextOutput::Bundle _b(alog);
                alog << "BR_REPLY thr " << (void*)pthread_self() << " / hand "
                    << handle << ": ";
                if (reply) alog << indent << *reply << dedent << endl;
                else alog << "(none requested)" << endl;
            }
        } else {
            err = waitForResponse(NULL, NULL);
        }
        
        return err;
    }

    这个函数的流程很简单,就是发数据,然后等结果。但需要关注下handle这个参数在这里的作用。

    分析writeTransactionData函数

    IPCThreadState::writeTransactionData
    status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
        int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
    {
        binder_transaction_data tr;
        //handle的值传给了target,用来标识目的端,其中 0是ServiceManager的标志。
    tr.target.handle = handle;
    //code是消息码,是用来switch/case的。
        tr.code = code;
        tr.flags = binderFlags;
        
        const status_t err = data.errorCheck();
        if (err == NO_ERROR) {
            tr.data_size = data.ipcDataSize();
            tr.data.ptr.buffer = data.ipcData();
            tr.offsets_size = data.ipcObjectsCount()*sizeof(size_t);
            tr.data.ptr.offsets = data.ipcObjects();
        } else if (statusBuffer) {
            tr.flags |= TF_STATUS_CODE;
            *statusBuffer = err;
            tr.data_size = sizeof(status_t);
            tr.data.ptr.buffer = statusBuffer;
            tr.offsets_size = 0;
            tr.data.ptr.offsets = NULL;
        } else {
            return (mLastError = err);
        }
        
        //把命令写到mOut中
        mOut.writeInt32(cmd);
        mOut.write(&tr, sizeof(tr));
        
        return NO_ERROR;
    }

    这样,就已经把addService函数中的请求信息写到mOut中了。接下来看看发送请求和接收回复部分的实现。代码在waitForResponse函数中。如下所示:

    IPCThreadState::waitForResponse
    status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
    {
        int32_t cmd;
        int32_t err;
    
    while (1) {
            //talkWithDriver!!! 还用多解释么?
            if ((err=talkWithDriver()) < NO_ERROR) break;
            err = mIn.errorCheck();
            if (err < NO_ERROR) break;
            if (mIn.dataAvail() == 0) continue;
            
            cmd = mIn.readInt32();
            
            IF_LOG_COMMANDS() {
                alog << "Processing waitForResponse Command: "
                    << getReturnString(cmd) << endl;
            }
    
            switch (cmd) {
            case BR_TRANSACTION_COMPLETE:
                if (!reply && !acquireResult) goto finish;
                break;
            
            case BR_DEAD_REPLY:
                err = DEAD_OBJECT;
                goto finish;
    
            case BR_FAILED_REPLY:
                err = FAILED_TRANSACTION;
                goto finish;
            
            case BR_ACQUIRE_RESULT:
                {
                    LOG_ASSERT(acquireResult != NULL, "Unexpected brACQUIRE_RESULT");
                    const int32_t result = mIn.readInt32();
                    if (!acquireResult) continue;
                    *acquireResult = result ? NO_ERROR : INVALID_OPERATION;
                }
                goto finish;
            
            case BR_REPLY:
                {
                    binder_transaction_data tr;
                    err = mIn.read(&tr, sizeof(tr));
                    LOG_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 size_t*>(tr.data.ptr.offsets),
                                tr.offsets_size/sizeof(size_t),
                                freeBuffer, this);
                        } else {
                            err = *static_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 size_t*>(tr.data.ptr.offsets),
                                tr.offsets_size/sizeof(size_t), this);
                        }
                    } else {
                        freeBuffer(NULL,
                            reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
                            tr.data_size,
                            reinterpret_cast<const size_t*>(tr.data.ptr.offsets),
                            tr.offsets_size/sizeof(size_t), this);
                        continue;
                    }
                }
                goto finish;
    
            default:
                //executeCommand函数
                err = executeCommand(cmd);
                if (err != NO_ERROR) goto finish;
                break;
            }
        }
    
    finish:
        if (err != NO_ERROR) {
            if (acquireResult) *acquireResult = err;
            if (reply) reply->setError(err);
            mLastError = err;
        }
        
        return err;
    }

    OK,我们已经发送了请求数据,假设马上收到了回复,看executeCommand函数的源码: 

    IPCThreadState::executeCommand
    status_t IPCThreadState::executeCommand(int32_t cmd)
    {
        BBinder* obj;
        RefBase::weakref_type* refs;
        status_t result = NO_ERROR;
        
        switch (cmd) {
        case BR_ERROR:
            result = mIn.readInt32();
            break;
            
        case BR_OK:
            break;
            
        case BR_ACQUIRE:
            refs = (RefBase::weakref_type*)mIn.readInt32();
            obj = (BBinder*)mIn.readInt32();
            LOG_ASSERT(refs->refBase() == obj,
                       "BR_ACQUIRE: object %p does not match cookie %p (expected %p)",
                       refs, obj, refs->refBase());
            obj->incStrong(mProcess.get());
            IF_LOG_REMOTEREFS() {
                LOG_REMOTEREFS("BR_ACQUIRE from driver on %p", obj);
                obj->printRefs();
            }
            mOut.writeInt32(BC_ACQUIRE_DONE);
            mOut.writeInt32((int32_t)refs);
            mOut.writeInt32((int32_t)obj);
            break;
            
        case BR_RELEASE:
            refs = (RefBase::weakref_type*)mIn.readInt32();
            obj = (BBinder*)mIn.readInt32();
            LOG_ASSERT(refs->refBase() == obj,
                       "BR_RELEASE: object %p does not match cookie %p (expected %p)",
                       refs, obj, refs->refBase());
            IF_LOG_REMOTEREFS() {
                LOG_REMOTEREFS("BR_RELEASE from driver on %p", obj);
                obj->printRefs();
            }
            mPendingStrongDerefs.push(obj);
            break;
            
        case BR_INCREFS:
            refs = (RefBase::weakref_type*)mIn.readInt32();
            obj = (BBinder*)mIn.readInt32();
            refs->incWeak(mProcess.get());
            mOut.writeInt32(BC_INCREFS_DONE);
            mOut.writeInt32((int32_t)refs);
            mOut.writeInt32((int32_t)obj);
            break;
            
        case BR_DECREFS:
            refs = (RefBase::weakref_type*)mIn.readInt32();
            obj = (BBinder*)mIn.readInt32();
            // NOTE: This assertion is not valid, because the object may no
            // longer exist (thus the (BBinder*)cast above resulting in a different
            // memory address).
            //LOG_ASSERT(refs->refBase() == obj,
            //           "BR_DECREFS: object %p does not match cookie %p (expected %p)",
            //           refs, obj, refs->refBase());
            mPendingWeakDerefs.push(refs);
            break;
            
        case BR_ATTEMPT_ACQUIRE:
            refs = (RefBase::weakref_type*)mIn.readInt32();
            obj = (BBinder*)mIn.readInt32();
             
            {
                const bool success = refs->attemptIncStrong(mProcess.get());
                LOG_ASSERT(success && refs->refBase() == obj,
                           "BR_ATTEMPT_ACQUIRE: object %p does not match cookie %p (expected %p)",
                           refs, obj, refs->refBase());
                
                mOut.writeInt32(BC_ACQUIRE_RESULT);
                mOut.writeInt32((int32_t)success);
            }
            break;
        
        case BR_TRANSACTION:
            {
                binder_transaction_data tr;
                result = mIn.read(&tr, sizeof(tr));
                LOG_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 size_t*>(tr.data.ptr.offsets),
                    tr.offsets_size/sizeof(size_t), freeBuffer, this);
                
                const pid_t origPid = mCallingPid;
                const uid_t origUid = mCallingUid;
                
                mCallingPid = tr.sender_pid;
                mCallingUid = tr.sender_euid;
                
                int curPrio = getpriority(PRIO_PROCESS, mMyThreadId);
                if (gDisableBackgroundScheduling) {
                    if (curPrio > ANDROID_PRIORITY_NORMAL) {
                        // We have inherited a reduced priority from the caller, but do not
                        // want to run in that state in this process.  The driver set our
                        // priority already (though not our scheduling class), so bounce
                        // it back to the default before invoking the transaction.
                        setpriority(PRIO_PROCESS, mMyThreadId, ANDROID_PRIORITY_NORMAL);
                    }
                } else {
                    if (curPrio >= ANDROID_PRIORITY_BACKGROUND) {
                        // We want to use the inherited priority from the caller.
                        // Ensure this thread is in the background scheduling class,
                        // since the driver won't modify scheduling classes for us.
                        // The scheduling group is reset to default by the caller
                        // once this method returns after the transaction is complete.
                        androidSetThreadSchedulingGroup(mMyThreadId,
                                                        ANDROID_TGROUP_BG_NONINTERACT);
                    }
                }
    
                //LOGI(">>>> TRANSACT from pid %d uid %d\n", mCallingPid, mCallingUid);
                
                Parcel reply;
                IF_LOG_TRANSACTIONS() {
                    TextOutput::Bundle _b(alog);
                    alog << "BR_TRANSACTION thr " << (void*)pthread_self()
                        << " / obj " << tr.target.ptr << " / code "
                        << TypeCode(tr.code) << ": " << indent << buffer
                        << dedent << endl
                        << "Data addr = "
                        << reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer)
                        << ", offsets addr="
                        << reinterpret_cast<const size_t*>(tr.data.ptr.offsets) << endl;
                }
                if (tr.target.ptr) {
                    //这里的b实际上就是实现了BnServiceXXX的那个对象
                    sp<BBinder> b((BBinder*)tr.cookie);
                    const status_t error = b->transact(tr.code, buffer, &reply, tr.flags);
                    if (error < NO_ERROR) reply.setError(error);
    
                } else {
                    // the_context_object->transact函数是IPCThreadState.cpp中定义的一个全局变量,可通过setTheContextObject函数设置
                    const status_t error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
                    if (error < NO_ERROR) reply.setError(error);
                }
                
                //LOGI("<<<< TRANSACT from pid %d restore pid %d uid %d\n",
                //     mCallingPid, origPid, origUid);
                
                if ((tr.flags & TF_ONE_WAY) == 0) {
                    LOG_ONEWAY("Sending reply to %d!", mCallingPid);
                    sendReply(reply, 0);
                } else {
                    LOG_ONEWAY("NOT sending reply to %d!", mCallingPid);
                }
                
                mCallingPid = origPid;
                mCallingUid = origUid;
    
                IF_LOG_TRANSACTIONS() {
                    TextOutput::Bundle _b(alog);
                    alog << "BC_REPLY thr " << (void*)pthread_self() << " / obj "
                        << tr.target.ptr << ": " << indent << reply << dedent << endl;
                }
                
            }
            break;
        
        case BR_DEAD_BINDER:
            {
                BpBinder *proxy = (BpBinder*)mIn.readInt32();
                proxy->sendObituary();
                mOut.writeInt32(BC_DEAD_BINDER_DONE);
                mOut.writeInt32((int32_t)proxy);
            } break;
            
        case BR_CLEAR_DEATH_NOTIFICATION_DONE:
            {
                BpBinder *proxy = (BpBinder*)mIn.readInt32();
                proxy->getWeakRefs()->decWeak(proxy);
            } break;
            
        case BR_FINISHED:
            result = TIMED_OUT;
            break;
            
        case BR_NOOP:
            break;
            
    case BR_SPAWN_LOOPER:
            //这里将接收来自驱动的指示以创建一个新线程,用于和Binder通信。
            mProcess->spawnPooledThread(false);
            break;
            
        default:
            printf("*** BAD COMMAND %d received from Binder driver\n", cmd);
            result = UNKNOWN_ERROR;
            break;
        }
    
        if (result != NO_ERROR) {
            mLastError = result;
        }
        
        return result;
    }

     对于如何和binder设备交互,可通过talkwithDriver函数分析。其实并不是通过write和read来发送和接收请求,而是通过ioctl函数。[---->IPCThreadState.cpp]

    IPCThreadState::talkWithDriver
    status_t IPCThreadState::talkWithDriver(bool doReceive)
    {
        LOG_ASSERT(mProcess->mDriverFD >= 0, "Binder driver is not opened");
        // binder_write_read是用来和binder设备交换数据的结构
        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 = (long unsigned int)mOut.data();
    
        // This is what we'll read.
    if (doReceive && needRead) {
            //接收数据缓冲区信息的填充。如果以后收到数据,就直接填在mIn中了。
            bwr.read_size = mIn.dataCapacity();
            bwr.read_buffer = (long unsigned int)mIn.data();
        } else {
            bwr.read_size = 0;
        }
        
        IF_LOG_COMMANDS() {
            TextOutput::Bundle _b(alog);
            if (outAvail != 0) {
                alog << "Sending commands to driver: " << indent;
                const void* cmds = (const void*)bwr.write_buffer;
                const void* end = ((const uint8_t*)cmds)+bwr.write_size;
                alog << HexDump(cmds, bwr.write_size) << endl;
                while (cmds < end) cmds = printCommand(alog, cmds);
                alog << dedent;
            }
            alog << "Size of receive buffer: " << bwr.read_size
                << ", needRead: " << needRead << ", doReceive: " << doReceive << endl;
        }
        
        // 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_LOG_COMMANDS() {
                alog << "About to read/write, write size = " << mOut.dataSize() << endl;
            }
    #if defined(HAVE_ANDROID_OS)
            //通过ioctl方式发送/接收请求
            if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
                err = NO_ERROR;
            else
                err = -errno;
    #else
            err = INVALID_OPERATION;
    #endif
            IF_LOG_COMMANDS() {
                alog << "Finished read/write, write size = " << mOut.dataSize() << endl;
            }
        } while (err == -EINTR);
        
        IF_LOG_COMMANDS() {
            alog << "Our err: " << (void*)err << ", write consumed: "
                << bwr.write_consumed << " (of " << mOut.dataSize()
                << "), read consumed: " << bwr.read_consumed << endl;
        }
    
        if (err >= NO_ERROR) {
            if (bwr.write_consumed > 0) {
                if (bwr.write_consumed < (ssize_t)mOut.dataSize())
                    mOut.remove(0, bwr.write_consumed);
                else
                    mOut.setDataSize(0);
            }
            if (bwr.read_consumed > 0) {
                mIn.setDataSize(bwr.read_consumed);
                mIn.setDataPosition(0);
            }
            IF_LOG_COMMANDS() {
                TextOutput::Bundle _b(alog);
                alog << "Remaining data size: " << mOut.dataSize() << endl;
                alog << "Received commands from driver: " << indent;
                const void* cmds = mIn.data();
                const void* end = mIn.data() + mIn.dataSize();
                alog << HexDump(cmds, mIn.dataSize()) << endl;
                while (cmds < end) cmds = printReturnCommand(alog, cmds);
                alog << dedent;
            }
            return NO_ERROR;
        }
        
        return err;
    }

     MediaPlayerService的注册过程分析完毕。开始分析startThreadPool和joinThreadPool函数。

      

    (4)秋风扫落叶----startThreadPool和joinThreadPool分析

    (4.1)创造劳动力----startThreadPool函数

    ProcessState::startThreadPool
    void ProcessState::startThreadPool()
    {
    AutoMutex _l(mLock);
        //如果已经是startThreadPool,那这个函数就到此为止了。
        if (!mThreadPoolStarted) {
            mThreadPoolStarted = true;
            spawnPooledThread(true); //传入的参数为true
        }
    }

    分析spawnPooledThread函数

    ProcessState::spawnPooledThread
    void ProcessState::spawnPooledThread(bool isMain)
    {
        //传递过来的参数isMain为true
        if (mThreadPoolStarted) {
            int32_t s = android_atomic_add(1, &mThreadPoolSeq);
            char buf[32];
            sprintf(buf, "Binder Thread #%d", s);
            LOGV("Spawning new pooled thread, name=%s\n", buf);
            sp<Thread> t = new PoolThread(isMain);
            t->run(buf);
        }
    }

    PoolThread是在IPCThreadState中定义的一个Thread子类,实现如下:

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

    (4.2)万众归一----joinThreadPool

    IPCThreadState和新创建的线程中都调用了该函数,看具体实现:

    IPCThreadState::joinThreadPool
    void IPCThreadState::joinThreadPool(bool isMain)
    {
        LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid());
        //因为isMain为true,所以把请求信息写入到mOut中
        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 default/foreground
        // one to avoid performing an initial transaction in the background.
        androidSetThreadSchedulingGroup(mMyThreadId, ANDROID_TGROUP_DEFAULT);
            
        status_t result;
        do {
            int32_t cmd;
            
            // When we've cleared the incoming command queue, process any pending derefs
            if (mIn.dataPosition() >= mIn.dataSize()) {
                size_t numPending = mPendingWeakDerefs.size();
                if (numPending > 0) {
                    for (size_t i = 0; i < numPending; i++) {
                        RefBase::weakref_type* refs = mPendingWeakDerefs[i];
                        refs->decWeak(mProcess.get());
                    }
                    mPendingWeakDerefs.clear();
                }
                
                //处理已经死亡的BBinder对象
                numPending = mPendingStrongDerefs.size();
                if (numPending > 0) {
                    for (size_t i = 0; i < numPending; i++) {
                        BBinder* obj = mPendingStrongDerefs[i];
                        obj->decStrong(mProcess.get());
                    }
                    mPendingStrongDerefs.clear();
                }
            }
    
            //发送命令,读取请求
            // now get the next command to be processed, waiting if necessary
            result = talkWithDriver();
            if (result >= NO_ERROR) {
                size_t IN = mIn.dataAvail();
                if (IN < sizeof(int32_t)) continue;
                cmd = mIn.readInt32();
                IF_LOG_COMMANDS() {
                    alog << "Processing top-level Command: "
                        << getReturnString(cmd) << endl;
                }
    
    
                result = executeCommand(cmd); //处理消息
            }
            
            // After executing the command, ensure that the thread is returned to the
            // default cgroup before rejoining the pool.  The driver takes care of
            // restoring the priority, but doesn't do anything with cgroups so we
            // need to take care of that here in userspace.  Note that we do make
            // sure to go in the foreground after executing a transaction, but
            // there are other callbacks into user code that could have changed
            // our group so we want to make absolutely sure it is put back.
            androidSetThreadSchedulingGroup(mMyThreadId, ANDROID_TGROUP_DEFAULT);
    
            // 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);
    }

    分析得知,IPCThreadState主线程和新创建的线程都在talkWithDriver,它们通过joinThreadPool读取binder设备,查看是否有请求。

    因此得知,binder设备是支持多线程操作的,其中一定做了同步方面的工作。

    ps:MediaServer这个进程一共注册了4个服务。

    从概念上再理解下,就是说:

    a. Binder是通信机制。

    b. 业务可以基于Binder通信。

    Binder之所以复杂,重要原因是在于android通过层层封装,巧妙地将通信和业务结合在了一起。如图所示:

     

    知识点3:服务总管ServiceManager

    1.ServiceManager原理

    defaultServiceManager返回的是一个BpServiceManager对象,通过它可以把命令请求发送给handle值为0的目的端。根据IServiceManager的图谱,应该要有一个类从BnServiceManager派生出来并处理这些来自远方的请求。但源码中并没有这样的一个类存在!但确实有一个程序完成了BnServiceManager的工作,这个程序就是ServiceManager。代码在Service_manager.c中。ServiceManager的入口函数如下所示: 

    Service_manager.c::main
    int main(int argc, char **argv)
    {
    struct binder_state *bs;
    // BINDER_SERVICE_MANAGER的值为NULL,是一个magic number.
        void *svcmgr = BINDER_SERVICE_MANAGER;
        // (1)打开binder设备
        bs = binder_open(128*1024);
        // (2)成为manager,将自己的handle置为0
        if (binder_become_context_manager(bs)) {
            LOGE("cannot become context manager (%s)\n", strerror(errno));
            return -1;
        }
    
    svcmgr_handle = svcmgr;
    // (3)处理客户端发过来的请求
        binder_loop(bs, svcmgr_handler);
        return 0;
    }

     (1) 打开binder设备

    binder_open函数有两个作用:a.打开binder设备;  b.内存映射

    实现如下:

    binder_open
    struct binder_state *binder_open(unsigned mapsize)
    {
        struct binder_state *bs;
    
        bs = malloc(sizeof(*bs));
        if (!bs) {
            errno = ENOMEM;
            return 0;
        }
    
        bs->fd = open("/dev/binder", O_RDWR);//打开binder设备
        if (bs->fd < 0) {
            fprintf(stderr,"binder: cannot open device (%s)\n",
                    strerror(errno));
            goto fail_open;
        }
    
        bs->mapsize = mapsize;
        bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0); //内存映射
        if (bs->mapped == MAP_FAILED) {
            fprintf(stderr,"binder: cannot map device (%s)\n",
                    strerror(errno));
            goto fail_map;
        }
    
            /* TODO: check version */
    
        return bs;
    
    fail_map:
        close(bs->fd);
    fail_open:
        free(bs);
        return 0;
    }

     (2) ServiceManager成为manager,实现代码如下:[---->Binder.c]  

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

     (3) 处理客户端发过来的请求,binder_loop实现在Binder.c中。

    binder_loop
    /*
    binder_handler参数是一个函数指针,binder_loop读取请求后将解析这些请求,最后调用binder_handler完成最终的处理。
    */
    void binder_loop(struct binder_state *bs, binder_handler func)
    {
        int res;
        struct binder_write_read bwr;
        unsigned readbuf[32];
    
        bwr.write_size = 0;
        bwr.write_consumed = 0;
        bwr.write_buffer = 0;
        
        readbuf[0] = BC_ENTER_LOOPER;
        binder_write(bs, readbuf, sizeof(unsigned));
    
        for (;;) {
            bwr.read_size = sizeof(readbuf);
            bwr.read_consumed = 0;
            bwr.read_buffer = (unsigned) readbuf;
    
            res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
    
            if (res < 0) {
                LOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
                break;
            }
            //接收到请求,交给binder_parse,最后会调用func来处理这些请求
            res = binder_parse(bs, 0, readbuf, bwr.read_consumed, func);
            if (res == 0) {
                LOGE("binder_loop: unexpected reply?!\n");
                break;
            }
            if (res < 0) {
                LOGE("binder_loop: io error %d %s\n", res, strerror(errno));
                break;
            }
        }
    }

    (4) 调用func处理

    main函数中传递给binder_loop的参数func是svcmgr_handler,代码如下:

    svcmgr_handler
    int svcmgr_handler(struct binder_state *bs,
                       struct binder_txn *txn,
                       struct binder_io *msg,
                       struct binder_io *reply)
    {
        struct svcinfo *si;
        uint16_t *s;
        unsigned len;
        void *ptr;
        uint32_t strict_policy;
    
    //    LOGI("target=%p code=%d pid=%d uid=%d\n",
    //         txn->target, txn->code, txn->sender_pid, txn->sender_euid);
        //svcmgr_handle就是前面说的magic number,值为null。这里比较target是不是自己。
        if (txn->target != svcmgr_handle)
            return -1;
    
        // Equivalent to Parcel::enforceInterface(), reading the RPC
        // header with the strict mode policy mask and the interface name.
        // Note that we ignore the strict_policy and don't propagate it
        // further (since we do no outbound RPCs anyway).
        strict_policy = bio_get_uint32(msg);
        s = bio_get_string16(msg, &len);
        if ((len != (sizeof(svcmgr_id) / 2)) ||
            memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
            fprintf(stderr,"invalid id %s\n", str8(s));
            return -1;
        }
    
        switch(txn->code) {
        case SVC_MGR_GET_SERVICE: //得到某个service的信息,service用字符串表示。
        case SVC_MGR_CHECK_SERVICE:
            s = bio_get_string16(msg, &len); //s是字符串表示的service名称。
            ptr = do_find_service(bs, s, len);
            if (!ptr)
                break;
            bio_put_ref(reply, ptr);
            return 0;
    
        case SVC_MGR_ADD_SERVICE: //对应addService请求。
            s = bio_get_string16(msg, &len);
            ptr = bio_get_ref(msg);
            if (do_add_service(bs, s, len, ptr, txn->sender_euid))
                return -1;
            break;
    
        //得到当前系统已经注册的所有service的名字。
        case SVC_MGR_LIST_SERVICES: {
            unsigned n = bio_get_uint32(msg);
    
            si = svclist;
            while ((n-- > 0) && si)
                si = si->next;
            if (si) {
                bio_put_string16(reply, si->name);
                return 0;
            }
            return -1;
        }
        default:
            LOGE("unknown code %d\n", txn->code);
            return -1;
        }
    
        bio_put_uint32(reply, 0);
        return 0;
    }

    2.服务的注册

    上面提到的switch/case语句,将实现IServiceManager中定义的各个业务函数。重点分析其中的do_add_service函数,它最终完成了对addService请求的处理。代码如下:[---->Service_manager.c]

    do_add_service
    int do_add_service(struct binder_state *bs,
                       uint16_t *s, unsigned len,
                       void *ptr, unsigned uid)
    {
        struct svcinfo *si;
    //    LOGI("add_service('%s',%p) uid=%d\n", str8(s), ptr, uid);
    
        if (!ptr || (len == 0) || (len > 127))
            return -1;
        // svc_can_register比较注册进程的uid和名字
        if (!svc_can_register(uid, s)) {
            LOGE("add_service('%s',%p) uid=%d - PERMISSION DENIED\n",
                 str8(s), ptr, uid);
            return -1;
        }
    
        si = find_svc(s, len);
        if (si) {
            if (si->ptr) {
                LOGE("add_service('%s',%p) uid=%d - ALREADY REGISTERED\n",
                     str8(s), ptr, uid);
                return -1;
            }
            si->ptr = ptr;
        } else {
            si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
            if (!si) {
                LOGE("add_service('%s',%p) uid=%d - OUT OF MEMORY\n",
                     str8(s), ptr, uid);
                return -1;
            }
            //ptr是关键数据,为void*类型。
            si->ptr = ptr;
            si->len = len;
            memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
            si->name[len] = '\0';
            si->death.func = svcinfo_death; //service退出的通知函数
            si->death.ptr = si;
            //这个svclist是一个list,保存了当前注册到ServiceManager中的信息。
            si->next = svclist;
            svclist = si;
        }
    
    binder_acquire(bs, ptr);
    //服务进程退出后,binder_link_to_death函数做清理工作。每当有服务进程退出时,ServiceManager都会得到来自binder设备的通知。
        binder_link_to_death(bs, ptr, &si->death);
        return 0;
    }

    (1)分析svc_can_register函数---->注册服务

    svc_can_register
    int svc_can_register(unsigned uid, uint16_t *name)
    {
        unsigned n;
        //如果用户组是root用户或system用户,则权限够高,允许注册。
        if ((uid == 0) || (uid == AID_SYSTEM))
            return 1;
    
        for (n = 0; n < sizeof(allowed) / sizeof(allowed[0]); n++)
            if ((uid == allowed[n].uid) && str16eq(name, allowed[n].name))
                return 1;
    
        return 0;
    }

    allowed结构数组控制那些权限达不到root和system的进程,它的定义如下:

    allowed结构数组
    static struct {
        unsigned uid;
        const char *name;
    } allowed[] = {
    #ifdef LVMX
        { AID_MEDIA, "com.lifevibes.mx.ipc" },
    #endif
        { AID_MEDIA, "media.audio_flinger" },
        { AID_MEDIA, "media.player" },
        { AID_MEDIA, "media.camera" },
        { AID_MEDIA, "media.audio_policy" },
        { AID_NFC,   "nfc" },
        { AID_RADIO, "radio.phone" },
        { AID_RADIO, "radio.sms" },
        { AID_RADIO, "radio.phonesubinfo" },
        { AID_RADIO, "radio.simphonebook" },
        { AID_RADIO, "radio.vt" },
    /* TODO: remove after phone services are updated: */
        { AID_RADIO, "phone" },
        { AID_RADIO, "sip" },
        { AID_RADIO, "isms" },
        { AID_RADIO, "iphonesubinfo" },
        { AID_RADIO, "simphonebook" },
    };

    所以,如果Server进程权限不够root和system,那么请记住要在allowed中添加相应的项。

    ServiceManager其实就是保存了一些服务的信息,那它存在的意义是什么?

    存在意义:

    a. ServiceManager能集中管理系统内的所有服务,同时能施加权限控制,并不是所有进程都能注册服务。

    b. ServiceManager支持通过字符串名称来查找对应的服务。

    c. 由于各种原因的影响,Server进程可能生死无常。如果让每个Client都去检测,压力实在太大了。现在有了统一的管理机构,Client只需要查询ServiceManager,就能把握动向,得到最新信息。这可能正是ServiceManager存在的最大意义吧。

      

    通过MediaPlayerService和它的Client来分析请求数据是如何从通信层传递到业务层并进行处理的。一个Client要想获得Service的信息,首先必须和ServiceManager打交道,通过getService来获取Service的信息。例如ImediaDeathNotifier.cpp中的getMediaPlayerService函数。

    IMediaDeathNotifier::getMediaPlayerService()
    /*static*/const sp<IMediaPlayerService>&
    IMediaDeathNotifier::getMediaPlayerService()
    {
        LOGV("getMediaPlayerService");
        Mutex::Autolock _l(sServiceLock);
        if (sMediaPlayerService.get() == 0) {
            sp<IServiceManager> sm = defaultServiceManager();
            sp<IBinder> binder;
            do {
                //向ServiceManager查询对应的服务信息,返回BpBinder
                binder = sm->getService(String16("media.player"));
                if (binder != 0) {
                    break;
                 }
                 LOGW("Media player service not published, waiting...");
                 //如果ServiceManager上没有查询的服务,则继续等待,直到对应服务注册为止。
                 usleep(500000); // 0.5 s
            } while(true);
    
            if (sDeathNotifier == NULL) {
            sDeathNotifier = new DeathNotifier();
        }
    binder->linkToDeath(sDeathNotifier);
    //通过interface_cast,将这个binder转化成BpMediaPlayerService,binder中的handle标识的一定是目的端MediaPlayerService。
        sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);
        }
        LOGE_IF(sMediaPlayerService == 0, "no media player service!?");
        return sMediaPlayerService;
    }

    有了BpMediaPlayerService,就可以使用任何ImediaPlayerService提供的业务逻辑函数了。

    调用的这些函数都将把请求数据打包发送给Binder驱动,并根据BpBinder中的handle值找到对应端的处理者来处理。过程如下:

    a.通信层接收到请求

    b.递交给业务层处理

    现在来分析下这个过程。

    (5)MediaPlayerService驻留在MediaServer进程中,这个进程有两个线程在talkWithDriver。假如其中有一个线程收到了请求信息,它最终会通过executeCommand调用来处理这个请求。

    代码如下:

    IPCThreadState::executeCommand
    status_t IPCThreadState::executeCommand(int32_t cmd)
    {
        BBinder* obj;
        RefBase::weakref_type* refs;
        status_t result = NO_ERROR;
        
        switch (cmd) {
        case BR_ERROR:
            result = mIn.readInt32();
            break;
        …………
        case BR_TRANSACTION:
            {
                binder_transaction_data tr;
                result = mIn.read(&tr, sizeof(tr));
                LOG_ASSERT(result == NO_ERROR,
                    "Not enough command data for brTRANSACTION");
                if (result != NO_ERROR) break;
                
                Parcel buffer;
                …………
                Parcel reply;
                …………
                if (tr.target.ptr) {
                    //在这里,b就是MediaPlayerService,这样就直接定位到业务层了
                    sp<BBinder> b((BBinder*)tr.cookie);
                    //(1)分析这里的transact函数
                    const status_t error = b->transact(tr.code, buffer, &reply, tr.flags);
                    if (error < NO_ERROR) reply.setError(error);
    
                } else {
                    const status_t error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
                    if (error < NO_ERROR) reply.setError(error);
                }
                
                //LOGI("<<<< TRANSACT from pid %d restore pid %d uid %d\n",
                //     mCallingPid, origPid, origUid);
                
                if ((tr.flags & TF_ONE_WAY) == 0) {
                    LOG_ONEWAY("Sending reply to %d!", mCallingPid);
                    sendReply(reply, 0);
                } else {
                    LOG_ONEWAY("NOT sending reply to %d!", mCallingPid);
                }
                
                mCallingPid = origPid;
                mCallingUid = origUid;
    
                IF_LOG_TRANSACTIONS() {
                    TextOutput::Bundle _b(alog);
                    alog << "BC_REPLY thr " << (void*)pthread_self() << " / obj "
                        << tr.target.ptr << ": " << indent << reply << dedent << endl;
                }
                
            }
            break;
        …………
    }

    因为MediaPlayerService继承自BnMediaPlayerService,而BnMediaPlayerService继承自

    BBinder和ImediaPlayerService。有了这样的理解,再来分析代码中的(1)

    (1)b->transact函数是继承自BBinder,来看代码:

    BBinder::transact
    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:
                //调用子类的onTransact函数
                err = onTransact(code, data, reply, flags);
                break;
        }
    
        if (reply != NULL) {
            reply->setDataPosition(0);
        }
    
        return err;
    }

    分析BnMediaPlayerService类中实现的onTransact函数[---->ImediaPlayerService.cpp]

    BnMediaPlayerService::onTransact
    status_t BnMediaPlayerService::onTransact(
        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
    {
        switch(code) {
            …………
            case CREATE_MEDIA_RECORDER: {
                CHECK_INTERFACE(IMediaPlayerService, data, reply);
                pid_t pid = data.readInt32();//从请求数据中读取相应参数。
                //子类要实现createMediaRecorder函数
                sp<IMediaRecorder> recorder = createMediaRecorder(pid);
                reply->writeStrongBinder(recorder->asBinder());
                return NO_ERROR;
            } break;
            case CREATE_METADATA_RETRIEVER: {
                CHECK_INTERFACE(IMediaPlayerService, data, reply);
                pid_t pid = data.readInt32();
                //子类要实现createMetadataRetriever函数
                sp<IMediaMetadataRetriever> retriever = createMetadataRetriever(pid);
                reply->writeStrongBinder(retriever->asBinder());
                return NO_ERROR;
            } break;
            default:
                return BBinder::onTransact(code, data, reply, flags);
        }
    }

    在MediaPlayerService.cpp中实现了这两个函数,如下:

    两个函数
    sp<IMediaRecorder> MediaPlayerService::createMediaRecorder(pid_t pid)
    {
        sp<MediaRecorderClient> recorder = new MediaRecorderClient(this, pid);
        wp<MediaRecorderClient> w = recorder;
        Mutex::Autolock lock(mLock);
        mMediaRecorderClients.add(w);
        LOGV("Create new media recorder client from pid %d", pid);
        return recorder;
    }
    
    sp<IMediaMetadataRetriever> MediaPlayerService::createMetadataRetriever(pid_t pid)
    {
        sp<MetadataRetrieverClient> retriever = new MetadataRetrieverClient(pid);
        LOGV("Create new media retriever from pid %d", pid);
        return retriever;
    }

     over~ 

  • 相关阅读:
    使用keepalived实现双机热备
    MYSQL ERROR CODE 错误编号的意义
    Mysql slow query log
    eclipse svn 分支合并到主干
    Timer的schedule和scheduleAtFixedRate方法的区别解析
    Java内部类引用外部类中的局部变量为何必须是final问题解析
    nginx中有关命令和日志切割,配置文件加载的详细阐述
    流媒体中ffmpeg 命令的使用
    windows下搭建nginx服务器及实现nginx支持https配置流程
    mysql 中sql语句的执行顺序
  • 原文地址:https://www.cnblogs.com/chenbin7/p/2831620.html
Copyright © 2011-2022 走看看