MediaPlayerService分析

一.MediaPlayerService简介

1.Media Service的启动

Media进程定义:

service media /system/bin/mediaserver

    class main

    user media

    group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc

    ioprio rt 4

servicemanager 进程定义:

service servicemanager /system/bin/servicemanager

    class core

    user system

  group system

Media中有很多Native ServiceAudioFlinger MediaPlayerService CameraService AudioPolicyService等),整个Androidnative或者framework)的Service都需要加入servicemanager中进行统一管理。
  那么Media Process ServiceManager Process是如何进行通信的呢——Binder.通过Media Process中使用binder进行完成IPC过程,学习Binder的概念和使用方法

2.MediaPlayer的文件

MediaPlayer是从MediaPlayer.java开始的,应用如果想播放音乐,先要new 一个MediaPlayer,并设置其相关的参数。先列出主要的代码文件,他们都在frameworks里面:

Java层代码:base/media/java/android/media/MediaPlayer.java

Jni层代码:

base/media/jni/android_media_MediaPlayer.cpp

本地代码:

av/media/libmedia/mediaplayer.cpp

./av/media/libmedia/IMediaPlayer.cpp

MediaPlayerService

av/media/libmediaplayerservice/MediaPlayerService.cpp

 

二.分析MediaPlayer的Binder机制

\frameworks\av\media\mediaserver\ main_mediaserver.cpp

MediaPlayerService分析_第1张图片

1 .   ProcessState对象创建

当前进程的状态属性,对象创建:

sp ProcessState::self()

{

    Mutex::Autolock _l(gProcessMutex);

    if (gProcess != NULL) {

        return gProcess;

    }

    gProcess = new ProcessState;

    return gProcess;

}

ProcessState构造函数:

ProcessState::ProcessState()

    : mDriverFD(open_driver())    //打开binder驱动设备

    , mVMStart(MAP_FAILED)

    , mManagesContexts(false)

    , mBinderContextCheckFunc(NULL)

    , mBinderContextUserData(NULL)

    , mThreadPoolStarted(false)

    , mThreadPoolSeq(1)

{

    if (mDriverFD >= 0) {

        //binderfd映射到当前进程虚拟空间地址中 binder进行交互

        mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ,

        MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);

    }

}

 

打开binder设备:

static int open_driver()

{

    //打开binder设备驱动

    int fd = open("/dev/binder", O_RDWR);

    if (fd >= 0) {

        //bidner最大支持线程数

        size_t maxThreads = 15;

        result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);

    }

    return fd;

}

ProcessState对象创建过程所做的事:
  打开/dev/binder设备,得到binder设备的fd
  将bidner设备fd映射到当前进程虚拟地址空间建立交互的通道;

2. IServiceManager对象创建
  sp sm = defaultServiceManager();
为什么需要一个IServiceManager对象呢,这个类是个抽象提供接口

class IServiceManager : public IInterface

{

    virtual sp getService( const String16& name) const = 0;

    virtual status_t addService( const String16& name,

                             const sp& service,

                             bool allowIsolated = false) = 0;

    ……                                   

};

  通过IServiceManager派生对象操作将Service加入到ServiceManager.

defaultServiceManager()函数

MediaPlayerService分析_第2张图片

ProcessState::self()->getContextObject(NULL)得到一个IBinder对象

ProcessState::self()刚才所创建的ProcessState对象。

 

MediaPlayerService分析_第3张图片

handle_entry是什么呢?

  struct handle_entry {

                IBinder* binder;

                RefBase::weakref_type* refs;

            };

  也就是说ProcessState 有一个表VectormHandleToObject;

表里面的每一项存储了一个binder,每一个binder对应一个handle

  MediaPlayerService分析_第4张图片MediaPlayerService分析_第5张图片

  Handle = 0是什么,句柄? 代表谁的句柄——ServiceManagerbinder中的资源。
ProcessState::self()->getContextObject(NULL)得到一个 IBinder——BpBinder(0);

于是得到:
  gDefaultServiceManager = interface_cast(BpBinder(0))

使用interface_castIBinder实例转化成IServiceManager实例。

MediaPlayerService分析_第6张图片

翻译为:

inline sp interface_cast(const sp& obj)

{

    return IServiceManager::asInterface(obj);

}

MediaPlayerService分析_第7张图片

替换成IServiceManager:

android::sp IServiceManager::asInterface(               

            const android::sp& obj)                  

{  

        //obj BpBinder实例                                                               

        android::sp intr;                               

        if (obj != NULL) {

            //返回NULL                                       

            intr = static_cast(                         

                obj->queryLocalInterface(                               

                        IServiceManager::descriptor).get());             

            if (intr == NULL) {                                        

                intr = new BpServiceManager(obj);                         

            }                                                           

        }                                                              

        return intr;                                                   

}

这里得到IServiceManager 实例:

 BpServiceManagernew BpServiceManagernew BpBinder0));

MediaPlayerService分析_第8张图片

关注BpServiceManager继承于模板类BpInterface

