Android Mediaplayer

JAVA类的路径:
frameworks/base/media/java/android/media/MediaPlayer.java

JAVA本地调用部分(JNI):
frameworks/base/media/jni/android_media_MediaPlayer.cpp 这部分内容编译成为目标是libmedia_jni.so。

主要的头文件在以下的目录中:frameworks/base/include/media/

多媒体底层库在以下的目录中:frameworks/av/media/libmedia/
这部分的内容被编译成库libmedia.so。

多媒体服务部分:
frameworks/av/media/libmediaplayerservice/
文件为mediaplayerservice.h和mediaplayerservice.cpp
这部分内容被编译成库libmediaplayerservice.so。

int main(int argc __unused, char** argv)
{
    ...
    InitializeIcuOrDie();  
    //获得ProcessState实例对象
    sp<ProcessState> proc(ProcessState::self());
    //获取ServiceManager实例对象 
    sp<IServiceManager> sm = defaultServiceManager();
    AudioFlinger::instantiate();

    MediaPlayerService::instantiate();
    ResourceManagerService::instantiate();
    CameraService::instantiate();
    AudioPolicyService::instantiate();
    SoundTriggerHwService::instantiate();
    RadioService::instantiate();
    registerExtensions();

    ProcessState::self()->startThreadPool();

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

defaultServiceManager

获取Service Manager远程接口的函数是defaultServiceManager.
gDefaultServiceManager是单例模式,调用defaultServiceManager函数时,如果gDefaultServiceManager已经创建,
则直接返回,否则通过interface_cast(ProcessState::self()->getContextObject(NULL))来创建一个,
并保存在gDefaultServiceManager全局变量中.

getService接口来获得.Service Manager远程接口是一个特殊的Binder引用,它的引用句柄一定是0。

ProcessState::ProcessState()
    : mDriverFD(open_driver()) 
    , mVMStart(MAP_FAILED)
    , mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
    , mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
    , mExecutingThreadsCount(0)
    , mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
    , mManagesContexts(false)
    , mBinderContextCheckFunc(NULL)
    , mBinderContextUserData(NULL)
    , mThreadPoolStarted(false)
    , mThreadPoolSeq(1)
{
    if (mDriverFD >= 0) {
        //采用内存映射函数mmap,给binder分配一块虚拟地址空间,用来接收事务
        mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
        if (mVMStart == MAP_FAILED) {
            close(mDriverFD); //没有足够空间分配给/dev/binder,则关闭驱动
            mDriverFD = -1;
        }
    }
}

ProcessState的单例模式的惟一性,因此一个进程只打开binder设备一次,其中ProcessState的成员变量mDriverFD记录binder驱动的fd,用于访问binder设备。

BINDER_VM_SIZE = (1*1024*1024) - (4096 *2), binder分配的默认内存大小为1M-8k。

DEFAULT_MAX_BINDER_THREADS = 15,binder默认的最大可并发访问的线程数为16。

sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
    //获取handle=0的IBinder
    return getStrongProxyForHandle(0);  
}

interface_cast

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

对于asInterface()函数,也是通过模板函数来定义的,通过下面两个代码完成的:

//位于IServiceManager.h文件
DECLARE_META_INTERFACE(IServiceManager)
//位于IServiceManager.cpp文件
IMPLEMENT_META_INTERFACE(ServiceManager,"android.os.IServiceManager")

IServiceManager::asInterface() 等价于 new BpServiceManager()

交互

如果我们要使用MediaPlayerService服务,那么MediaPlayerService客户端就需要与MediaPlayerService
(即BnMediaPlayerService)交互。交互的过程需要建立一个循环,然后读写Binder设备。注意,
在BnMediaPlayerService中并没有打开Binder设备和建立一个循环监听,这里实际上是借用ProcessState来完成了MediaPlayerService的一些功能.

IPCThreadState::self()->joinThreadPool,也就是说,主线程和工作线程都会执行joinThreadPool;
在该函数中通过talkWithDriver函数操作Binder驱动程序,executeCommand函数来执行命令。
查看executeCommand的代码可以得知,实际上会根据不同的命令进行不同的解析,
但是最终的解析还是调用BBinder::transact函数,而transact又调用了自己的BBinder::onTransact函数。
这里的BnMediaPlayerService继承自BBinder,所以会调用到它自己的BnMediaPlayerService::onTransact函数。

客户端

libs/media/mediaplayer.cpp

class MediaPlayer : public BnMediaPlayerClient,
                    public virtual IMediaDeathNotifier
const sp<IMediaPlayerService>& service(getMediaPlayerService());  
        if (service != 0) {  
            sp<IMediaPlayer> player(service->create(getpid(), this, url));  
            err = setDataSource(player);  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值