java層 native層_Java層的ServiceManager和Native層的ServiceManager的對應過程

轉自:https://blog.csdn.net/moonshine2016/article/details/54378358

參考:https://www.jianshu.com/p/9c023701c261

幾天前一個同事問Java層的Binder和Java層的ServiceManager和C++層的ServiceManager是如何對應起來的,竟然一時語噻,一段時間不關注就會感到陌生啊,現在再總結一下,只寫Java層的,C++層的不寫,C++ Binder的知識需掌握,java和native的基本概念及對應關係不講。

Java層Binder的初始化過程

Binder最終是要和它的驅動打交道,Java層要調Linux內核層的東西必然要透過native方法,而對於android的系統服務,native和java的對應,總會有一個註冊過程,先看這個註冊是在哪實現的

JNI Binder的註冊

Zygote在啟動時:

app_main.cpp

int main(int argc, char* const argv[])

{

......

AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));

......

if (zygote) {

runtime.start("com.android.internal.os.ZygoteInit", args, zygote);

}

......

}

AppRuntime是AndroidRuntime的子類別,它本身沒有覆蓋start方法,所以要去看AndroidRuntime類中的start方法

void AndroidRuntime::start(const char* className, const Vector& options, bool zygote)

{

......

/*

* Register android functions.

*/

if (startReg(env) < 0) {

ALOGE("Unable to register all android natives
");

return;

}

......

}

/*

* Register android native functions with the VM.

*/

/*static*/ int AndroidRuntime::startReg(JNIEnv* env)

{

......

if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {

env->PopLocalFrame(NULL);

return -1;

}

......

}

gRegJNI是個陣列:

static const RegJNIRec gRegJNI[] = {

......

REG_JNI(register_android_os_Binder),

......

};

REG_JNI是一個巨集定義

#ifdef NDEBUG

#define REG_JNI(name) { name }

struct RegJNIRec {

int (*mProc)(JNIEnv*);

};

#else

#define REG_JNI(name) { name, #name }

struct RegJNIRec {

int (*mProc)(JNIEnv*);

const char* mName;

};

#endif

gRegJNI是一個RegJNIRec的陣列,所以gRegJNI的定義就變成了這樣:

static const RegJNIRec gRegJNI[] = {

......

{ register_android_os_Binder },

......

};

register_jni_procs函式如下:

static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)

{

for (size_t i = 0; i < count; i++) {

if (array[i].mProc(env) < 0) {

#ifndef NDEBUG

ALOGD("----------!!! %s failed to load
", array[i].mName);

#endif

return -1;

}

}

return 0;

}

就是迴圈呼叫gRegJNI陣列中的函式,這時register_android_os_Binder(env)就被呼叫了。

register_android_os_Binder在AndroidRuntime.cpp中被宣告為extern:

extern int register_android_os_Binder(JNIEnv* env);

1

實現它的地方是在android_util_Binder.cpp中:

int register_android_os_Binder(JNIEnv* env)

{

if (int_register_android_os_Binder(env) < 0)

return -1;

if (int_register_android_os_BinderInternal(env) < 0)

return -1;

if (int_register_android_os_BinderProxy(env) < 0)

return -1;

......

return 0;

}

從名字上看,它要關聯3個Java的類,分別是Binder, BinderInternal和BinderProxy,一個一個看來:

const char* const kBinderPathName = "android/os/Binder";

static int int_register_android_os_Binder(JNIEnv* env)

{

jclass clazz = FindClassOrDie(env, kBinderPathName);

gBinderOffsets.mClass = MakeGlobalRefOrDie(env, clazz);

gBinderOffsets.mExecTransact = GetMethodIDOrDie(env, clazz, "execTransact", "(IJJI)Z");

gBinderOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");

return RegisterMethodsOrDie(

env, kBinderPathName,

gBinderMethods, NELEM(gBinderMethods));

}

關聯了android.os.Binder類,並會用到該類的mExecTransact域和execTransact方法,將其儲存到gBinderOffsets物件中,也就意味著native會將某值儲存到mExecTransact中,也會回呼execTransact方法。

const char* const kBinderInternalPathName = "com/android/internal/os/BinderInternal";

static int int_register_android_os_BinderInternal(JNIEnv* env)

{

jclass clazz = FindClassOrDie(env, kBinderInternalPathName);

gBinderInternalOffsets.mClass = MakeGlobalRefOrDie(env, clazz);

gBinderInternalOffsets.mForceGc = GetStaticMethodIDOrDie(env, clazz, "forceBinderGc", "()V");

return RegisterMethodsOrDie(

env, kBinderInternalPathName,

gBinderInternalMethods, NELEM(gBinderInternalMethods));

}

關聯了java的com.android.internal.os.BinderInternal類,儲存了其forceBinderGc方法。

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);

