Binder代理执行服务接口方法原理分析

来源:互联网 发布:mac制作铃声怎么改时间 编辑:程序博客网 时间:2024/06/05 10:18


是这样的,当客户端请求服务端服务时候,获取一个代理。代理可以调用接口的所有方法。

那么有一个问题,如果方法是有返回值的,返回值怎么获取。如果没有返回值,怎么传递到服务端呢。


下面分析ServiceManager这个服务

以接口定义的addService为例子


我们客户端是任意Service,它现在想往大管家添加自己,就这么简单,首先获取BpServiceManager,


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

virtual sp<IBinder> getService(const String16& name) const
    {
        unsigned n;
        for (n = 0; n < 5; n++){
            sp<IBinder> svc = checkService(name);
            if (svc != NULL) return svc;
            ALOGI("Waiting for service %s...\n", String8(name).string());
            sleep(1);
        }
        return NULL;
    }


    virtual sp<IBinder> checkService( const String16& name) const
    {
        Parcel data, reply;
        data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
        data.writeString16(name);
        remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
        return reply.readStrongBinder();
    }

这里面作为IPC通信的客户端请求端,transact是发送Parcel数据。对于addService没有什么特别的返回,而getService这种客户端想要得到一个

服务啊,所以肯定真正的返回一些什么东西才可以


仔细看getService调用checkService,而checkService,它返回是一个reply.readStrongBinder();

也就是说BpServiceManager持有的remote()是binder,所以可以读写数据,先写数据,然后readStrongBinder

就会返回一个Binder了。


那只好分析readStrongBinder了。

sp<IBinder> Parcel::readStrongBinder() const
{
    sp<IBinder> val;
    unflatten_binder(ProcessState::self(), *this, &val);
    return val;
}


--》》》unflatten_binder分析


status_t unflatten_binder(const sp<ProcessState>& proc,
    const Parcel& in, wp<IBinder>* out)
{
    const flat_binder_object* flat = in.readObject(false);


    if (flat) {
        switch (flat->type) {
            case BINDER_TYPE_BINDER:
                *out = reinterpret_cast<IBinder*>(flat->cookie);
                return finish_unflatten_binder(NULL, *flat, in);
            case BINDER_TYPE_WEAK_BINDER:
                if (flat->binder != 0) {
                    out->set_object_and_refs(
                        reinterpret_cast<IBinder*>(flat->cookie),
                        reinterpret_cast<RefBase::weakref_type*>(flat->binder));
                } else {
                    *out = NULL;
                }
                return finish_unflatten_binder(NULL, *flat, in);
            case BINDER_TYPE_HANDLE:
            case BINDER_TYPE_WEAK_HANDLE:
                *out = proc->getWeakProxyForHandle(flat->handle);
                return finish_unflatten_binder(
                    static_cast<BpBinder*>(out->unsafe_get()), *flat, in);
        }
    }
    return BAD_TYPE;
}

Parcel读取一个object即可,当类型为binder返回这个binder

当类型为handler,返回new一个BpBinder.


这样我们便知道getService返回的也是一个远程管家ServiceManager管理的服务列表,列表存着他们的handler

实际上返回给客户端又是一个BpBinder


顺带着看看writeStrongBinder

addService里面出现了一个writeStrongBinder

Parcel数据类型写入一个需要添加Service的Binder

也就是在BpServiceManager持有的BpBinder中再transact这个Parcel数据

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;
    if (binder != NULL) {
        IBinder *local = binder->localBinder();
        if (!local) {
            BpBinder *proxy = binder->remoteBinder();
            if (proxy == NULL) {
                ALOGE("null proxy");
            }
            const int32_t handle = proxy ? proxy->handle() : 0;
            obj.type = BINDER_TYPE_HANDLE;
            obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */
            obj.handle = handle;
            obj.cookie = 0;
        } else {
            obj.type = BINDER_TYPE_BINDER;
            obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
            obj.cookie = reinterpret_cast<uintptr_t>(local);
        }
    } else {
        obj.type = BINDER_TYPE_BINDER;
        obj.binder = 0;
        obj.cookie = 0;
    }


    return finish_flatten_binder(binder, obj, out);
}


获取这个Binder是否有remote()。如果有,写入handler,handler相当于排列号,之后ServiceManager收到这个数据

会也一个列表存下该Service名字和号码,以后你想获取这个服务,也是根据号码返回一个Binder







0 0