美文网首页
Binder(三)

Binder(三)

作者: JackyWu15 | 来源:发表于2020-01-21 18:38 被阅读0次

    接着上一篇,MediaPlayerService已经被注册到ServiceManager中了,本篇将接着分析MediaPlayerService服务的获取,以及通过MediaPlayerService服务创建播放器2个流程。

    <Binder(一)>一篇知道,MediaPlayer.java调用setDataSource方法,最终会调用MediaPlayer.cpp的setDataSource函数。

    status_t MediaPlayer::setDataSource(
            const sp<IMediaHTTPService> &httpService,
            const char *url, const KeyedVector<String8, String8> *headers)
    {
        ALOGV("setDataSource(%s)", url);
        status_t err = BAD_VALUE;
        if (url != NULL) {
            //1,获取IMediaPlayerService服务
            const sp<IMediaPlayerService>& service(getMediaPlayerService());
            if (service != 0) {
                //2,让远程服务创建播放器
                sp<IMediaPlayer> player(service->create(this, mAudioSessionId));
                if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
                        //通过IMediaPlayer操作播放器
                    (NO_ERROR != player->setDataSource(httpService, url, headers))) {
                    player.clear();
                }
                err = attachNewPlayer(player);
            }
        }
        return err;
    }
    

    我们先看getMediaPlayerService()函数的执行过程。

    IMediaDeathNotifier::getMediaPlayerService()
    {
        ALOGV("getMediaPlayerService");
        Mutex::Autolock _l(sServiceLock);
        if (sMediaPlayerService == 0) {
            //获取IServiceManager
            sp<IServiceManager> sm = defaultServiceManager();
            sp<IBinder> binder;
            do {
                //使用String16("media.player")获取服务
                binder = sm->getService(String16("media.player"));
                if (binder != 0) {
                    break;
                }
                //如果服务还未注册,等待
                usleep(500000); // 0.5 s
            } while (true);
    
            if (sDeathNotifier == NULL) {
                sDeathNotifier = new DeathNotifier();
            }
            binder->linkToDeath(sDeathNotifier);
            //将IBinder保存到BpMediaPlayerService的成员变量mRemote中
            sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);
        }
    
        return sMediaPlayerService;
    }
    

    defaultServiceManager()返回BpServiceManager。

    class BpServiceManager : public BpInterface<IServiceManager>
    {
    public:
        BpServiceManager(const sp<IBinder>& impl)
            : BpInterface<IServiceManager>(impl)
        {
        }
    
        virtual sp<IBinder> getService(const String16& name) const
        {
            unsigned n;
            //最多查询5次
            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);
            //发送CHECK_SERVICE_TRANSACTION指令
            remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
            //读取响应数据
            return reply.readStrongBinder();
        }
    
    

    transact会通过BpBinder(0)发送数据给ServiceManager查找名字为"media.player"的Service,在上一篇分析过,ServiceManager会通过svcmgr_handler函数来处理请求。

    int svcmgr_handler(struct binder_state *bs,
                       struct binder_transaction_data *txn,
                       struct binder_io *msg,
                       struct binder_io *reply)
    {
        ......
    
        switch(txn->code) {
        //获取某个Service,通过msg来取
        case SVC_MGR_GET_SERVICE:
        case SVC_MGR_CHECK_SERVICE:
            //s为对应Service名字
            s = bio_get_string16(msg, &len);
            if (s == NULL) {
                return -1;
            }
            //查找Service,返回handle值
            handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid);
            //不为0则找到
            if (!handle)
                break;
            //写入reply回传给客户端
            bio_put_ref(reply, handle);
            return 0;
    
    

    do_find_service根据"media.player"进行查找,并返回它的句柄handle。

    uint32_t do_find_service(struct binder_state *bs, const uint16_t *s, size_t len, uid_t uid, pid_t spid)
    {
        struct svcinfo *si;
        //检查权限
        if (!svc_can_find(s, len, spid)) {
            ALOGE("find_service('%s') uid=%d - PERMISSION DENIED\n",
                 str8(s, len), uid);
            return 0;
        }
        //查找服务
        si = find_svc(s, len);
         //si不为null,handle大于0
        if (si && si->handle) {
            if (!si->allow_isolated) {
              
                uid_t appid = uid % AID_USER;
                if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) {
                    return 0;
                }
            }
            //成功返回handle
            return si->handle;
        } else {
            return 0;
        }
    }
    

    继续看查找的关键函数find_svc。

    struct svcinfo *find_svc(const uint16_t *s16, size_t len)
    {
        struct svcinfo *si;
        //遍历
        for (si = svclist; si; si = si->next) {
            if ((len == si->len) &&
                !memcmp(s16, si->name, len * sizeof(uint16_t))) {
                return si;
            }
        }
        return NULL;
    }
    

    Service整个查找过程,就是根据Service名去遍历svcinfo链表,找到svcinfo结构体后,将svcinfo的handle值写入缓存,回传给客户端。

    我们回头看reply.readStrongBinder()这个方法如何解析响应数据,和返回需要的服务对象。reply是一个Parcel类。

    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, sp<IBinder>* out)
    {
       //读取数据
        const flat_binder_object* flat = in.readObject(false);
        //此时为BINDER_TYPE_HANDLE类型
        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_HANDLE:
                    //传入handle
                    *out = proc->getStrongProxyForHandle(flat->handle);
                    return finish_unflatten_binder(
                        static_cast<BpBinder*>(out->get()), *flat, in);
            }
        }
        return BAD_TYPE;
    }
    
    sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
    {
        sp<IBinder> result;
    
        AutoMutex _l(mLock);
        //构建一个entry
        handle_entry* e = lookupHandleLocked(handle);
        if (e != NULL) {
            IBinder* b = e->binder;
            if (b == NULL || !e->refs->attemptIncWeak(this)) {
                //此时handle不为0
                if (handle == 0) {
                     Parcel data;
                    //ping下驱动是否通
                    status_t status = IPCThreadState::self()->transact(
                            0, IBinder::PING_TRANSACTION, data, NULL, 0);
                    if (status == DEAD_OBJECT)
                       return NULL;
                }
                //根据handle创建了一个BpBinder
                b = new BpBinder(handle); 
                e->binder = b;
                if (b) e->refs = b->getWeakRefs();
              //将创建的BpBinder返回
                result = b;
            } else {
                 result.force_set(b);
                e->refs->decWeak(this);
            }
        }
        return result;
    }
    

    这里的流程和获取IServiceManger是相同的,只是此时的handle大于0,它通过ProcessState创建了一个BpBinder(handle)。

    回到IMediaDeathNotifier::getMediaPlayerService函数,BpBinder(handle)同样通过interface_cast进行了强转,强转流程可以看前面IServiceManger的获取流程。

    也就是说,最终客户端得到一个BpMediaPlayerService,它的成员变量mRemote持有一个BpBinder(handle),有了这个handle句柄,就能通过Binder驱动和MediaPlayerService进行通讯了。

    流程1到此分析完成,即当前已获取到了IMediaPlayerService。继续分析流程2,IMediaPlayerService调用了create函数,创建播放器。

     virtual sp<IMediaPlayer> create(
                const sp<IMediaPlayerClient>& client, int audioSessionId) {
            Parcel data, reply;
            data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
            data.writeStrongBinder(client->asBinder());
            data.writeInt32(audioSessionId);
            //获取mRemote,发送创建指令CREATE,
            remote()->transact(CREATE, data, &reply);
            //返回播放器引用
            return interface_cast<IMediaPlayer>(reply.readStrongBinder());
        }
    
    

    通过remote()获取mRemote,即BpBinder(0)发送CREATE创建指令。上一篇分析过,MediaPlayerService在MediaServer中创建,并开启了两个线程循环执行talkWithDriver函数,循环读写消息,假设其中一个线程收到CREATE这个指令,最终将执行executeCommand函数,

    status_t IPCThreadState::executeCommand(int32_t cmd)
    {
        BBinder* obj;
        RefBase::weakref_type* refs;
        status_t result = NO_ERROR;
        
        switch (cmd) {
          ......
        case BR_TRANSACTION:
            {
                binder_transaction_data tr;
                result = mIn.read(&tr, sizeof(tr));
            
                if (result != NO_ERROR) break;
                ......
    
                Parcel reply;
                status_t error;
               //转为BBinder对象,实际就是BnMediaPlayerService
                if (tr.target.ptr) {
                    sp<BBinder> b((BBinder*)tr.cookie);
                    error = b->transact(tr.code, buffer, &reply, tr.flags);
    
                } else {
                    error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
                }
    

    BpXXX对应着服务端在客户端的业务代理,而Bn则对应服务端本地的业务处理类,因此每个服务端都包含一个BnXXX内部类,它继承模板类BnInterface和BBinder对象。

    class BnMediaPlayerService: public BnInterface<IMediaPlayerService>
    {
    public:
        virtual status_t    onTransact( uint32_t code,
                                        const Parcel& data,
                                        Parcel* reply,
                                        uint32_t flags = 0);
    };
    
    };
    
    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();
    };
    
    

    而transact函数定义在BBinder中,直接看transact函数。

    status_t BBinder::transact(
        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
    {
        data.setDataPosition(0);
    
        status_t err = NO_ERROR;
        switch (code) {
            case PING_TRANSACTION:
                reply->writeInt32(pingBinder());
                break;
            default:
              //处理消息数据
                err = onTransact(code, data, reply, flags);
                break;
        }
    
        if (reply != NULL) {
            reply->setDataPosition(0);
        }
    
        return err;
    }
    

    onTransact用于处理消息数据,它是一个虚函数,由继承关系知道,它实现在BnMediaPlayerService中。

    status_t BnMediaPlayerService::onTransact(
        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
    {
        switch (code) {
              ......
            case CREATE: {
                CHECK_INTERFACE(IMediaPlayerService, data, reply);
                sp<IMediaPlayerClient> client =
                    interface_cast<IMediaPlayerClient>(data.readStrongBinder());
                int audioSessionId = data.readInt32();
                //创建播放器
                sp<IMediaPlayer> player = create(client, audioSessionId);
                //将播放器转为Binder类型的数据,写入响应缓冲区
                reply->writeStrongBinder(player->asBinder());
                return NO_ERROR;
            } break;
         ......
            default:
                return BBinder::onTransact(code, data, reply, flags);
        }
    }
    

    如上,BnMediaPlayerService将会创建一个播放器,返回给MediaPlayer.cpp客户端,这个MediaPlayer.cpp的远程服务端是一个MediaPlayerService的内部类,为Client,它继承自IMediaPlayer。

    sp<IMediaPlayer> MediaPlayerService::create(const sp<IMediaPlayerClient>& client,
            int audioSessionId)
    {
        pid_t pid = IPCThreadState::self()->getCallingPid();
        int32_t connId = android_atomic_inc(&mNextConnId);
       //创建Client对象,它是BnMediaPlayer的子类
        sp<Client> c = new Client(
                this, pid, connId, client, audioSessionId,
                IPCThreadState::self()->getCallingUid());
    
        wp<Client> w = c;
        {
            Mutex::Autolock lock(mLock);
            mClients.add(w);
        }
        return c;
    }
    

    Client是MediaPlayerService的内部类,它继承自BnMediaPlayer,也就是IMediaPlayer的服务端,函数返回后,也就是客户端得到Client的远程对象代理,那么紧接着会执行Client的setDataSource函数。

    status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64_t length)
    {
        ALOGV("setDataSource fd=%d, offset=%lld, length=%lld", fd, offset, length);
        struct stat sb;
        int ret = fstat(fd, &sb);
        if (ret != 0) {
       
            return UNKNOWN_ERROR;
        }
    
    
        if (offset >= sb.st_size) {
            ALOGE("offset error");
            ::close(fd);
            return UNKNOWN_ERROR;
        }
        if (offset + length > sb.st_size) {
            length = sb.st_size - offset;
            ALOGV("calculated length = %lld", length);
        }
      //获取到当前适合播放该视频源的播放器类型
        player_type playerType = MediaPlayerFactory::getPlayerType(this,
                                                                   fd,
                                                                   offset,
                                                                   length);
       // 根据得到的播放器类型去创建对应的播放器实例:
        sp<MediaPlayerBase> p = setDataSource_pre(playerType);
        if (p == NULL) {
            return NO_INIT;
        }
       
        setDataSource_post(p, p->setDataSource(fd, offset, length));
        return mStatus;
    }
    

    这里分两步执行,先获取到适合播放该视频源的播放器类型,再根据这个类型去创建播放器。MediaPlayerFactory保存的工厂类,在MediaPlayerService构造时就注册好了。

    MediaPlayerService::MediaPlayerService()
    {
        ALOGV("MediaPlayerService created");
        mNextConnId = 1;
    
        mBatteryAudio.refCount = 0;
        for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
            mBatteryAudio.deviceOn[i] = 0;
            mBatteryAudio.lastTime[i] = 0;
            mBatteryAudio.totalTime[i] = 0;
        }
    
        mBatteryAudio.deviceOn[SPEAKER] = 1;
    
        const sp<IServiceManager> sm(defaultServiceManager());
        if (sm != NULL) {
            const String16 name("batterystats");
            sp<IBatteryStats> batteryStats =
                    interface_cast<IBatteryStats>(sm->getService(name));
            if (batteryStats != NULL) {
                batteryStats->noteResetVideo();
                batteryStats->noteResetAudio();
            }
        }
        //注册播放器工厂类
        MediaPlayerFactory::registerBuiltinFactories();
    }
    

    构造函数最后一行注册了所有类型播放器工厂。

    void MediaPlayerFactory::registerBuiltinFactories() {
        Mutex::Autolock lock_(&sLock);
    
        if (sInitComplete)
            return;
    
        registerFactory_l(new StagefrightPlayerFactory(), STAGEFRIGHT_PLAYER);
        registerFactory_l(new NuPlayerFactory(), NU_PLAYER);
        registerFactory_l(new SonivoxPlayerFactory(), SONIVOX_PLAYER);
        registerFactory_l(new TestPlayerFactory(), TEST_PLAYER);
    
        sInitComplete = true;
    }
    

    我们回头看根据类型获取播放器的函数setDataSource_pre。

    sp<MediaPlayerBase> MediaPlayerService::Client::setDataSource_pre(
            player_type playerType)
    {
         //根据类型创建播放器
        sp<MediaPlayerBase> p = createPlayer(playerType);
        if (p == NULL) {
            return p;
        }
    
        if (!p->hardwareOutput()) {
            mAudioOutput = new AudioOutput(mAudioSessionId, IPCThreadState::self()->getCallingUid(),
                    mPid, mAudioAttributes);
            static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
        }
    
        return p;
    }
    
    
    sp<MediaPlayerBase> MediaPlayerService::Client::createPlayer(player_type playerType)
    {
      
        sp<MediaPlayerBase> p = mPlayer;
        if ((p != NULL) && (p->playerType() != playerType)) {
            ALOGV("delete player");
            p.clear();
        }
        //通过工厂类创建播放器
        if (p == NULL) {
            p = MediaPlayerFactory::createPlayer(playerType, this, notify);
        }
    
        if (p != NULL) {
            p->setUID(mUID);
        }
    
        return p;
    }
    

    关键代码所示,MediaPlayerFactory工厂类获取播放器。

    sp<MediaPlayerBase> MediaPlayerFactory::createPlayer(
            player_type playerType,
            void* cookie,
            notify_callback_f notifyFunc) {
        sp<MediaPlayerBase> p;
        IFactory* factory;
        status_t init_result;
        Mutex::Autolock lock_(&sLock);
    
        if (sFactoryMap.indexOfKey(playerType) < 0) {
            ALOGE("Failed to create player object of type %d, no registered"
                  " factory", playerType);
            return p;
        }
        //从sFactoryMap获取对应的工厂类
        factory = sFactoryMap.valueFor(playerType);
        CHECK(NULL != factory);
    
        //通过IFactory内部类的不同实现类,创建不同的MediaPlayer
        p = factory->createPlayer();
    
        if (p == NULL) {
            ALOGE("Failed to create player object of type %d, create failed",
                   playerType);
            return p;
        }
    
        init_result = p->initCheck();
        if (init_result == NO_ERROR) {
            p->setNotifyCallback(cookie, notifyFunc);
        } else {
            p.clear();
        }
    
        return p;
    }
    

    在注册工厂类时已经将各类型工厂加入到成员sFactoryMap中,此时根据类型获取到特定的工厂,并通过createPlayer创建播放器,安卓有2种类型的播放器,以NuPlayerFactory为例来看下创建的函数。

    class NuPlayerFactory : public MediaPlayerFactory::IFactory {
      public:
        virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
                                   const char* url,
                                   float curScore) {
            static const float kOurScore = 0.8;
    
            if (kOurScore <= curScore)
                return 0.0;
    
            if (!strncasecmp("http://", url, 7)
                    || !strncasecmp("https://", url, 8)
                    || !strncasecmp("file://", url, 7)) {
                size_t len = strlen(url);
                if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
                    return kOurScore;
                }
    
                if (strstr(url,"m3u8")) {
                    return kOurScore;
                }
    
                if ((len >= 4 && !strcasecmp(".sdp", &url[len - 4])) || strstr(url, ".sdp?")) {
                    return kOurScore;
                }
            }
    
            if (!strncasecmp("rtsp://", url, 7)) {
                return kOurScore;
            }
    
            return 0.0;
        }
    
        virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
                                   const sp<IStreamSource>& /*source*/,
                                   float /*curScore*/) {
            return 1.0;
        }
        //创建播放器
        virtual sp<MediaPlayerBase> createPlayer() {
            ALOGV(" create NuPlayer");
            return new NuPlayerDriver;
        }
    };
    
    

    到此播放器便创建完成,

    相关文章

      网友评论

          本文标题:Binder(三)

          本文链接:https://www.haomeiwen.com/subject/mvfszctx.html