clazz = FindClassOrDie(env, kBinderProxyPathName);

gBinderProxyOffsets.mClass = MakeGlobalRefOrDie(env, clazz);

gBinderProxyOffsets.mConstructor = GetMethodIDOrDie(env, clazz, "", "()V");

gBinderProxyOffsets.mSendDeathNotice = GetStaticMethodIDOrDie(env, clazz, "sendDeathNotice",

"(Landroid/os/IBinder$DeathRecipient;)V");

gBinderProxyOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");

gBinderProxyOffsets.mSelf = GetFieldIDOrDie(env, clazz, "mSelf",

"Ljava/lang/ref/WeakReference;");

gBinderProxyOffsets.mOrgue = GetFieldIDOrDie(env, clazz, "mOrgue", "J");

clazz = FindClassOrDie(env, "java/lang/Class");

gClassOffsets.mGetName = GetMethodIDOrDie(env, clazz, "getName", "()Ljava/lang/String;");

return RegisterMethodsOrDie(

env, kBinderProxyPathName,

gBinderProxyMethods, NELEM(gBinderProxyMethods));

}

這個方法比較長,儲存的Java的東西也比較多,值得注意的是,它還儲存了BinderProxy的建構函式,也就是說它可能會主動new一個BinderProxy例項出來。

看到目前為止,native的Binder要對應到Java的3個類中,分別是android.os.Binder,com.android.internal.os.BinderInternal和android.os.BinderProxy。為了方便閱讀,將它們的對應關係以類圖的形式總結下:

716f3bcf143db38a5f44b139fd5e628b.png

將Java層的服務註冊到ServiceManager中的過程

我們知道,native層的Binder有Bn和Bp之說,Bn應該是Binder Native的縮寫,就是本地實現Binder的意思也可以說是C/S中的S,Bp是Binder Proxy的縮寫,相當於C。

以PackageManagerService為例:

public static PackageManagerService main(Context

......

PackageManagerService m = new PackageManagerService(context, installer,

factoryTest, onlyCore);

......

ServiceManager.addService("package", m);

return m;

}

public static void addService(String name, IBinder service) {

try {

getIServiceManager().addService(name, service, false);

} catch (RemoteException e) {

Log.e(TAG, "error in addService", e);

}

}

getIServiceManager回傳的是一個IServiceManager類,且是個單例,最後呼叫的就是

private static IServiceManager getIServiceManager() {

if (sServiceManager != null) {

return sServiceManager;

}

// Find the service manager

sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());

return sServiceManager;

}

以上程式碼帶來 三個問題,一個是BinderInternal.getContextObject(),一個是ServiceManagerNative.asInterface,另一個是addService的作用:

BinderInternal.getContextObject()的實質

ServiceManagerNative.asInterface中的引數是BinderInternal.getContextObject(),看它是native方法,對應的native程式碼就在剛剛看到的android_util_Binder.cpp檔案中:

static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)

{

// 是一個BpBinder

sp b = ProcessState::self()->getContextObject(NULL);

return javaObjectForIBinder(env, b);

}

jobject javaObjectForIBinder(JNIEnv* env, const sp& val)

