Skip to main content
 首页 » 编程设计

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

2022年07月19日27zhengyun_ustc

一、测试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

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

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

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

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

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

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

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

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()????? 
        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;                                        
} 

本文参考链接:https://www.cnblogs.com/hellokitty2/p/10846044.html