BpInterface构造函数:

MediaPlayerService分析_第9张图片

BpRefBase构造函数:

MediaPlayerService分析_第10张图片

  gDefaultServiceManager = interface_cast(BpBinder(0))
实际为:
  gDefaultServiceManager = new BpServiceManagernew BpBinder0));
Bn代表Binder Native Bp代表Binder Proxy
BpServiceManager代理的BpBinder实例 BpBinder代理的handle0

这个关系有些复杂,看一下类继承结构图:

MediaPlayerService分析_第11张图片MediaPlayerService分析_第12张图片

上面这个结构看起来感觉很熟悉——Bridge模式。将Binder数据交互和功能处理桥接起来。

Media Process main函数中通过:

  sp sm = defaultServiceManager();
  我们得到了sm:是BpServiceManager对象。

3.    MediaPlayerService加入到ServiceManager中

回到main函数中:

MediaPlayerService分析_第13张图片

MediaPlayerService::instantiate();

MediaPlayerService分析_第14张图片

BpServiceManager添加Service

virtual status_t addService(const String16& name, const sp& service,

            bool allowIsolated)

{

        //生成数据包Parcel

        Parcel data, reply;

        // Write RPC headers 写入Interface名字 得到android.os.IServiceManager

        data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());

        //写入Service名字 media.player

        data.writeString16(name);

        //写入服务

        data.writeStrongBinder(service);

        data.writeInt32(allowIsolated ? 1 : 0);

        // remote()返回BpBinder对象

        status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);

        return err == NO_ERROR ? reply.readExceptionCode() : err;

}

remote()->transact BpBinder

status_t BpBinder::transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)

{

if (mAlive) {

        //到当前进程IPCThreadState mHandle=0

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

            mHandle, code, data, reply, flags);

        if (status == DEAD_OBJECT) mAlive = 0;

        return status;

    }

    return DEAD_OBJECT;

}

IPCThreadState中写入数据到Binder设备过程

IPCThreadState::self()->transact过程:

status_t IPCThreadState::transact(int32_t handle,

                            uint32_t code, const Parcel& data,

                            Parcel* reply, uint32_t flags)

{

    status_t err = data.errorCheck();

 

    flags |= TF_ACCEPT_FDS;

    //将数据转化成binder_transaction_data 写入到Parcel实例mOut

    err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);

    //写入数据

    err = waitForResponse(reply);

    return err;

}

 

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

{

    while (1) {

        //将数据写入到Binder设备中

        talkWithDriver();

        ……

    }

    return err;

}

 

status_t IPCThreadState::talkWithDriver(bool doReceive)

{

    //将数据封装成binder_write_read结构

    binder_write_read bwr;

 

    do {

        //将数据写入到所打开的Binder设备中

        ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)

        ……

   

    } while (err == -EINTR);

    return NO_ERROR;

}

MediaPlayerService加入到ServiceManager中,

这里就通过BpServiceManagerAddService将数据写入到Binder设备传递给ServiceManager

继续Media Process过程

4.    Media Process消息循

 

int main(int argc, char** argv)

{

    //启动进程的线程池   

    ProcessState::self()->startThreadPool();     //走到了这里

 

    //执行线程消息循环

    IPCThreadState::self()->joinThreadPool();

}

  1. 创建工作者线程

void ProcessState::startThreadPool()

{

    spawnPooledThread(true);

}

 

void ProcessState::spawnPooledThread(bool isMain)

{

    //创建PoolThread对象 run ,非线程

    sp t = new PoolThread(isMain);

  t->run(buf);

}

PoolThread继承Thread

执行Threadrun函数:

status_t Thread::run(const char* name, int32_t priority, size_t stack)

{

    //创建线程mThread _threadLoop

    bool res;

    res = createThreadEtc(_threadLoop,

    this, name, priority, stack, &mThread);

    return NO_ERROR;

}

现在有两个线程:主线程和mThread线程

mThread线程执行:_threadLoop

int Thread::_threadLoop(void* user)

{

    Thread* const self = static_cast(user);

    do {

        //调用子类的threadLoop

        result = self->threadLoop();

        ……

    } while(strong != 0);

    return 0;

}

 

class PoolThread : public Thread

{

protected:

    virtual bool threadLoop()

    {

        IPCThreadState::self()->joinThreadPool(mIsMain);

        return false;

    }

};

2 进程间通信消息循环过程

消息循环

void IPCThreadState::joinThreadPool(bool isMain)

{

    mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);

    status_t result;   

    //消息循环

    do {

        int32_t cmd;

        //binder设备中读取命令

        result = talkWithDriver();

        if (result >= NO_ERROR) {

            cmd = mIn.readInt32();

            //执行命令

            result = executeCommand(cmd);

        }

           ……

    } while (result != -ECONNREFUSED && result != -EBADF);

   

    mOut.writeInt32(BC_EXIT_LOOPER);

    talkWithDriver(false);

}

命令执行

status_t IPCThreadState::executeCommand(int32_t cmd)