{

if (val == NULL) return NULL;

if (val->checkSubclass(&gBinderOffsets)) {

// One of our own!

jobject object = static_cast(val.get())->object();

LOGDEATH("objectForBinder %p: it's our own %p!
", val.get(), object);

return object;

}

// For the rest of the function we will hold this lock, to serialize

// looking/creation/destruction of Java proxies for native Binder proxies.

AutoMutex _l(mProxyLock);

// Someone else's... do we know about it?

// 1

jobject object = (jobject)val->findObject(&gBinderProxyOffsets);

if (object != NULL) {

jobject res = jniGetReferent(env, object);

if (res != NULL) {

ALOGV("objectForBinder %p: found existing %p!
", val.get(), res);

return res;

}

LOGDEATH("Proxy object %p of IBinder %p no longer in working set!!!", object, val.get());

android_atomic_dec(&gNumProxyRefs);

val->detachObject(&gBinderProxyOffsets);

env->DeleteGlobalRef(object);

}

//2

object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);

if (object != NULL) {

LOGDEATH("objectForBinder %p: created new proxy %p !
", val.get(), object);

// The proxy holds a reference to the native object.

//3

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));

......

// Note that a new object reference has been created.

//4

android_atomic_inc(&gNumProxyRefs);

incRefsCreated(env);

}

return object;

}

首先判斷下和Java層關聯的Native層的BpBinder是否存在,如果存在,刪除。

接著建立一個Java層的BinderProxy例項。

將Native層的BpBinder指標儲存到java BinderProxy例項的mObject欄位中,這樣透過BinderProxy的mObject欄位就可以操作Native層的BpBinder了。

原子增加gNumProxyRefs和gNumRefsCreated的數量,當gNumRefsCreated的值超過200,將會呼叫BinderInternal的forceBinderGc方法。

總結下:

建立了一個Native層的BpBinder;

將BpBinder的指標儲存到BinderProxy的mObject,而BpBinder的通訊物件就是Native的ServiceManager,這為Java和Native的ServiceManager的通訊埋下了伏筆。

可以將BinderProxy說成Java層的Bp端。

ServiceManagerNative.asInterface的作用

static public IServiceManager asInterface(IBinder obj)

{

if (obj == null) {

return null;

}

//1

IServiceManager in =

(IServiceManager)obj.queryLocalInterface(descriptor);

if (in != null) {

return in;

}

//2

return new ServiceManagerProxy(obj);

}

obj是Native例項化的BinderProxy物件,BinderProxy的程式碼在Binder.java中,和Binder位於同一個檔案中。queryLocalInterface的回傳值為null。

例項化一個ServiceManagerProxy物件,該例項中有一個IBinder型別的mRemote欄位,該欄位儲存BinderProxy例項。

public ServiceManagerProxy(IBinder remote) {

mRemote = remote;

}

總結:

ServiceManagerNative.asInterface回傳的是ServiceManagerProxy的例項,該例項實現IServiceManager的介面。

ServiceManagerProxy中透過mRemote欄位儲存了BinderProxy,也就是Java層的Bp端。

addService的作用

有上分析,當呼叫ServiceManager.addService時,實際上呼叫的是ServiceManagerProxy類中的addService,ServiceManagerProxy類位於ServiceManagerNative.java檔案中。

public void addService(String name, IBinder service, boolean allowIsolated)

throws RemoteException {

Parcel data = Parcel.obtain();

Parcel reply = Parcel.obtain();

data.writeInterfaceToken(IServiceManager.descriptor);

data.writeString(name);

data.writeStrongBinder(service);

data.writeInt(allowIsolated ? 1 : 0);

//1

mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);

reply.recycle();

data.recycle();

}

mRemote即為BinderProxy,它會呼叫transactNative,transactNative是個native方法,接著看這個方法。

static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,

//1

IBinder* target = (IBinder*)

env->GetLongField(obj, gBinderProxyOffsets.mObject);

if (target == NULL) {

jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!");

return JNI_FALSE;

}

//2

status_t err = target->transact(code, *data, reply, flags);

......

return JNI_FALSE;

}

