Binder学习—— C++实现分析

一、测试Demo的实现

1.Binder C++实现参考文件

frameworks/av/include/media/IMediaPlayerService.h
frameworks/av/media/libmedia/IMediaPlayerService.cpp
frameworks/av/media/libmediaplayerservice/MediaPlayerService.h
frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
frameworks/av/media/mediaserver/Main_mediaserver.cpp

 

2.实现代码

实现Service端和Client端,test_server.cpp中注册两个服务"hello""goodbye",test_client.cpp来获取使用服务。

定义抽象类,包含Service和Client两端都要实现的函数:
IHelloService.h
IGoodbyeService.h

Service端的实现(Bn: Binder native):
BnHelloService.h
BnGoodbyeService.h
BnHelloService.cpp
BnGoodbyeService.cpp

Client端的实现(Bp: Binder proxy):
BpHelloService.cpp
BpGoodbyeService.cpp

# tree
.
├── Android.mk
├── BnGoodbyeService.cpp
├── BnGoodbyeService.h
├── BnHelloService.cpp
├── BnHelloService.h
├── BpGoodbyeService.cpp
├── BpHelloService.cpp
├── IGoodbyeService.h
├── IHelloService.h
├── test_client.cpp
└── test_server.cpp

 

(1) IHelloService.h

/* 参考: frameworks\av\include\media\IMediaPlayerService.h */

#ifndef ANDROID_IHELLOERVICE_H
#define ANDROID_IHELLOERVICE_H

#include <utils/Errors.h>  // for status_t
#include <utils/KeyedVector.h>
#include <utils/RefBase.h>
#include <utils/String8.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>

#define HELLO_SVR_CMD_SAYHELLO     0
#define HELLO_SVR_CMD_SAYHELLO_TO  1

#if 1
/*-----DECLARE_META_INTERFACE(HelloService);等效如下:-----*/

static const android::String16 descriptor;
static android::sp<IHelloService> asInterface(const android::sp<android::IBinder>& obj);
virtual const android::String16& getInterfaceDescriptor() const;
IHelloService();
virtual ~IHelloService();
/*--------------------------------------------------------*/

#endif


namespace android {

class IHelloService: public IInterface
{
public:
    DECLARE_META_INTERFACE(HelloService);
    /*使用纯虚函数做成抽象类*/
    virtual void sayhello(void) = 0;
    virtual int sayhello_to(const char *name) = 0;
};

}

#endif

 

(2) IGoodbyeService.h

/* 参考: frameworks\av\include\media\IMediaPlayerService.h */

#ifndef ANDROID_IGOODBYEERVICE_H
#define ANDROID_IGOODBYEERVICE_H

#include <utils/Errors.h>  // for status_t
#include <utils/KeyedVector.h>
#include <utils/RefBase.h>
#include <utils/String8.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>

#define GOODBYE_SVR_CMD_SAYGOODBYE     0
#define GOODBYE_SVR_CMD_SAYGOODBYE_TO  1


namespace android {

class IGoodbyeService: public IInterface
{
public:
    DECLARE_META_INTERFACE(GoodbyeService);
    virtual void saygoodbye(void) = 0;
    virtual int saygoodbye_to(const char *name) = 0;
};

}

#endif

 

(3) BnHelloService.h

#ifndef ANDROID_BNHELLOERVICE_H
#define ANDROID_BNHELLOERVICE_H

#include "IHelloService.h"

namespace android {

class BnHelloService: public BnInterface<IHelloService>
{
public:
    /*自己又添加了一个函数*/
    virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);

    /*继承来的纯虚函数需要实现*/
    virtual void sayhello(void);
    virtual int sayhello_to(const char *name);

};
}

#endif

 

(4) BnGoodbyeService.h

#ifndef ANDROID_BNGOODBYEERVICE_H
#define ANDROID_BNGOODBYEERVICE_H

#include "IGoodbyeService.h"

namespace android {

class BnGoodbyeService: public BnInterface<IGoodbyeService>
{
public:
    virtual status_t    onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);