{

    BBinder* obj;

    RefBase::weakref_type* refs;

    switch (cmd) {

    case BR_DECREFS:

        break;

    case BR_ATTEMPT_ACQUIRE:

        break;

case BR_TRANSACTION:

  binder_transaction_data tr;

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

      if (tr.target.ptr) {

        //将目标对象转化成BBinder

        sp b((BBinder*)tr.cookie);

        //调用BBindertransact 函数

       const status_t error = b->transact(tr.code, buffer, &reply, tr.flags);

      }

        break;

    ……

    default:

    }

    return result;

}

binder_transaction_data.cookietarget object cookie目标对象,这个target object是指那个呢?

Media Process里面有几个ServiceAudioFlingerMediaPlayerServiceCameraService等。

这个目标是这其中Service中的一个,假设目标对象为为MediaPlayerService,那为何要转化成BBinder呢?

3 Service对命令的处

线程从binder接收到消息命令,将命令传递给Service处理。将目标对象转化成BBinder,然后调度此命令;

命令从远端传递到本地端进行处理,每个Service都对应BnXXX对象来处理远端BpXXX传来的命令。

sp b((BBinder*)tr.cookie);
  const status_t error = b->transact(tr.code, buffer, &reply, tr.flags);
  这里b代表某个Service:假设为MediaPlayerService;弄清楚执行过程,要弄清楚类继承关系

MediaPlayerService分析_第15张图片

本地端BnMediaPlayerService消息处理过程:真正的对象是MediaPlayerService实例。
BBinder ->transact开始传递

status_t BBinder::transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)

{

    //onTransact是个virtual函数 派生类BnMediaPlayerService重写

    err = onTransact(code, data, reply, flags);

    return err;

}

 

status_t BnMediaPlayerService::onTransact(

    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)

{

    switch (code) {

        case CREATE: {

            pid_t pid = data.readInt32();

            sp client =

                interface_cast(data.readStrongBinder());

            //create是个virtual函数 派生类MediaPlayerService重写

            sp player = create(pid, client, audioSessionId);

            //创建player写入到数据包中 传回

            reply->writeStrongBinder(player->asBinder());

            return NO_ERROR;

        } break;

        ……

        default:

            return BBinder::onTransact(code, data, reply, flags);

    }

}

可以看看Client类继承关系结构图

MediaPlayerService分析_第16张图片    

  看到这个跟上面的MediaPlayerService继承关系非常的相似,

  这个结构也非常的熟悉——Adapter模式;将binder消息交互和命令处理适配到一起。

 

Client端与Service端交

ClientService进行使用Binder通信,是得到一个Service BnXXX端对象的代理,在Client BpXXX代理,

然后使用此代理进行相关的操作. 前面在使用ServiceManager就是此种方式进行。

  实际上通信的基础是BinderProxy不过是在Binder上进行了一层封装,封装了对binder驱动的底层操作,使具有面向对象的特性。

任意两个进程通过Binder进行通信,就是先得到另一个进程的binder标识,通过此binder进行数据交换。

MediaPlayerService分析_第17张图片

1 新增加一个服务
看下面media Palyer类继承结构。
实现Bn端类继承结构

实现Bn端类继承结构:

MediaPlayerService分析_第18张图片

    


实现Bp端类继承结构:

    MediaPlayerService分析_第19张图片

 

可以看到

  •   需要定义服务公共接口IMediaPlayerService
  •   实现服务Bn 派发消息BnMediaPlayerService
  •   实现服务的命令处理MediaPlayerService
  •   实现服务代理BpMediaPlayerService

2 Client获取Service

Native Service以及framework Service都是加入到ServiceManger中,

不管native端还是Framework端得Service 其实都是要满足上面远程对象代理结构。

native端获取service

//获取ServiceManager的代理对象

sp sm = defaultServiceManager();

//通过ServiceManager获取media Service binder

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

//binder封装 构造media Service代理对象 BpMediaPlayerService

sMediaPlayerService = interface_cast(binder);

framework层的service,借助AIDL文件,实现跨进程的通信:

  所有frameworkservice想要作为公共的服务,被别的应用程序调用,都要实现AIDL文件,服务要继承该AIDL文件内部类Stub
其实AIDL文件是对Framework中service作为进程通信的框架的封装,系统自动生成中间需要的代码和步骤,统一结构:还是binder代理,服务代理。

MediaPlayerService分析_第20张图片

const sp service(getMediaPlayerService());

MediaPlayerService分析_第21张图片

sp sm = defaultServiceManager();   //handle0Bp ServiceManager

while循环中是去取MediaPlayerServiceBp端,但此时服务可能还没有起来,所以可能要等;

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

sMediaPlayerService = interface_cast(binder); //ServiceManager如此相似,其实就是建立了个包含binderIMediaPlayerService对象

其实就是创建了BpMediaPlayerService对象,后面调用它的create去创建Player

MediaPlayerService分析_第22张图片

你可能感兴趣的:(Android)