media服务启动C/S分析

前言

废话不多说,media媒体服务重要就是了

服务启动

media服务是开机init进程解析init.rc时候启动的
init.rc:

service media /system/bin/mediaserver
    class main
    user media
    group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm
    ioprio rt 4

它启动的是/system/bin/mediaserver的可执行程序,原型是main_mediaserver.cpp

我们直接看他的函数入口main函数关键实现:

        sp<ProcessState> proc(ProcessState::self());
        sp<IServiceManager> sm = defaultServiceManager();
        ALOGI("ServiceManager: %p", sm.get());
        AudioFlinger::instantiate();
        MediaPlayerService::instantiate();
        CameraService::instantiate();
        AudioPolicyService::instantiate();
        registerExtensions();
        ProcessState::self()->startThreadPool();
        IPCThreadState::self()->joinThreadPool();

我们只看上面代码的 MediaPlayerService::instantiate();这一行代码,
跟踪实现可得:

void MediaPlayerService::instantiate() {
    defaultServiceManager()->addService(
            String16("media.player"), new MediaPlayerService());
}

实际就是向defaultServiceManager注册服务,函数启动告一段落,后面说明怎么使用。

java层api调用

上面知道了服务在开机的时候就已经注册到系统的服务管理了,我们上层应用层在开发的时候会用到mediaplayer,不管你使用什么套路,最终都会调用setDataSource这个函数,它又会调用到native层_setDataSource:

    private native void _setDataSource(
        String path, String[] keys, String[] values)
        throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;

_setDataSource在native层代码在
android_media_MediaPlayer.cpp文件中,

{"_setDataSource",       "(Ljava/io/FileDescriptor;JJ)V",    (void *)android_media_MediaPlayer_setDataSourceFD},

它对应着android_media_MediaPlayer_setDataSourceFD函数,继续看这个函数的具体实现:

native层C/S端

static void
android_media_MediaPlayer_setDataSourceFD(JNIEnv *env, jobject thiz, jobject fileDescriptor, jlong offset, jlong length)
{
    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    if (mp == NULL ) {
        jniThrowException(env, "java/lang/IllegalStateException", NULL);
        return;
    }

    if (fileDescriptor == NULL) {
        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
        return;
    }
    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
    ALOGV("setDataSourceFD: fd %d", fd);
    process_media_player_call( env, thiz, mp->setDataSource(fd, offset, length), "java/io/IOException", "setDataSourceFD failed." );
}

可以看到他又调用了native MediaPlayer类的setDataSource函数:

status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length)
{
    ALOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
    status_t err = UNKNOWN_ERROR;
    const sp<IMediaPlayerService>& service(getMediaPlayerService());  //1
    if (service != 0) {
        sp<IMediaPlayer> player(service->create(this, mAudioSessionId)); //2
        if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
            (NO_ERROR != player->setDataSource(fd, offset, length))) {
            player.clear();
        }
        err = attachNewPlayer(player);  //3
    }
    return err;
}

好了,这里是关键地方,速度放慢一点,首先是在注释1处,获取到了media.player服务,然后将返回值给了service这个引用,
注释2通过这个应用,调用了:

    virtual sp<IMediaPlayer> create(
            const sp<IMediaPlayerClient>& client, int audioSessionId) {
        Parcel data, reply;
        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
        data.writeStrongBinder(client->asBinder());
        data.writeInt32(audioSessionId);

        remote()->transact(CREATE, data, &reply);
        return interface_cast<IMediaPlayer>(reply.readStrongBinder());  //4
    }

然后呢,服务端收到CREATE这个信令之后做了什么呢:

        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);//5
            reply->writeStrongBinder(player->asBinder()); //6
            return NO_ERROR;
        } break;

主要注意注释5,6这段代码,结果是返回给上层一个MediaPlayerService::Client的实例,其中注释5所调用的代码如下:

sp<IMediaPlayer> MediaPlayerService::create(const sp<IMediaPlayerClient>& client,
        int audioSessionId)
{
    pid_t pid = IPCThreadState::self()->getCallingPid();
    int32_t connId = android_atomic_inc(&mNextConnId);

    sp<Client> c = new Client(
            this, pid, connId, client, audioSessionId,
            IPCThreadState::self()->getCallingUid());

    ALOGV("Create new client(%d) from pid %d, uid %d, ", connId, pid,
         IPCThreadState::self()->getCallingUid());

    wp<Client> w = c;
    {
        Mutex::Autolock lock(mLock);
        mClients.add(w);
    }
    return c;
}

上层收到返回值之后,会调用 interface_cast,即注释4所在代码,
interface_cast实现:

template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
    return INTERFACE::asInterface(obj);
}

asInterface实现:

    android::sp<I##INTERFACE> I##INTERFACE::asInterface(              
            const android::sp<android::IBinder>& obj)              
    {                                                              
        android::sp<I##INTERFACE> intr;                                
        if (obj != NULL) {                                              
            intr = static_cast<I##INTERFACE*>(                        
                obj->queryLocalInterface(                             
                        I##INTERFACE::descriptor).get());               
            if (intr == NULL) {                                         
                intr = new Bp##INTERFACE(obj);                          
            }                                                           
        }                                                               
        return intr;                                                    
    }    

所以说注释4中最终返回给再上一层的是一个BpMediaPlayer对象
我们再回到注释3中,看这个attachNewPlayer函数实现:

status_t MediaPlayer::attachNewPlayer(const sp<IMediaPlayer>& player)
{
    status_t err = UNKNOWN_ERROR;
    sp<IMediaPlayer> p;
    { // scope for the lock
        Mutex::Autolock _l(mLock);

        if ( !( (mCurrentState & MEDIA_PLAYER_IDLE) ||
                (mCurrentState == MEDIA_PLAYER_STATE_ERROR ) ) ) {
            ALOGE("attachNewPlayer called in state %d", mCurrentState);
            return INVALID_OPERATION;
        }

        clear_l();
        p = mPlayer;           //7
        mPlayer = player;   //8
        if (player != 0) {
            mCurrentState = MEDIA_PLAYER_INITIALIZED;
            err = NO_ERROR;
        } else {
            ALOGE("Unable to create media player");
        }
    }

    if (p != 0) {
        p->disconnect();
    }

    return err;
}

再看一下注释7,8是关键,mPlayer 现在就是BpMediaPlayer这个对象了,后面start或者其他操作就可以通过binder调用
到BnMediaPlayer,而BnMediaPlayer是Client的父类,最终其实就是在调用MediaPlayerService::Client的函数。

后记

mediaplayer蛮有意思的,可以更好的辅助理解binder实现机制

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值