    virtual void saygoodbye(void);
    virtual int saygoodbye_to(const char *name);
};
}

#endif

 

(5) BnHelloService.cpp

/* 参考: frameworks\av\media\libmedia\IMediaPlayerService.cpp */

#define LOG_TAG "HelloService"

#include "BnHelloService.h"

namespace android {

status_t BnHelloService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    /* 解析数据,调用sayhello/sayhello_to */
    switch (code) {
        case HELLO_SVR_CMD_SAYHELLO: {
            sayhello();
            return NO_ERROR;
        } break;
        
        case HELLO_SVR_CMD_SAYHELLO_TO: {
            /* 从data中取出参数 */
            int32_t policy =  data.readInt32();
            String16 name16 = data.readString16();
            String8 name8(name16);
            int cnt = sayhello_to(name8.string());
            /* 把返回值写入reply传回去 */
            reply->writeInt32(cnt);
            return NO_ERROR;
        } break;
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
}

void BnHelloService::sayhello(void)
{
    static int cnt = 0;
    ALOGI("say hello : %d\n", cnt++);

}

int BnHelloService::sayhello_to(const char *name)
{
    static int cnt = 0;
    ALOGI("say hello to %s : %d\n", name, cnt++);
    return cnt;
}
}

 

(6) BnGoodbyeService.cpp

/* 参考: frameworks\av\media\libmedia\IMediaPlayerService.cpp */

#define LOG_TAG "GoodbyeService"

#include "BnGoodbyeService.h"

namespace android {

status_t BnGoodbyeService::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    /* 解析数据,调用saygoodbye/saygoodbye_to */
    switch (code) {
        case GOODBYE_SVR_CMD_SAYGOODBYE: {
            saygoodbye();
            return NO_ERROR;
        } break;
        
        case GOODBYE_SVR_CMD_SAYGOODBYE_TO: {
            /* 从data中取出参数 */
            int32_t policy =  data.readInt32();
            String16 name16 = data.readString16();
            String8 name8(name16);
            int cnt = saygoodbye_to(name8.string());
            /* 把返回值写入reply传回去 */
            reply->writeInt32(cnt);
            return NO_ERROR;
        } break;
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
}

void BnGoodbyeService::saygoodbye(void)
{
    static int cnt = 0;
    ALOGI("say goodbye : %d\n", cnt++);
}

int BnGoodbyeService::saygoodbye_to(const char *name)
{
    static int cnt = 0;
    ALOGI("say goodbye to %s : %d\n", name, cnt++);
    return cnt;
}
}

 

(7) BpHelloService.cpp

/* 参考: frameworks\av\media\libmedia\IMediaPlayerService.cpp */

#include "IHelloService.h"

namespace android {

class BpHelloService: public BpInterface<IHelloService>
{
public:
    BpHelloService(const sp<IBinder>& impl) : BpInterface<IHelloService>(impl)
    {
    }

    void sayhello(void)
    {
        /* 构造/发送数据 */
        Parcel data, reply;
        /*为了兼容之前的C程序才写入这个垃圾数据的*/
        data.writeInt32(0);
        /*调用远端的hello函数*/
        remote()->transact(HELLO_SVR_CMD_SAYHELLO, data, &reply); /*remote() ?*/
    }
    
    int sayhello_to(const char *name)
    {
        /* 构造/发送数据 */
        Parcel data, reply;

        /*为了兼容之前的C程序才写入这个垃圾数据(0)的*/
        data.writeInt32(0);
        data.writeString16(String16(name));

        remote()->transact(HELLO_SVR_CMD_SAYHELLO_TO, data, &reply);

        /*传送回返回值*/
        return reply.readInt32();
    }

};

IMPLEMENT_META_INTERFACE(HelloService, "android.media.IHelloService");

}

#if 1
/*------IMPLEMENT_META_INTERFACE(HelloService, "android.media.IHelloService"); 等效如下:-------*/


