一 Media Service程序啟動
Init.rc中描述的service對應linux 的程序:
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的概念和使用方法。
\frameworks\av\media\mediaserver\ main_mediaserver.cpp:
int main(int argc, char** argv)
{
//建立ProcessState 目前程序屬性
sp<ProcessState> proc(ProcessState::self());
//IServiceManager對象
sp<IServiceManager> sm = defaultServiceManager();
//初始化MediaPlayerService服務對象
MediaPlayerService::instantiate();
……
//啟動程序的線程池
ProcessState::self()->startThreadPool();
//執行線程消息循環
IPCThreadState::self()->joinThreadPool();
}
Sp:指針運算符和普通運算符的重載 StrongPointer。
二 Media Process執行過程
1 ProcessState對象建立
目前程序的狀态屬性,對象建立:
sp<ProcessState> 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) {
//将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映射到目前程序虛拟位址空間建立互動的通道;
2 IServiceManager對象建立
sp<IServiceManager> sm = defaultServiceManager();
為什麼需要一個IServiceManager對象呢,這個類是個抽象提供接口
class IServiceManager : public IInterface
{
virtual sp<IBinder> getService( const String16& name) const = 0;
virtual status_t addService( const String16& name,
const sp<IBinder>& service,
bool allowIsolated = false) = 0;
……
};
通過IServiceManager派生對象操作将Service加入到ServiceManager中.
defaultServiceManager()函數:
sp<IServiceManager> defaultServiceManager()
{
//單例對象
if (gDefaultServiceManager != NULL)
return gDefaultServiceManager;
AutoMutex _l(gDefaultServiceManagerLock);
if (gDefaultServiceManager == NULL) {
//建立對象
gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(NULL));
}
return gDefaultServiceManager;
}
ProcessState::self()->getContextObject(NULL):得到一個IBinder對象
ProcessState::self()剛才所建立的ProcessState對象。
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)
{
return getStrongProxyForHandle(0);
}
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;
AutoMutex _l(mLock);
//從表中查詢一個handle對應的handle_entry
//若沒有則建立一個 handle == 0
handle_entry* e = lookupHandleLocked(handle);
if (e != NULL) {
IBinder* b = e->binder;
if (b == NULL || !e->refs->attemptIncWeak(this)) {
//handle_entry對象成員初始化 建立handle=0的BpBinder
b = new BpBinder(handle);
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
}
}
return result;
}
handle_entry是什麼呢?
struct handle_entry {
IBinder* binder;
RefBase::weakref_type* refs;
};
也就是說ProcessState 有一個表Vector<handle_entry>mHandleToObject;
表裡面的每一項存儲了一個binder,每一個binder對應一個handle。
Handle = 0是什麼,句柄? 代表誰的句柄——ServiceManager在binder中的資源。
從ProcessState::self()->getContextObject(NULL)得到一個 IBinder——BpBinder(0);
于是得到:
gDefaultServiceManager = interface_cast<IServiceManager>(BpBinder(0));
使用interface_cast将IBinder執行個體轉化成IServiceManager執行個體。
3 interface_cast函數
\frameworks\native\include\binder\IInterface.h:
interface_cast是個内聯模闆函數:
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
結合前面就是:
inline sp<IServiceManager> interface_cast(const sp<IBinder>& obj)
{
return IServiceManager::asInterface(obj);
}
是以需要到IServiceManager裡面去看看是如何實作的
4 IServiceManager類
\frameworks\native\include\binder\IServiceManager.h:
IServiceManager是一個抽象類:
class IServiceManager : public IInterface
{
public:
//宏聲明
DECLARE_META_INTERFACE(ServiceManager);
virtual sp<IBinder> getService( const String16& name) const = 0;
virtual status_t addService( const String16& name,
const sp<IBinder>& service,
bool allowIsolated = false) = 0;
……
}
DECLARE_META_INTERFACE聲明:
#define DECLARE_META_INTERFACE(INTERFACE) \
static const android::String16 descriptor; \
static android::sp<I##INTERFACE> asInterface( \
const android::sp<android::IBinder>& obj); \
virtual const android::String16& getInterfaceDescriptor() const; \
I##INTERFACE(); \
virtual ~I##INTERFACE(); \
替換成IServiceManager:
//實作時傳入:android.os.IServiceManager
static const android::String16 descriptor;
static android::sp<IServiceManager> asInterface(
const android::sp<android::IBinder>& obj);
virtual const android::String16& getInterfaceDescriptor() const;
//構造析構函數
IServiceManager();
virtual ~IServiceManager();
實作\frameworks\native\include\binder\IServiceManager.cpp:
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
IMPLEMENT_META_INTERFACE實作:
看一下asInterface接口:
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
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; \
} \
替換成IServiceManager:
android::sp<IServiceManager> IServiceManager::asInterface(
const android::sp<android::IBinder>& obj)
{
//obj BpBinder執行個體
android::sp<IServiceManager> intr;
if (obj != NULL) {
//傳回NULL
intr = static_cast<IServiceManager*>(
obj->queryLocalInterface(
IServiceManager::descriptor).get());
if (intr == NULL) {
intr = new BpServiceManager(obj);
}
}
return intr;
}
這裡得到IServiceManager 執行個體:
BpServiceManager:new BpServiceManager(new BpBinder(0));
5 BpServiceManager 和 BpInterface類
\frameworks\native\libs\binder\ IServiceManager.cpp:BpServiceManager
class BpServiceManager : public BpInterface<IServiceManager>
{
public:
//impl就是 new BpBinder(0)
BpServiceManager(const sp<IBinder>& impl)
: BpInterface<IServiceManager>(impl)
{
}
virtual sp<IBinder> checkService(const String16& name) const
{
……
remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
}
virtual status_t addService(const String16& name, const sp<IBinder>& service,
bool allowIsolated)
{
……
remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
}
}
\frameworks\native\include\binder\ IInterface.h:模闆類BpInterface
template<typename INTERFACE>
class BpInterface : public INTERFACE, public BpRefBase // INTERFACE IServiceManager
{
public:
BpInterface(const sp<IBinder>& remote);
protected:
virtual IBinder* onAsBinder();
};
BpInterface構造函數:
template<typename INTERFACE>
inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)
: BpRefBase(remote)
{
}
BpRefBase構造函數:
BpRefBase::BpRefBase(const sp<IBinder>& o)
: mRemote(o.get()), mRefs(NULL), mState(0)
{
// IBinder mRemote 指向 o.get() :new BpBinder(0)
}
gDefaultServiceManager = interface_cast<IServiceManager>(BpBinder(0));
實際為:
gDefaultServiceManager = new BpServiceManager(new BpBinder(0));
Bn代表Binder Native Bp代表Binder Proxy
BpServiceManager代理的BpBinder執行個體 BpBinder代理的handle(0)
這個關系有些複雜,看一下類繼承結構圖:
上面這個結構看起來感覺很熟悉——Bridge模式。将Binder資料互動和功能處理橋接起來。
在Media Process 的main函數中通過:
sp<IServiceManager> sm = defaultServiceManager();
我們得到了sm:是BpServiceManager對象。
三 MediaPlayerService加入到ServiceManager中
回到main函數中:
int main(int argc, char** argv)
{
//建立ProcessState 目前程序屬性
sp<ProcessState> proc(ProcessState::self());
//IServiceManager對象
sp<IServiceManager> sm = defaultServiceManager();
//初始化MediaPlayerService服務對象
MediaPlayerService::instantiate(); //執行到這裡
……
//啟動程序的線程池
ProcessState::self()->startThreadPool();
//執行線程消息循環
IPCThreadState::self()->joinThreadPool();
}
1 MediaPlayerService初始化過程
void MediaPlayerService::instantiate() {
// defaultServiceManager就是上面所述得到的BpServiceManager對象
defaultServiceManager()->addService(
String16("media.player"), new MediaPlayerService());
}
BpServiceManager添加Service:
virtual status_t addService(const String16& name, const sp<IBinder>& 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;
}
2 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過程
四 Media Process消息循環
int main(int argc, char** argv)
{
//啟動程序的線程池
ProcessState::self()->startThreadPool(); //走到了這裡
//執行線程消息循環
IPCThreadState::self()->joinThreadPool();
}
1 建立工作者線程
startThreadPool:\frameworks\native\libs\binder\ ProcessState.cpp:
void ProcessState::startThreadPool()
{
spawnPooledThread(true);
}
void ProcessState::spawnPooledThread(bool isMain)
{
//建立PoolThread對象 并run ,非線程
sp<Thread> t = new PoolThread(isMain);
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<Thread*>(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<BBinder> b((BBinder*)tr.cookie);
//調用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呢?
3 Service對指令的處理
線程從binder接收到消息指令,将指令傳遞給Service處理。将目标對象轉化成BBinder,然後排程此指令;
指令從遠端傳遞到本地端進行處理,每個Service都對應BnXXX對象來處理遠端BpXXX傳來的指令。
sp<BBinder> b((BBinder*)tr.cookie);
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<IMediaPlayerClient> client =
interface_cast<IMediaPlayerClient>(data.readStrongBinder());
//create是個virtual函數 派生類MediaPlayerService重寫
sp<IMediaPlayer> player = create(pid, client, audioSessionId);
//建立player寫入到資料包中 傳回
reply->writeStrongBinder(player->asBinder());
return NO_ERROR;
} break;
……
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
可以看看Client類繼承關系結構圖:
看到這個跟上面的MediaPlayerService繼承關系非常的相似,
這個結構也非常的熟悉——Adapter模式;将binder消息互動和指令處理适配到一起。
五 Client端與Service端互動
Client對Service進行使用Binder通信,是得到一個Service BnXXX端對象的代理,在Client 為BpXXX代理,
然後使用此代理進行相關的操作. 前面在使用ServiceManager就是此種方式進行。
實際上通信的基礎是Binder,Proxy不過是在Binder上進行了一層封裝,封裝了對binder驅動的底層操作,使具有面向對象的特性。
任意兩個程序通過Binder進行通信,就是先得到另一個程序的binder辨別,通過此binder進行資料交換。
1 新增加一個服務
看下面media Palyer類繼承結構。
實作Bn端類繼承結構:
實作Bp端類繼承結構:
可以看到 :
- 需要定義服務公共接口IMediaPlayerService;
- 實作服務Bn端 派發消息BnMediaPlayerService;
- 實作服務的指令處理MediaPlayerService;
- 實作服務代理BpMediaPlayerService;
2 Client擷取Service服務
Native Service以及framework Service都是加入到ServiceManger中,
不管native端還是Framework端得Service 其實都是要滿足上面遠端對象代理結構。
native端擷取service:
//擷取ServiceManager的代理對象
sp<IServiceManager> sm = defaultServiceManager();
//通過ServiceManager擷取media Service binder
binder = sm->getService(String16("media.player"));
//将binder封裝 構造media Service代理對象 BpMediaPlayerService
sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);
framework層的service,借助AIDL檔案,實作跨程序的通信:
所有framework端service想要作為公共的服務,被别的應用程式調用,都要實作AIDL檔案,服務要繼承該AIDL檔案内部類Stub。
其實AIDL檔案是對Framework中service作為程序通信的架構的封裝,系統自動生成中間需要的代碼和步驟,統一結構:還是binder代理,服務代理。
下面看看PowerManagerService實作。
PowerManagerService服務:
\frameworks\base\services\java\com\android\server\PowerManagerService.java
public class PowerManagerService extends IPowerManager.Stub……
{
public void goToSleep(long time){
……
}
};
AIDL檔案:\frameworks\base\core\java\android\os\IPowerManager.aidl
interface IPowerManager
{
void goToSleep(long time);
……
}
AIDL對應的Java檔案:
AIDL會自動生成一個對應的Java的interface檔案,看看這個接口檔案。
AIDL自動生成對應java檔案位置:\out\target\common\obj\JAVA_LIBRARIES\framework_intermediates\src\core\java\android\os
public interface IPowerManager extends android.os.IInterface {
//IPowerManager 内部類 Stub
public static abstract class Stub extends android.os.Binder implements
android.os.IPowerManager {
public static android.os.IPowerManager asInterface(
android.os.IBinder obj)
{
//生成一個Proxy對象
return new android.os.IPowerManager.Stub.Proxy(obj);
}
public android.os.IBinder asBinder() {
return this;
}
@Override
public boolean onTransact(int code, android.os.Parcel data,
android.os.Parcel reply, int flags)
{
switch (code) {
case TRANSACTION_goToSleep:
this.goToSleep(_arg0);
return true;
……
}
}
//Stub内部類Proxy
private static class Proxy implements android.os.IPowerManager {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
public void goToSleep(long time)
{
//将資料打包成Parcel
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeLong(time);
//傳輸資料到binder 到相關的Service 程序
// IPCThreadState::transact方法中完成
mRemote.transact(Stub.TRANSACTION_goToSleep, _data, _reply,0);
_reply.readException();
}
}
}
//goToSleep接口對應的ID
static final int TRANSACTION_goToSleep = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
//接口
public void goToSleep(long time);
}
看下其中類結構:
AIDL自動生成對應的java檔案,将結構過程進行了統一,自動生成中間代碼。
Application擷取用Service:
IPowerManager m mPowerManagerService;
//擷取service的bingder
IBinder binder = ServiceManager.getService("power");
//建立service代理對象
mPowerManagerService = IPowerManager.Stub.asInterface(binder);
//調用接口
mPowerManagerService.goToSleep();
Native Service和 Framework Service結構方式基本一緻的。
程序間通信Linux系統已經提供了很多方式,比如Socket,為什麼Android非要另辟蹊徑,設計了Binder呢?
可以閱讀一下:http://www.cnblogs.com/bastard/archive/2012/10/17/2728155.html
Game Over !
參考文檔:
http://www.cnblogs.com/innost/archive/2011/01/09/1931456.html
http://blog.csdn.net/maxleng/article/details/5490770
注:
“我們其實還一部分沒有研究,就是同一個程序之間的對象傳遞與遠端傳遞是差別的。同一個程序間專遞服務地和對象,
就沒有代理BpBinder産生,而隻是對象的直接應用了。應用程式并不知道資料是在同一程序間傳遞還是不同程序間傳遞,
這個隻有核心中的Binder知道,是以核心Binder驅動可以将Binder對象資料類型從BINDER_TYPE_BINDER修改為
BINDER_TYPE_HANDLE或者BINDER_TYPE_WEAK_HANDLE作為引用傳遞。” ——來自上述位址
這個可以看到在SystemServer運作的Service之間使用時,直接轉化成了對應的對象,而不是通過代理。