取出儲存在BinderProxy中的BpBinder物件的指標

向Native層的ServiceManager發送請求

總結:

Java層呼叫ServiceManger.addService後,最終是向Native層的ServiceManager請求增加服務的。

Native層的ServiceManager是衹有一個的,而java層的ServiceManager相對於Native的ServiceManager也只是個C端,這樣,不管是透過Native add service還是透過java add service,整個Android都可以拿到這個service的Binder。

Java Service端的Bp在哪裡

這時候還有個疑問,當呼叫ServiceManager.addService時傳入的Service應該對應到Native的BnBinder啊,現在對應關係如何體現呢?這個關係要重看下addService了。

addService第二個引數的型別是IBinder,它是個介面,而它的實現類是Binder,java上層能呼叫addService新增服務時,所有的例項都是Binder,根據java的規則,只要例項化,其父類的相應的建構函式必被呼叫:

public Binder() {

init();

......

}

init()是native方法,其實現在android_util_Binder.cpp中:

static void android_os_Binder_init(JNIEnv* env, jobject obj)

{

JavaBBinderHolder* jbh = new JavaBBinderHolder();

...

env->SetLongField(obj, gBinderOffsets.mObject, (jlong)jbh);

}

new一個native層的JavaBBinderHolder,並將其儲存到Binder的mObject中。注意哦,雖然native層的gBinderOffsets.mObject是個static的,但java層的Binder的mObject可不是static的哦,就是說每個Binder例項都有一個Native的JavaBBinderHolder物件指標。

JavaBBinderHolder類的宣告如下:

class JavaBBinderHolder : public RefBase

{

}

沒有繼承BBinder,還是沒發現作為Bn端的蹤影,需要再review下前面的流程,看下ServiceManagerProxy新增服務時發生了什麼:

public void addService(String name, IBinder service, boolean allowIsolated)

throws RemoteException {

Parcel data = Parcel.obtain();

......

data.writeStrongBinder(service);

......

}

writeStrongBinder值得懷疑

writeStrongBinder發生了什麼

Parcel的這個函式如下:

public final void writeStrongBinder(IBinder val) {

nativeWriteStrongBinder(mNativePtr, val);

}

nativeWriteStrongBinder的實現在android_os_Parcel.cpp中:

static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)

{

Parcel* parcel = reinterpret_cast(nativePtr);

if (parcel != NULL) {

const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));

if (err != NO_ERROR) {

signalExceptionForError(env, clazz, err);

}

}

}

呼叫了一個ibinderForJavaObject函式,該函式位於android_util_Binder.cpp中

sp ibinderForJavaObject(JNIEnv* env, jobject obj)

{

if (obj == NULL) return NULL;

if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {

JavaBBinderHolder* jbh = (JavaBBinderHolder*)

env->GetLongField(obj, gBinderOffsets.mObject);

return jbh != NULL ? jbh->get(env, obj) : NULL;

}

if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {

return (IBinder*)

env->GetLongField(obj, gBinderProxyOffsets.mObject);

}

ALOGW("ibinderForJavaObject: %p is not a Binder object", obj);

return NULL;

}

傳入的obj是Binder例項,所以剛剛建立的JavaBBinderHolder的get函式會被呼叫:

sp get(JNIEnv* env, jobject obj)

{

AutoMutex _l(mLock);

sp b = mBinder.promote();

if (b == NULL) {

b = new JavaBBinder(env, obj);

mBinder = b;

ALOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%" PRId32 "
",

b.get(), b->getWeakRefs(), obj, b->getWeakRefs()->getWeakCount());

}

return b;

}

回傳的是JavaBBinder例項,

JavaBBinder繼承了BBinder,所以最終新增到Native ServiceManager中的是這個物件,總結下它們的類圖:

e1bcf7a8e6bce62e32057909b962405b.png

Java層的Binder物件擁有Native JavaBBinderHolder物件的指標,JavaBBinderHolder有JavaBBinder的物件,而JavaBBinder又有Java層Binder的物件。