const android::String16 IHelloService::descriptor("android.media.IHelloService");
const android::String16& IHelloService::getInterfaceDescriptor() const {
    return IHelloService::descriptor;
}
android::sp<IHelloService> IHelloService::asInterface(const android::sp<android::IBinder>& obj)
{
    android::sp<IHelloService> intr;
    if (obj != NULL) {
        intr = static_cast<IHelloService*>(obj->queryLocalInterface(IHelloService::descriptor).get());
        if (intr == NULL) {
            intr = new BpHelloService(obj);
        }
    }
    return intr;
}
IHelloService::IHelloService() { }
IHelloService::~IHelloService() { }
#endif

 

(8) BpGoodbyeService.cpp

/* 参考: frameworks\av\media\libmedia\IMediaPlayerService.cpp */

#include "IGoodbyeService.h"

namespace android {

class BpGoodbyeService: public BpInterface<IGoodbyeService>
{
public:
    BpGoodbyeService(const sp<IBinder>& impl) : BpInterface<IGoodbyeService>(impl)
    {
    }

    void saygoodbye(void)
    {
        /* 构造/发送数据 */
        Parcel data, reply;
        data.writeInt32(0);

        remote()->transact(GOODBYE_SVR_CMD_SAYGOODBYE, data, &reply);
    }
    
    int saygoodbye_to(const char *name)
    {
        /* 构造/发送数据 */
        Parcel data, reply;

        data.writeInt32(0);
        data.writeString16(String16(name));

        remote()->transact(GOODBYE_SVR_CMD_SAYGOODBYE_TO, data, &reply);

        return reply.readInt32();
    }

};

IMPLEMENT_META_INTERFACE(GoodbyeService, "android.media.IGoodbyeService");

}

参考:http://github.com/weidongshan/APP_0004_Binder_CPP_App.git

 

3.编译测试

将代码放在frameworks/testing/biner_cpp_v1下,然后mm编译。

 

二、分析

1. Service的注册过程处理过程分析(test_server.cpp)

(1) 获取SM分析

defaultServiceManager    //IServiceManager.cpp
    gDefaultServiceManager = interface_cast<IServiceManager>(ProcessState::self()->getContextObject(NULL));
        obj = ProcessState::self()->getContextObject(NULL)
            getStrongProxyForHandle(0); //ProcessState.cpp 直接指定的是handle=0了,是SM
                return new BpBinder(0); //BpBinder.cpp SM就表示为一个handle=0的BpBinder对象。obj=此BpBinder对象
        IServiceManager::asInterface(obj); //obj=此BpBinder对象
            return new BpServiceManager(obj); //IServiceManager.cpp BpServiceManager充当SM的角色。

 

(2) addService()分析

sm->addService(String16("hello"), new BnHelloService()); //test_server.cpp
    virtual status_t addService(const String16& name, const sp<IBinder>& service, bool allowIsolated); //IServiceManager.cpp
    //allowIsolated声明的时候声明为: bool allowIsolated=false,使用的是默认参数
    data.writeStrongBinder(service); //service=BnHelloService
        flatten_binder(ProcessState::self(), val, this); //Parcel.cpp val=service=BnHelloService
            IBinder *local = binder->localBinder(); //binder=val,根据继承关系,localBinder直接return this, local也就是BnHelloService对象。
            flat_binder_object obj;
            obj.type = BINDER_TYPE_BINDER; //add service的时候的type
            obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
            obj.cookie = reinterpret_cast<uintptr_t>(local); // BnHelloService对象赋值给flat_binder_object的cookie域
            finish_flatten_binder //Parcel.cpp 应该是写到驱动
                out->writeObject(flat, false); 

 

(3)创建一个子线程循环read-parse-process

