雖說閱讀Binder的源代碼是學習Binder機制的最好的方式,但是也絕不能打無準備之仗,因爲Binder的相關源代碼是比較枯燥無味而且比較難以理解的,如果能夠輔予一些理論知識,那就更好了。閒話少說,網上關於Binder機制的資料還是不少的,這裏就不想再詳細寫一遍了,強烈推薦下面兩篇文章:
Android Binder設計與實現 – 設計篇
void MediaPlayerService::instantiate() {
266 defaultServiceManager()->addService(
267 String16("media.player"), new MediaPlayerService());
268}
defaultServiceManager = BpServiceManager
class MediaPlayerService : public BnMediaPlayerService
Bn Binder Native層
Bp Binder Proxy 代理
BpServiceManager BnServiceManager BnMediaPlayerService BpMediaPlayerService來和他交互呢
p<IServiceManager> defaultServiceManager()
{
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
return getStrongProxyForHandle(0);
}
b = new BpBinder(handle);
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
DECLARE_META_INTERFACE(ServiceManager);
#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(); \
怎麼和MFC這麼類似?微軟的影響很大啊!知道MFC的,有DELCARE肯定有IMPLEMENT
class BpServiceManager : public BpInterface<IServiceManager>
{
public:
BpServiceManager(const sp<IBinder>& impl)
: BpInterface<IServiceManager>(impl)
{
}
addService Parcel writeInterfaceToken ADD_SERVICE_TRANSACTION
remote transact
class BpRefBase : public virtual RefBase
{
inline IBinder* remote() { return mRemote; }
BpBinder::BpBinder(int32_t handle)
class BpServiceManager : public BpInterface<IServiceManager>
{
public:
BpServiceManager(const sp<IBinder>& impl)
: BpInterface<IServiceManager>(impl)
{
}
inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)
: BpRefBase(remote)
{
}
BpRefBase::BpRefBase(const sp<IBinder>& o)
: mRemote(o.get()), mRefs(NULL), mState(0)
{
virtual status_t addService(const String16& name, const sp<IBinder>& service,
bool allowIsolated)
{
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
data.writeStrongBinder(service);
data.writeInt32(allowIsolated ? 1 : 0);
status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
return err == NO_ERROR ? reply.readExceptionCode() : err;
}
BpBinder轉換爲 IServiceManager :BpRefBase
status_t BpBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
//又繞回去了,調用IPCThreadState的transact。
//注意啊,這裏的mHandle爲0,code是ADD_SERVICE_TRANSACTION,data是命令包
//reply是回覆包,flags=0
status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{
err = waitForResponse(reply);
status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
{
binder_transaction_data tr;
tr.data.ptr.buffer = reinterpret_cast<uintptr_t>(statusBuffer);
reinterpret_cast<uintptr_t>(statusBuffer)
上面把命令數據封裝成binder_transaction_data,然後
寫到mOut中,mOut是命令的緩衝區,也是一個Parcel
mOut.writeInt32(cmd);
mOut.write(&tr, sizeof(tr));
//僅僅寫到了Parcel中,Parcel好像沒和/dev/binder設備有什麼關聯啊?
恩,那隻能在另外一個地方寫到binder設備中去了。難道是在?
return NO_ERROR;
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
//看見沒?這裏開始操作mIn了,看來talkWithDriver中
//把mOut發出去,然後從driver中讀到數據放到mIn中了。
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
binder_write_read bwr;
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
好了,到這裏,我們發送addService的流程就徹底走完了。
BpServiceManager發送了一個addService命令到BnServiceManager,然後收到回覆。
int main(int argc __unused, char** argv)
{
sp<ProcessState> proc(ProcessState::self());
MediaLogService::instantiate();
ProcessState::self()->startThreadPool();
一個調用的函數是ProcessState::self(),然後賦值給了proc變量,程序運行完,proc會自動delete內部的內容,所以就自動釋放了先前分配的資源。
bs = binder_open(128*1024);
bs->fd = open("/dev/binder", O_RDWR);
bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);//映射內存
if (binder_become_context_manager(bs)) {
ALOGE("cannot become context manager (%s)\n", strerror(errno));
return -1;
}
int binder_become_context_manager(struct binder_state *bs)
{
return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}
binder_loop(bs, svcmgr_handler);
void binder_loop(struct binder_state *bs, binder_handler func)
{
struct binder_write_read bwr; binder_write(bs, readbuf, sizeof(uint32_t));
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
if (res < 0) {
ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
break;
}
res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
int binder_parse(struct binder_state *bs, struct binder_io *bio,
uintptr_t ptr, size_t size, binder_handler func)
{
恩,最後有一個類似handleMessage的地方處理各種各樣的命令。這個就是
svcmgr_handler,就在ServiceManager.c中
int svcmgr_handler(struct binder_state *bs,
struct binder_transaction_data *txn,
struct binder_io *msg,
struct binder_io *reply)
{
struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
if (func) {
if (do_add_service(bs, s, len, handle, txn->sender_euid,
allow_isolated, txn->sender_pid))
int do_add_service(struct binder_state *bs,
const uint16_t *s, size_t len,
uint32_t handle, uid_t uid, int allow_isolated,
pid_t spid)
//si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t))
// memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
memcpy(si-name,s, (len + 1) * sizeof(uint16_t))
//si->next = svclist;
//svclist = si;
si->next = svclist
svclist = si;
喔,對於addService來說,看來ServiceManager把信息加入到自己維護的一個服務列表中了。
ServiceManager存在的意義
Android系統中Service信息都是先add到ServiceManager中,由ServiceManager來集中管理,這樣就可以查詢當前系統有哪些服務。而且,Android系統中某個服務例如MediaPlayerService的客戶端想要和MediaPlayerService通訊的話,必須先向ServiceManager查詢MediaPlayerService的信息,然後通過ServiceManager返回的東西再來和MediaPlayerService交互。
畢竟,要是MediaPlayerService身體不好,老是掛掉的話,客戶的代碼就麻煩了,就不知道後續新生的MediaPlayerService的信息了,所以只能這樣:
另外,ServiceManager的handle標示是0,所以只要往handle是0的服務發送消息了,最終都會被傳遞到ServiceManager中去
virtual status_t addService(const String16& name, const sp<IBinder>& service,
bool allowIsolated)
{
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
data.writeStrongBinder(service);
data.writeInt32(allowIsolated ? 1 : 0);
status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
return err == NO_ERROR ? reply.readExceptionCode() : err;
}
defaultServiceManager()->addService(
String16("media.player"), new MediaPlayerService());
class MediaPlayerService : public BnMediaPlayerService
{
class BnMediaPlayerService: public BnInterface<IMediaPlayerService>
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
template<typename INTERFACE>
class BnInterface : public INTERFACE, public BBinder
{
兌現後變成
class BnInterface : public IMediaPlayerService, public BBinder
class PoolThread : public Thread
{
t->run(name.string());
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
void IPCThreadState::joinThreadPool(bool isMain)
{
./work/android-5.0.2/external/lldb/source/Target/Thread.cpp