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 Service(AudioFlinger MediaPlayerService CameraService AudioPolicyService等),整个Android(native或者framework)的Service都需要加入servicemanager中进行统一管理。
那么Media Process 与ServiceManager Process是如何进行通信的呢——Binder.通过Media Process中使用binder进行完成IPC过程,学习Binder的概念和使用方法。
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
\frameworks\av\media\mediaserver\ main_mediaserver.cpp:
当前进程的状态属性,对象创建:
sp
{
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) {
//将binder的fd映射到当前进程虚拟空间地址中 与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映射到当前进程虚拟地址空间建立交互的通道;
class IServiceManager : public IInterface
{
virtual sp
virtual status_t addService( const String16& name,
const sp
bool allowIsolated = false) = 0;
……
};
通过IServiceManager派生对象操作将Service加入到ServiceManager中.
defaultServiceManager()函数:
ProcessState::self()->getContextObject(NULL):得到一个IBinder对象
ProcessState::self()刚才所创建的ProcessState对象。
handle_entry是什么呢?
struct handle_entry {
IBinder* binder;
RefBase::weakref_type* refs;
};
也就是说ProcessState 有一个表Vector
表里面的每一项存储了一个binder,每一个binder对应一个handle。
Handle = 0是什么,句柄? 代表谁的句柄——ServiceManager在binder中的资源。
从ProcessState::self()->getContextObject(NULL)得到一个 IBinder——BpBinder(0);
于是得到:
gDefaultServiceManager = interface_cast
使用interface_cast将IBinder实例转化成IServiceManager实例。
翻译为:
inline sp
{
return IServiceManager::asInterface(obj);
}
替换成IServiceManager:
android::sp
const android::sp
{
//obj BpBinder实例
android::sp
if (obj != NULL) {
//返回NULL
intr = static_cast
obj->queryLocalInterface(
IServiceManager::descriptor).get());
if (intr == NULL) {
intr = new BpServiceManager(obj);
}
}
return intr;
}
这里得到IServiceManager 实例:
BpServiceManager:new BpServiceManager(new BpBinder(0));
关注BpServiceManager继承于模板类BpInterface
BpInterface构造函数:
BpRefBase构造函数:
gDefaultServiceManager = interface_cast
实际为:
gDefaultServiceManager = new BpServiceManager(new BpBinder(0));
Bn代表Binder Native Bp代表Binder Proxy
BpServiceManager代理的BpBinder实例 BpBinder代理的handle(0)
这个关系有些复杂,看一下类继承结构图:
上面这个结构看起来感觉很熟悉——Bridge模式。将Binder数据交互和功能处理桥接起来。
在Media Process 的main函数中通过:
sp
我们得到了sm:是BpServiceManager对象。
回到main函数中:
MediaPlayerService::instantiate();
BpServiceManager添加Service:
virtual status_t addService(const String16& name, const sp
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中,
这里就通过BpServiceManager的AddService将数据写入到Binder设备传递给ServiceManager。
继续Media Process过程
int main(int argc, char** argv)
{
//启动进程的线程池
ProcessState::self()->startThreadPool(); //走到了这里
//执行线程消息循环
IPCThreadState::self()->joinThreadPool();
}
void ProcessState::startThreadPool()
{
spawnPooledThread(true);
}
void ProcessState::spawnPooledThread(bool isMain)
{
//创建PoolThread对象 并run ,非线程
sp
t->run(buf);
}
PoolThread继承Thread
执行Thread的run函数:
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
do {
//调用子类的threadLoop
result = self->threadLoop();
……
} while(strong != 0);
return 0;
}
class PoolThread : public Thread
{
protected:
virtual bool threadLoop()
{
IPCThreadState::self()->joinThreadPool(mIsMain);
return false;
}
};
消息循环:
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
//调用BBinder的transact 函数
const status_t error = b->transact(tr.code, buffer, &reply, tr.flags);
}
break;
……
default:
}
return result;
}
binder_transaction_data.cookie:target object cookie目标对象,这个target object是指那个呢?
在Media Process里面有几个Service:AudioFlinger、MediaPlayerService、CameraService等。
这个目标是这其中Service中的一个,假设目标对象为为MediaPlayerService,那为何要转化成BBinder呢?
线程从binder接收到消息命令,将命令传递给Service处理。将目标对象转化成BBinder,然后调度此命令;
命令从远端传递到本地端进行处理,每个Service都对应BnXXX对象来处理远端BpXXX传来的命令。
sp
const status_t error = b->transact(tr.code, buffer, &reply, tr.flags);
这里b代表某个Service:假设为MediaPlayerService;弄清楚执行过程,要弄清楚类继承关系。
本地端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
interface_cast
//create是个virtual函数 派生类MediaPlayerService重写
sp
//创建player写入到数据包中 传回
reply->writeStrongBinder(player->asBinder());
return NO_ERROR;
} break;
……
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
可以看看Client类继承关系结构图:
看到这个跟上面的MediaPlayerService继承关系非常的相似,
这个结构也非常的熟悉——Adapter模式;将binder消息交互和命令处理适配到一起。
Client对Service进行使用Binder通信,是得到一个Service BnXXX端对象的代理,在Client 为BpXXX代理,
然后使用此代理进行相关的操作. 前面在使用ServiceManager就是此种方式进行。
实际上通信的基础是Binder,Proxy不过是在Binder上进行了一层封装,封装了对binder驱动的底层操作,使具有面向对象的特性。
任意两个进程通过Binder进行通信,就是先得到另一个进程的binder标识,通过此binder进行数据交换。
实现Bn端类继承结构:
实现Bp端类继承结构:
可以看到 :
Native Service以及framework Service都是加入到ServiceManger中,
不管native端还是Framework端得Service 其实都是要满足上面远程对象代理结构。
native端获取service:
//获取ServiceManager的代理对象
sp
//通过ServiceManager获取media Service binder
binder = sm->getService(String16("media.player"));
//将binder封装 构造media Service代理对象 BpMediaPlayerService
sMediaPlayerService = interface_cast
framework层的service,借助AIDL文件,实现跨进程的通信:
所有framework端service想要作为公共的服务,被别的应用程序调用,都要实现AIDL文件,服务要继承该AIDL文件内部类Stub。
其实AIDL文件是对Framework中service作为进程通信的框架的封装,系统自动生成中间需要的代码和步骤,统一结构:还是binder代理,服务代理。
const sp
sp
while循环中是去取MediaPlayerService的Bp端,但此时服务可能还没有起来,所以可能要等;
binder = sm->getService(String16("media.player"));
sMediaPlayerService = interface_cast
其实就是创建了BpMediaPlayerService对象,后面调用它的create去创建Player