ProcessState::self()->startThreadPool(); //test_server.cpp 它会以一个线程的状态存在,可以通过/proc/$(PID)/task来验证。
    spawnPooledThread(true); //ProcessState.cpp isMain=true
        sp<Thread> t = new PoolThread(isMain);
        t->run(name.string()); //相当于执行PoolThread中的threadLoop
             IPCThreadState::self()->joinThreadPool(true);
                mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER); //IPCThreadState.cpp
                //若是isMain=true表示注册是主线程,为false表示新创建的子线程
                    //循环读取数据,解析数据,执行,答复
                    getAndExecuteCommand
                        executeCommand(cmd) //IPCThreadState.cpp
                            case BR_TRANSACTION:
                                sp<BBinder> b((BBinder*)tr.cookie); //cookie 就是 BnHelloService 对象
                                b->transact(tr.code, buffer, &reply, tr.flags); //这里调用的就是 BnHelloService.transact()
                            case BR_SPAWN_LOOPER:
                                mProcess->spawnPooledThread(false); //Service创建多线程   

IPCThreadState::self()->joinThreadPool(); //test_server.cpp 也是进入解析数据,执行,答复的循环

补充:

① ProcessState::self():获取ProcessState的单例模式,每个进程有一个唯一的实例

② IPCThreadState::self():获取IPCThreadState的单例模式,每个线程都有一个唯一的实例,实现如下:

处理涉及线程特有数据(Thread Specific Data)
这里,每个线程都有一个IPCThreadState对象,也就是说这个对象是每个线程特有的东西,各不相同,因此它应该存在这个线程的局部空间里。
K = pthread_key_create()
(K, V) 同一个K对于不同的线程可以设置不同的Value
每个线程设置不同的Value
线程1:pthread_setspecific(K, V1);
线程2:pthread_setspecific(K, V2); // V1和V2都存在于线程的局部空间里

线程1:pthread_getspecific(K); 得到V1
线程2:pthread_getspecific(K); 得到V2

这里不同的线程使用的是同一个键,但是不同的值,通过判断值是否为NULL来判断是否每个线程已经分配过了。

 

2. Client获取服务过程和使用服务分析(test_client.cpp)

(1) 打开binder设备节点和获取SM

sp<ProcessState> proc(ProcessState::self()); //test_client.cpp 构造函数中打开binder设备并进行mmap了
sp<IServiceManager> sm = defaultServiceManager(); //test_client.cpp 获得BpServiceManager 在IServiceManager.cpp中定义的

 

(2) 获取BpBinder对象的过程

sp<IBinder> binder = sm->getService(String16("hello")); //test_client.cpp 
//binder是BpBinder对象,里面含有HelloService的handle
    sp<IBinder> svc = checkService(name);
        remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply); //remote()是获取服务时赋值,Bpbinder或BinderProxy对象。
        return reply.readStrongBinder();
            unflatten_binder //Parcel.cpp 
                *out = proc->getStrongProxyForHandle(flat->handle); 
                //获取到一个 flat_binder_object 结构,里面有 Service 的 handle,通过 flat->handle 获取一个 sp<IBinder> 对象。

 

(3) 获得BpHelloService对象的过程

调用BpServiceManager的getService函数获得一个flat_binder_object,从中取出handle, 创建一个BpBinder(handle),
然后使用interface_cast使用这个BpBinder创建一个BpHelloService对象

sp<IHelloService> service = interface_cast<IHelloService>(binder);
//binder是BpBinder对象, 里面含有HelloService的handle,把binder转换为IHelloService接口(BpHelloService对象)

之后就可以通过service来访问这个服务里面提供的函数了。

补充:

IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");展开后:
android::sp<IServiceManager> IServiceManager::asInterface(const android::sp<android::IBinder>& obj)      
{                                                      
    android::sp<IServiceManager> intr;                    
    if (obj != NULL) { /*这个是Client端获取执行*/                              
        intr = static_cast<IServiceManager*>(obj->queryLocalInterface(IServiceManager::descriptor).get());  
        if (intr == NULL) {  /*这个是Service端注册执行*/                         
            intr = new BpServiceManager(obj);             
        }                                              
    }                                                  
    return intr;                                       
} 

 

posted on 2019-05-10 18:24  Hello-World3  阅读(897)  评论(0编辑  收藏  举报

导航