当前位置: 首页 > 工具软件 > form-binder > 使用案例 >

Android-binder

桑坚
2023-12-01

Server获得了Service Manager远程接口之后,就要把自己的Service添加到Service Manager中去,然后把自己启动起来,等待Client的请求。


MediaPlayerService  继承了

--> BnMediaPlayerService类(一个Binder Native类,用来处理Client请求) 

--> BnInterface<IMediaPlayerService>类

 

BnInterface是一个模板类,它定义在frameworks/base/include/binder/IInterface.h文件中:

-------------------------------------------------------------------------------------------------------------------------

template<typename INTERFACE>

class BnInterface : public INTERFACE, public BBinder

{

public:

    virtual sp<IInterface>      queryLocalInterface(const String16& _descriptor);

    virtual const String16&     getInterfaceDescriptor() const;

protected:

    virtual IBinder*            onAsBinder();

};

-------------------------------------------------------------------------------------------------------------------------

 

这里可以看出,BnMediaPlayerService实际是继承了 --> IMediaPlayerService和BBinder类。

IMediaPlayerService和BBinder类又分别继承了IInterface和IBinder类,IInterface和IBinder类又同时继承了RefBase类。

 

BnMediaPlayerService使用了IPCThreadState接收Client处发送过来的请求,

                                          而IPCThreadState又借助了ProcessState类来与Binder驱动程序交互。

 

IPCThreadState接收到了Client处的请求后,就会调用BBinder类的transact函数,并传入相关参数,

BBinder类的transact函数 最终调用BnMediaPlayerService类的onTransact函数,于是,就开始真正地处理Client的请求了。

----------------------------------------------------------------------------------------------------------------------------------------------------------


int main(int argc, char** argv)

{

    sp<ProcessState> proc(ProcessState::self());

    sp<IServiceManager> sm = defaultServiceManager();

    LOGI("ServiceManager: %p", sm.get());

 

    AudioFlinger::instantiate();

    MediaPlayerService::instantiate();      // 该函数内部调用addService,把MediaPlayerService信息 add到ServiceManager中

    CameraService::instantiate();

    AudioPolicyService::instantiate();

    ProcessState::self()->startThreadPool();

    IPCThreadState::self()->joinThreadPool();

}

 

进入到MediaPlayerService::instantiate函数把MediaPlayerService添加到Service Manger中去。这个函数定义在frameworks/base/media/libmediaplayerservice/MediaPlayerService.cpp文件中:

void MediaPlayerService::instantiate() {  

    defaultServiceManager()->addService(  

            String16("media.player"), new MediaPlayerService());  

}  

 defaultServiceManager返回的实际是一个BpServiceManger类实例, 即:

    BpServiceManger()->addService(   )


--------------------------------------------------------------------------------------------------------------

addService是调用的BpServiceManager的函数。

virtual status_t addService (const String16& name,    const sp<IBinder>& service)

    {

        Parcel data, reply;         // data是发送到BnServiceManager的命令包


        data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());

// 再把新service名字写进去 叫media.player

        data.writeString16(name);


// 把新服务service (MediaPlayerService)   写到命令中

        data.writeStrongBinder(service);

//调用remotetransact函数

        status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);

        return err == NO_ERROR ? reply.readInt32() : err;

}

--------------------------------------------------------------------------------------------------------------

这里的Parcel类是用来于序列化进程间通信数据用的。

data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());  

         IServiceManager::getInterfaceDescriptor()返回来的是一个字符串,即"android.os.IServiceManager"。


我们看一下Parcel::writeInterfaceToken的实现,位于frameworks/base/libs/binder/Parcel.cpp文件中:

status_t Parcel::writeInterfaceToken(const String16& interface)  

{  

    writeInt32(IPCThreadState::self()->getStrictModePolicy() |  

               STRICT_MODE_PENALTY_GATHER);  

    return writeString16(interface);       // 它的作用是写入一个整数和一个字符串到Parcel中去

}  

------------------------------------------------------

data.writeString16(name);  

        这里又是写入一个字符串到Parcel中去,这里的name即是上面传进来的“media.player”字符串。

------------------------------------------------------

data.writeStrongBinder(service);  

        这里定义一个Binder对象到Parcel去。

我们重点看一下这个函数的实现,因为它涉及到 进程间传输Binder实体的问题 ,比较复杂,需要重点关注,同时,也是理解Binder机制的一个重点所在。

注意,这里的service参数是一个MediaPlayerService对象。

status_t Parcel::writeStrongBinder(const sp<IBinder>& val)  

{  

    return flatten_binder(ProcessState::self(), val, this);  

}  


status_t flatten_binder(const sp<ProcessState>& proc,

    const sp<IBinder>& binder,   Parcel* out)

{

   flat_binder_object obj;

    

    obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;

 0x7f 表示处理本Binder实体请求数据包的线程的最低优先级,

 FLAT_BINDER_FLAG_ACCEPTS_FDS 表示这个Binder实体可以接受文件描述符,Binder实体在收到文件描述符时,就会在本进程中打开这个文件。

       传进来的binder即为MediaPlayerService::instantiate函数中new出来的MediaPlayerService实例,因此,不为空。

       又由于MediaPlayerService继承自BBinder类,它是一个本地Binder实体,因此binder->localBinder返回一个BBinder指针,而且肯定不为空,于是执行下面语句:

    if(binder != NULL) {

        IBinder *local = binder->localBinder();

        if (!local) {

            BpBinder *proxy = binder->remoteBinder();

            if (proxy == NULL) {

                LOGE("null proxy");

            }

            const int32_t handle = proxy ? proxy->handle() : 0;

            obj.type = BINDER_TYPE_HANDLE;

            obj.handle = handle;

            obj.cookie = NULL;

        } else {

            obj.type = BINDER_TYPE_BINDER;

            obj.binder = local->getWeakRefs();

            obj.cookie = local;

        }

    } else {

        obj.type = BINDER_TYPE_BINDER;

        obj.binder = NULL;

        obj.cookie = NULL;

    }

    return finish_flatten_binder(binder, obj, out);

}


 后记:        

   有关binder机制的分析已整理为pdf文档:

        http://wenku.baidu.com/view/4e9a5763f5335a8102d220bf.html

 

 类似资料: