Android学习(六)getService(String16(media.player))

sm->getService(String16("media.player"))

昨天分析到这里,始终没有搞清楚getService这个函数到底是怎么获取到对应的服务的,具体只有下面两行代码:

sp<IServiceManager> sm = defaultServiceManager();

binder = sm->getService(String16("media.player"));

defaultServiceManager()这个函数调用已经清楚了,所以第一行的调用基本可以等价于以下代码(去除了进程线程对象唯一等等):

sp<IServiceManager> sm  = new BpServiceManager(new BpBinder(0));

所以sm 就是一个BpServiceManager对象,通过BpBinder对象与Binder驱动对话,唤醒ServiceManager进程,再获得ServiceManager的返回,主要是在返回后没有理解,到达的代码如下:

status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)

{

    int32_t cmd;

    int32_t err;

 

    while (1) {

        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_REPLY:

            {

                binder_transaction_data tr;

                err = mIn.read(&tr, sizeof(tr));

                ALOG_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.dataNaNr.buffer),

                            tr.data_size,

                            reinterpret_cast<const size_t*>(tr.dataNaNr.offsets),

                            tr.offsets_size/sizeof(size_t),

                            freeBuffer, this);

                    } else {

                        err = *static_cast<const status_t*>(tr.dataNaNr.buffer);

                        freeBuffer(NULL,

                            reinterpret_cast<const uint8_t*>(tr.dataNaNr.buffer),

                            tr.data_size,

                            reinterpret_cast<const size_t*>(tr.dataNaNr.offsets),

                            tr.offsets_size/sizeof(size_t), this);

                    }

                } else {

                    freeBuffer(NULL,

                        reinterpret_cast<const uint8_t*>(tr.dataNaNr.buffer),

                        tr.data_size,

                        reinterpret_cast<const size_t*>(tr.dataNaNr.offsets),

                        tr.offsets_size/sizeof(size_t), this);

                    continue;

                }

            }

            goto finish;

 

        default:

            err = executeCommand(cmd);

            if (err != NO_ERROR) goto finish;

            break;

        }

    }

这里的reply返回后会一直传到以下代码:

/*\frameworks\native\libs\binder\IServiceManager.cpp*/

class BpServiceManager : public BpInterface<IServiceManager>

{

public:

    BpServiceManager(const sp<IBinder>& impl)

        : BpInterface<IServiceManager>(impl)

    {

    }

 

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

    }

进入Parcel看看reply.readStrongBinder();

sp<IBinder> Parcel::readStrongBinder() const

{

    sp<IBinder> val;

    unflatten_binder(ProcessState::self(), *this, &val);

    return val;

}

 

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 = static_cast<IBinder*>(flat->cookie);

                return finish_unflatten_binder(NULL, *flat, in);

            case BINDER_TYPE_WEAK_BINDER:

                if (flat->binder != NULL) {

                    out->set_object_and_refs(

                        static_cast<IBinder*>(flat->cookie),

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

}

 

这里flat->typeBINDER_TYPE_HANDLE,所以调用ProcessState::getStrongProxyForHandle()函数,这里的handle就是ServiceManager内维护的MediaPlayerService对应的Binder句柄,这个ProcessState根据这个句柄new 了一个BpBinder,并将其保存起来,这样下次需要从ServiceManager请求获取到相同句柄的时候就可以直接返回了。

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)

{

    sp<IBinder> result;

 

    AutoMutex _l(mLock);

 

    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)) {

            if (handle == 0) {

                Parcel data;

                status_t status = IPCThreadState::self()->transact(

                        0, IBinder::PING_TRANSACTION, data, NULL, 0);

                if (status == DEAD_OBJECT)

                   return NULL;

            }

 

            b = new BpBinder(handle); à这里的handle不为0,而是MediaPlayerServiceServiceManager中对应的句柄

            e->binder = b;

            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获得MediaPlayerService的代理:

sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);

根据前面ServiceManager一样,最后调用的是IMediaPlayerServiceasInterface()宏函数,等价于以下:

android::sp<IMediaPlayerService> IMediaPlayerService::asInterface(const android::sp<android::IBinder>& obj)

{

      android::sp<IMediaPlayerService> intr;

      if(obj != NULL ) {

           intr = static_cast<IMediaPlayerService>(

                 obj->queryLocalInterface(IMediaPlayerService::descriptor).get);

                 if (intr == NULL) {

                      intr = new BpMediaPlayerService(obj);

                 }

      }

      return intr;

}

 

sm->getService(String16("media.player"));整个过程就相当于与ServiceManager进程对话,查找相关的服务对应的handle值,再创建一个新BpBinder对象,构造对应服务的Bp对象。

转载于:https://my.oschina.net/honeyandroid/blog/507585

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值