Binder(三)

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

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

status_t MediaPlayer::setDataSource(
        const sp &httpService,
        const char *url, const KeyedVector *headers)
{
    ALOGV("setDataSource(%s)", url);
    status_t err = BAD_VALUE;
    if (url != NULL) {
        //1,获取IMediaPlayerService服务
        const sp& service(getMediaPlayerService());
        if (service != 0) {
            //2,让远程服务创建播放器
            sp 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 sm = defaultServiceManager();
        sp 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(binder);
    }

    return sMediaPlayerService;
}

defaultServiceManager()返回BpServiceManager。

class BpServiceManager : public BpInterface
{
public:
    BpServiceManager(const sp& impl)
        : BpInterface(impl)
    {
    }

    virtual sp getService(const String16& name) const
    {
        unsigned n;
        //最多查询5次
        for (n = 0; n < 5; n++){
            
            sp svc = checkService(name);
            if (svc != NULL) return svc;
            ALOGI("Waiting for service %s...\n", String8(name).string());
            sleep(1);
        }
        return NULL;
    }
//发送查找指令
 virtual sp 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 Parcel::readStrongBinder() const
{
    sp val;
    unflatten_binder(ProcessState::self(), *this, &val);
    return val;
}

status_t unflatten_binder(const sp& proc,
    const Parcel& in, sp* out)
{
   //读取数据
    const flat_binder_object* flat = in.readObject(false);
    //此时为BINDER_TYPE_HANDLE类型
    if (flat) {
        switch (flat->type) {
            case BINDER_TYPE_BINDER:
                *out = reinterpret_cast(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(out->get()), *flat, in);
        }
    }
    return BAD_TYPE;
}
sp ProcessState::getStrongProxyForHandle(int32_t handle)
{
    sp 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 create(
            const sp& 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(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 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
{
public:
    virtual status_t    onTransact( uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0);
};

};
template
class BnInterface : public INTERFACE, public BBinder
{
public:
    virtual sp      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 client =
                interface_cast(data.readStrongBinder());
            int audioSessionId = data.readInt32();
            //创建播放器
            sp 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 MediaPlayerService::create(const sp& client,
        int audioSessionId)
{
    pid_t pid = IPCThreadState::self()->getCallingPid();
    int32_t connId = android_atomic_inc(&mNextConnId);
   //创建Client对象,它是BnMediaPlayer的子类
    sp c = new Client(
            this, pid, connId, client, audioSessionId,
            IPCThreadState::self()->getCallingUid());

    wp 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 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 sm(defaultServiceManager());
    if (sm != NULL) {
        const String16 name("batterystats");
        sp batteryStats =
                interface_cast(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 MediaPlayerService::Client::setDataSource_pre(
        player_type playerType)
{
     //根据类型创建播放器
    sp p = createPlayer(playerType);
    if (p == NULL) {
        return p;
    }

    if (!p->hardwareOutput()) {
        mAudioOutput = new AudioOutput(mAudioSessionId, IPCThreadState::self()->getCallingUid(),
                mPid, mAudioAttributes);
        static_cast(p.get())->setAudioSink(mAudioOutput);
    }

    return p;
}

sp MediaPlayerService::Client::createPlayer(player_type playerType)
{
  
    sp 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 MediaPlayerFactory::createPlayer(
        player_type playerType,
        void* cookie,
        notify_callback_f notifyFunc) {
    sp 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& /*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& /*client*/,
                               const sp& /*source*/,
                               float /*curScore*/) {
        return 1.0;
    }
    //创建播放器
    virtual sp createPlayer() {
        ALOGV(" create NuPlayer");
        return new NuPlayerDriver;
    }
};

到此播放器便创建完成,

你可能感兴趣的:(Binder(三))