相信大家對(duì)上面這一副binder跨進(jìn)程通信的圖都應(yīng)該比較熟悉天吓,圖中的主要有4個(gè)角色:
1鲫凶、客戶端(A進(jìn)程)
2许布、SerivceManager
3、服務(wù)端(B進(jìn)程)
4箍铭、binder驅(qū)動(dòng)
平時(shí)一問到binder是怎么跨進(jìn)程通信的泊柬?那么同學(xué)們肯定大部分回答:binder最后調(diào)到底層還是通過binder驅(qū)動(dòng)來實(shí)現(xiàn)跨進(jìn)程通信的。那么這里就要問一下:請(qǐng)問android中app的java層binder調(diào)用诈火,是怎么一步步調(diào)用到了底層binder驅(qū)動(dòng)呢兽赁?
這個(gè)中間問號(hào)部分也就本節(jié)要給大家重點(diǎn)分享的部分。
1.ServiceManager方法調(diào)用也是binder跨進(jìn)程通信
跨進(jìn)程通信那么必然會(huì)出現(xiàn)有兩端冷守,即客戶端和服務(wù)端這樣的C/S模型刀崖,那么問題是C端怎么知道的S端?那么這就會(huì)引出一個(gè)重要的角色ServiceManager拍摇,ServiceManager本身工作相對(duì)簡(jiǎn)單亮钦,其功能:查詢和注冊(cè)服務(wù)〕浠睿客戶端通過ServiceManager查詢到了注冊(cè)服務(wù)后蜂莉,才可以進(jìn)行跨進(jìn)程通信,這里就是常說的ServiceManager像個(gè)DNS服務(wù)器混卵。但問題來了映穗,ServiceManager本身自己就是一個(gè)獨(dú)立進(jìn)程,那么客戶端去SerivceManager中查詢服務(wù)也肯定是跨進(jìn)程通信幕随,所以本節(jié)分析跨進(jìn)程通信時(shí)就拿ServiceManager.getService這個(gè)跨進(jìn)程調(diào)用來展開分析蚁滋。
2.ServiceManager接口獲取分析
平時(shí)系統(tǒng)中獲取某一個(gè)服務(wù),一般都是最后都是ServiceManager.getService這種方式合陵,來看看它的源碼:
//ServiceManager.java中
public static IBinder getService(String name) {
try {
//緩存中獲取枢赔,第一次緩存沒有
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
//Binder.allowBlocking僅僅是為了提示是否為阻塞行接口,沒有實(shí)際干活
return Binder.allowBlocking(getIServiceManager().getService(name));
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
這里大家可以看到實(shí)際真正干活的是getIServiceManager().getService(name)拥知,這里首先來看getIServiceManager()方法:
//ServiceManager.java中
private static IServiceManager getIServiceManager() {
//這里有一個(gè)sServiceManager來緩存踏拜,但是第一次肯定還為null
if (sServiceManager != null) {
return sServiceManager;
}
// 這里用調(diào)用了ServiceManagerNative類的asInterface方法和BinderInternal.getContextObject()方法
sServiceManager = ServiceManagerNative
.asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
return sServiceManager;
}
這里又調(diào)用到了ServiceManagerNative類的asInterface方法這方法本身應(yīng)該在應(yīng)用寫aidl生成的java文件中也經(jīng)常見到:
//ServiceManagerNative.java
static public IServiceManager asInterface(IBinder obj)
{
if (obj == null) {
return null;
}
IServiceManager in =
(IServiceManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
//其實(shí)就是 new ServiceManagerProxy代理對(duì)象,參數(shù)是IBinder 類型的對(duì)象
return new ServiceManagerProxy(obj);
}
它的核心就是new ServiceManagerProxy低剔,但是真正干活的還是IBinder參數(shù)速梗,參數(shù)getIServiceManager方法中可以看出獲取其實(shí)是核心是BinderInternal.getContextObject()方法,但getContextObject是個(gè)native的方法襟齿,所以就得看對(duì)應(yīng)的jni方法:
//android_util_Binder.cpp
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
//調(diào)用getContextObject構(gòu)造出一個(gè)IBinder類型對(duì)象
sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
//把C++層面的IBinder類型對(duì)象轉(zhuǎn)成java成的IBinder對(duì)象
return javaObjectForIBinder(env, b);
}
這里一共才2行代碼姻锁,那就一行行深入分析,首先來看ProcessState::self()->getContextObject:
//ProcessState.cpp
//這里直接就沒有使用傳遞來的參數(shù)猜欺,本身傳遞來的也是個(gè)NULL
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
return getStrongProxyForHandle(0);
}
ProcessState這里又調(diào)用了getStrongProxyForHandle方法位隶,而且傳遞了一個(gè)參數(shù)0:
//ProcessState.cpp
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;
AutoMutex _l(mLock);
//根據(jù)handle查詢handle_entry對(duì)象,handle沒有初始化過則構(gòu)造一個(gè)handle_entry空殼出來
handle_entry* e = lookupHandleLocked(handle);
//因?yàn)閔andle_entry已經(jīng)有了开皿,只不過是一個(gè)空殼里面內(nèi)容都為空
if (e != NULL) {
IBinder* b = e->binder;
//這里e->binder第一次肯定為空
if (b == NULL || !e->refs->attemptIncWeak(this)) {
//如果傳入handle為0
if (handle == 0) {
Parcel data;
//這里會(huì)調(diào)用 IPCThreadState::self()->transact方法來傳遞一個(gè)PING_TRANSACTION涧黄,主要目的
//是為了試探ServiceManager是否還存活
status_t status = IPCThreadState::self()->transact(
0, IBinder::PING_TRANSACTION, data, NULL, 0);
if (status == DEAD_OBJECT)
return NULL;
}
//利用handle值構(gòu)造出一個(gè)BpBinder對(duì)象顿肺,最后返回也是這個(gè)BpBinder對(duì)象
b = new BpBinder(handle);
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
} else {
result.force_set(b);
e->refs->decWeak(this);
}
}
return result;
}
到這里我們就看到了最后其實(shí)就是new BpBinder(handle);授滓,這里handle就是我們經(jīng)常說 “引用”,即對(duì)遠(yuǎn)程對(duì)象的引用,這里因?yàn)镾erviceManager的的特殊性闰围,所以android系統(tǒng)中默認(rèn)把任何進(jìn)程對(duì)ServiceManager的引用handle值都設(shè)置為固定的0帆卓。那么到這里就分析完了ProcessState::self()->getContextObject(NULL)了纫骑,返回的其實(shí)就是個(gè)new BpBinder(0)衙熔,但是這里還是C++層的BpBinder對(duì)象,而我們是要獲取Java層的IBinder類型的對(duì)象月帝,那接下來就要分析上面剩下的 javaObjectForIBinder(env, b):
//android_util_Binder.cpp
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{
//省略部分
//這里構(gòu)造出了gBinderProxyOffsets的java對(duì)象
object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
if (object != NULL) {
// The proxy holds a reference to the native object.
//這里吧val這個(gè)c++的對(duì)象指針設(shè)置到gBinderProxyOffsets.mObject這個(gè)java屬性中
env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
val->incStrong((void*)javaObjectForIBinder);
// The native object needs to hold a weak reference back to the
// proxy, so we can retrieve the same proxy if it is still active.
jobject refObject = env->NewGlobalRef(
env->GetObjectField(object, gBinderProxyOffsets.mSelf));
//前面只是基于val建立對(duì)應(yīng)的java對(duì)象躏惋,及java對(duì)象可以直接拿到val指針
//但是我們進(jìn)程也需要val指針可以獲取到j(luò)ava對(duì)象
val->attachObject(&gBinderProxyOffsets, refObject,
jnienv_to_javavm(env), proxy_cleanup);
//省略部分
}
return object;
}
這里面gBinderProxyOffsets相關(guān)的是什么呢?這里再來看它的對(duì)應(yīng)初始化代碼:
//android_util_Binder.cpp
const char* const kBinderProxyPathName = "android/os/BinderProxy";
static int int_register_android_os_BinderProxy(JNIEnv* env)
{
jclass clazz = FindClassOrDie(env, "java/lang/Error");
gErrorOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
//通過jni找出android/os/BinderProxy這個(gè)java類
clazz = FindClassOrDie(env, kBinderProxyPathName);
gBinderProxyOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
//通過jni找出android/os/BinderProxy這個(gè)java類的構(gòu)造方法
gBinderProxyOffsets.mConstructor = GetMethodIDOrDie(env, clazz, "<init>", "()V");
gBinderProxyOffsets.mSendDeathNotice = GetStaticMethodIDOrDie(env, clazz, "sendDeathNotice",
"(Landroid/os/IBinder$DeathRecipient;)V");
///通過jni找出android/os/BinderProxy這個(gè)java類的mObject 屬性
gBinderProxyOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");
//省略部分
}
這里面可以看出其實(shí)都是通過jni相關(guān)方法嫁赏,讓native的相關(guān)變量與java層的BinderProxy相綁定一起其掂,到這里就可以看出在BinderProxy是在native層面被構(gòu)造出來的,設(shè)置了它的mObject值就是c++層的BpBinder指針潦蝇,那么到這里就已經(jīng)分析完了開始的getIServiceManager方法款熬,這個(gè)時(shí)候就有了ServiceManager的Proxy代理,總結(jié)以下幾點(diǎn)核心部分:
1攘乒、ServiceManager特殊贤牛,它的handle固定為0,native層直接進(jìn)行new BpBinder(0)
2则酝、native層面的BpBinder需要轉(zhuǎn)換成Java層的BinderProxy殉簸,這個(gè)需要native通過jni構(gòu)造出java層對(duì)應(yīng)的BinderProxy,且BinderProxy的mObject值就是BpBinder(0)的指針沽讹,mObject也是Java層面與native層面進(jìn)行互通的最關(guān)鍵紐帶
3.getService獲取遠(yuǎn)程服務(wù)代理的源碼分析
首先來看ServiceManagerNative.java中的ServiceManagerProxy類中的getService
//ServiceManagerNative.java
public IBinder getService(String name) throws RemoteException {
//準(zhǔn)備輸入和返回Parcel對(duì)象
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeString(name);
//這里已經(jīng)知道m(xù)Remote其實(shí)就是前面分析構(gòu)造出來的BinderProxy對(duì)象
mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
//讀取返回的IBinder數(shù)據(jù)
IBinder binder = reply.readStrongBinder();
reply.recycle();
data.recycle();
return binder;
}
這里其實(shí)核心就是 mRemote.transact和 reply.readStrongBinder兩個(gè)部分般卑,這里先來分析transact部分,
這個(gè)mRemote對(duì)象是BinderProxy對(duì)象爽雄,所以來看BinderProxy類的transact方法蝠检,注意這里BinderProxy沒有單獨(dú)java文件,它在Binder.java文件中:
//Binder.java
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
//省略
try {
return transactNative(code, data, reply, flags);
} finally {
//省略
}
}
這里其實(shí)又是調(diào)用了一個(gè)native方法transactNative挚瘟,注意這里transactNative到android_os_BinderProxy_transact是有一個(gè)轉(zhuǎn)換關(guān)系的叹谁,這個(gè)在分析android系統(tǒng)源碼時(shí)候很常見:
//android_util_Binder.cpp
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{
//省略部分
//這里從BinderProxy類型的java對(duì)象中獲取mObject屬性,前面分析過它的值就是BpBinder對(duì)象指針
IBinder* target = (IBinder*)env->GetLongField(obj, gBinderProxyOffsets.mObject);
//省略部分
//調(diào)用BpBinder對(duì)象的transact方法
status_t err = target->transact(code, *data, reply, flags);
//省略部分
}
這里就可以看出前面講的mObject為啥是“重要紐帶”乘盖,那么接下來看看BpBinder的transact方法:
//BpBinder.cpp
status_t BpBinder::transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
if (mAlive) {
//本質(zhì)是調(diào)用了IPCThreadState的transact方法
status_t status = IPCThreadState::self()->transact(mHandle, code, data, reply, flags);
if (status == DEAD_OBJECT) mAlive = 0;
return status;
}
return DEAD_OBJECT;
}
那么接下來看看IPCThreadState的transact方法:
//IPCThreadState.cpp
status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{
//省略部分
if (err == NO_ERROR) {
//準(zhǔn)備好與驅(qū)動(dòng)通信的數(shù)據(jù)格式結(jié)構(gòu)體
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
}
//如果不是TF_ONE_WAY即oneway類型的調(diào)用
if ((flags & TF_ONE_WAY) == 0) {
if (reply) {
//這里需要等待答復(fù)
err = waitForResponse(reply);
} else {
Parcel fakeReply;
err = waitForResponse(&fakeReply);
}
} else {
//即oneway類型的調(diào)用
err = waitForResponse(NULL, NULL);
}
return err;
}
這里面分為兩個(gè)大塊writeTransactionData和waitForResponse焰檩,writeTransactionData主要目的就是把數(shù)據(jù)組裝成和驅(qū)動(dòng)一致的binder_transaction_data結(jié)構(gòu)體,然后在是waitForResponse:
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
uint32_t cmd;
int32_t err;
while (1) {
//與驅(qū)動(dòng)進(jìn)行通信订框,這里主要通過相關(guān)ioctl相關(guān)方法
if ((err=talkWithDriver()) < NO_ERROR) break;
if (mIn.dataAvail() == 0) continue;
//得到驅(qū)動(dòng)返回cmd
cmd = (uint32_t)mIn.readInt32();
switch (cmd) {
case BR_REPLY:
{
binder_transaction_data tr;
//得到驅(qū)動(dòng)返回?cái)?shù)據(jù)
err = mIn.read(&tr, sizeof(tr));
//省略部分
}
//省略部分
}
可以看出主要就是talkWithDriver與驅(qū)動(dòng)進(jìn)行通信并且一直等待返回驅(qū)動(dòng)相應(yīng)結(jié)果析苫,這里涉及驅(qū)動(dòng)部分就不給大家在這里講解,大家把驅(qū)動(dòng)暫時(shí)當(dāng)作黑盒既可以。
這個(gè)地方簡(jiǎn)單看看ServiceManager這個(gè)服務(wù)端衩侥,面對(duì)客戶端的getService做了什么呢浪腐?
在servicemanager代碼中如果接受到客戶端請(qǐng)求,最后都會(huì)調(diào)用到svcmgr_handler來負(fù)責(zé)處理:
int svcmgr_handler(struct binder_state *bs,
struct binder_transaction_data *txn,
struct binder_io *msg,
struct binder_io *reply)
{
struct svcinfo *si;
uint16_t *s;
size_t len;
uint32_t handle;
uint32_t strict_policy;
int allow_isolated;
//..省略部分
switch(txn->code) {
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE:
//根據(jù)獲取到service的name
s = bio_get_string16(msg, &len);
if (s == NULL) {
return -1;
}
//根據(jù)name從已經(jīng)存在集合中找出對(duì)應(yīng)的handle即索引
handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid);
if (!handle)
break;
//把handle獲取到了后寫入reply
bio_put_ref(reply, handle);
return 0;
//..省略部分
default:
ALOGE("unknown code %d\n", txn->code);
return -1;
}
bio_put_uint32(reply, 0);
return 0;
}
這里面根據(jù)name從集合中尋找出了服務(wù)的handle,注意這里只是找出了一個(gè)int類型的handle顿乒,然后在調(diào)用bio_put_ref進(jìn)行寫入reply,再通過binder驅(qū)動(dòng)傳遞給客戶端泽谨,這里看看bio_put_ref方法:
void bio_put_ref(struct binder_io *bio, uint32_t handle)
{
//構(gòu)造出一個(gè)binder結(jié)構(gòu)體
struct flat_binder_object *obj;
if (handle)
obj = bio_alloc_obj(bio);
else
obj = bio_alloc(bio, sizeof(*obj));
if (!obj)
return;
//給flat_binder_object 結(jié)構(gòu)體對(duì)應(yīng)屬性賦值
obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
//設(shè)置類型為BINDER_TYPE_HANDLE
obj->type = BINDER_TYPE_HANDLE;
//把handle賦值給flat_binder_object 的handle屬性
obj->handle = handle;
obj->cookie = 0;
}
這里大概我們就清除了原來servicemanager這一邊做的事情就是根據(jù)name查找到這個(gè)name對(duì)應(yīng)的handle,再把這個(gè)handle值包裝到flat_binder_object 結(jié)構(gòu)體中璧榄,再把結(jié)構(gòu)體傳遞到驅(qū)動(dòng),驅(qū)動(dòng)再傳遞到客戶端吧雹,具體傳遞過程就不在這一節(jié)詳細(xì)講述骨杂,分析這里相當(dāng)于客戶端調(diào)用transact方法后,服務(wù)端servicemanager的數(shù)據(jù)經(jīng)過binder驅(qū)動(dòng)進(jìn)行了返回雄卷。但是返回后的數(shù)據(jù)是怎么一步步又變成IBinder對(duì)象的呢搓蚪?這里我們接下來看 IBinder getService(String name)的 IBinder binder = reply.readStrongBinder()方法了,這里看著就是從Parcel類型的reply中調(diào)用了readStrongBinder方法就返回了IBinder對(duì)象丁鹉。注意啦Parcel這里是java層的妒潭,但是最后調(diào)用它又會(huì)調(diào)用到Parcel.cpp中,先看Parcel.java:
//Parcel.java
public final IBinder readStrongBinder() {
return nativeReadStrongBinder(mNativePtr);
}
這里其實(shí)就只調(diào)用了nativeReadStrongBinder方法揣钦,它又是一個(gè)jni方法雳灾,所以這個(gè)方法后就會(huì)調(diào)用到native層,具體看一下這個(gè)方法在native層映射成了哪個(gè)方法:
//android_os_Parcel.cpp
{"nativeReadStrongBinder", "(J)Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder},
這里被映射成了android_os_Parcel_readStrongBinder方法:
//android_os_Parcel.cpp
static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) {
return javaObjectForIBinder(env, parcel->readStrongBinder());
}
return NULL;
}
這里又會(huì)先調(diào)用parcel->readStrongBinder()獲取native層的BpBinder對(duì)象作為參數(shù)冯凹,然后再調(diào)用javaObjectForIBinder轉(zhuǎn)為java對(duì)象谎亩,這個(gè)前面已經(jīng)講過了哦。
//Parcel.cpp
sp<IBinder> Parcel::readStrongBinder() const
{
sp<IBinder> val;
//這里又調(diào)用了readNullableStrongBinder
readNullableStrongBinder(&val);
return val;
}
接下來看看readNullableStrongBinder:
status_t Parcel::readNullableStrongBinder(sp<IBinder>* val) const
{
return unflatten_binder(ProcessState::self(), *this, val);
}
這里又調(diào)用到了unflatten_binder:
status_t unflatten_binder(const sp<ProcessState>& proc,
const Parcel& in, sp<IBinder>* out)
{
const flat_binder_object* flat = in.readObject(false);
if (flat) {
switch (flat->type) {
case BINDER_TYPE_BINDER:
*out = reinterpret_cast<IBinder*>(flat->cookie);
return finish_unflatten_binder(NULL, *flat, in);
case BINDER_TYPE_HANDLE:
//這里核心又是獲取了handle后調(diào)用getStrongProxyForHandle
*out = proc->getStrongProxyForHandle(flat->handle);
return finish_unflatten_binder(
static_cast<BpBinder*>(out->get()), *flat, in);
}
}
return BAD_TYPE;
}
這里我們前面分析servicemanager時(shí)候就知道type類型為BINDER_TYPE_HANDLE宇姚,所以根據(jù)flat->handle的handle值調(diào)用getStrongProxyForHandle匈庭,這個(gè)getStrongProxyForHandle方法前面已經(jīng)分析過他就是new BpBinder(handle),所以這里就明白了這個(gè)getService方法最后也是根據(jù)servicemanager返回的handle(這里大家要注意這個(gè)客戶端的handle值和servicemanager中寫入的handle值不一定相等浑劳,而是各種進(jìn)程獨(dú)立阱持,但是在binder驅(qū)動(dòng)可以關(guān)聯(lián)上,具體區(qū)別會(huì)binder驅(qū)動(dòng)中進(jìn)行剖析)呀洲。
getService部分的總結(jié):
1紊选、獲取遠(yuǎn)端Serivce整體依然是new BpBinder(handle) --> javaObjectForIBinder變成BinderProxy的過程
2、但這里的handle不再像ServiceManager那么簡(jiǎn)單的直接寫死為0道逗,而是需要把name傳遞到SeriveManager查詢對(duì)應(yīng)的服務(wù)兵罢,ServiceManager把對(duì)應(yīng)服務(wù)flat_binder_object對(duì)象通過binder驅(qū)動(dòng)傳遞到客戶端,客戶端再?gòu)膄lat_binder_object獲取handle
至此我們就分析完了客戶端發(fā)起一個(gè)調(diào)用到獲取驅(qū)動(dòng)數(shù)據(jù)返回的整個(gè)過程滓窍,那么接下要分析的是作為一個(gè)服務(wù)端即Binder實(shí)現(xiàn)端卖词。