Android之IPC6————Binder3 Framework層分析
Android之IPC6————Binder3 Framework層分析
文章目錄
一.概述
在前兩篇我們分析了Binder在Native層的實現,我們今天來看在Framework層,Binder相關的內容,這一篇也是以註冊服務和獲取服務來看Binder的流程。
bidner在Framework層,採用JNI技術來呼叫native層的binder架構,從而為上層應用提供服務。
java JNI本意是Java native interface,是為了方便javad呼叫C,C++等原生代碼所封裝的異常介面。jni也是JVM規範中的一部份,因此可以將我們寫的 JNI 程式在任何實現了 JNI 規範的 Java 虛擬機器中執行。
這篇文章主要講下面幾個方面:
- BinderJNI初始化(註冊)
- FrameWork層的註冊服務
- FrameWork層的獲取服務
下面這個是framework的binder類關係圖:
二.BinderJNI初始化
在Android系統開機的過程中,Zygote啟動時會有一個虛擬機器註冊過程,該過程呼叫AndroidRuntime::startReg方法來完成jni方法的註冊。
1.註冊JNI方法
int AndroidRuntime::startReg(JNIEnv* env)
{
androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);
env->PushLocalFrame(200);
//註冊jni方法 【見下】
if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
env->PopLocalFrame(NULL);
return -1;
}
env->PopLocalFrame(NULL);
return 0;
}
註冊jni方法
int register_android_os_Binder(JNIEnv* env) {
// 註冊Binder類的jni方法【見下】
if (int_register_android_os_Binder(env) < 0)
return -1;
// 註冊BinderInternal類的jni方法【見下】
if (int_register_android_os_BinderInternal(env) < 0)
return -1;
// 註冊BinderProxy類的jni方法【見下】
if (int_register_android_os_BinderProxy(env) < 0)
return -1;
...
return 0;
}
2.註冊Binder類
static int int_register_android_os_Binder(JNIEnv* env)
{
//其中kBinderPathName = "android/os/Binder";查詢kBinderPathName路徑所屬類
jclass clazz;
clazz = env->FindClass(kBinderPathName);
LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Binder");
//將java層的Binder類儲存到mClass變數;
gBinderOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
//將Java層execTransact()方法儲存到mExecTransact變數;
gBinderOffsets.mExecTransact
= env->GetMethodID(clazz, "execTransact", "(IJJI)Z");
assert(gBinderOffsets.mExecTransact);
//將Java層mObject屬性儲存到mObject變數
gBinderOffsets.mObject
= env->GetFieldID(clazz, "mObject", "J");
assert(gBinderOffsets.mObject);
return AndroidRuntime::registerNativeMethods(
env, kBinderPathName,
gBinderMethods, NELEM(gBinderMethods));
}
gBinderoffers是全域性靜態結構體,其定義如下:
static struct bindernative_offsets_t
{
// Class state.
jclass mClass; //記錄Binder類
jmethodID mExecTransact;//記錄execTransact()方法
// Object state.
jfieldID mObject; //記錄mObject屬性
} gBinderOffsets;
gBinderoffers儲存了Binder.java類本身的以及其成員方法,execTransact()和成員屬性mObject,這為JNI層訪問Java層提供通道。另外通過查詢獲取Java層 binder資訊後儲存到gBinderOffsets。
再看看registerNativeMethods中第三個引數,即 gBinderMethods
//為Java層訪問JNI層提供通道。
static const JNINativeMethod gBinderMethods[] = {
/* name, signature, funcPtr */
{ "getCallingPid", "()I", (void*)android_os_Binder_getCallingPid },
{ "getCallingUid", "()I", (void*)android_os_Binder_getCallingUid },
{ "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity },
{ "restoreCallingIdentity", "(J)V", (void*)android_os_Binder_restoreCallingIdentity },
{ "setThreadStrictModePolicy", "(I)V", (void*)android_os_Binder_setThreadStrictModePolicy },
{ "getThreadStrictModePolicy", "()I", (void*)android_os_Binder_getThreadStrictModePolicy },
{ "flushPendingCommands", "()V", (void*)android_os_Binder_flushPendingCommands },
{ "init", "()V", (void*)android_os_Binder_init },
{ "destroy", "()V", (void*)android_os_Binder_destroy }
};
在int_register_android_os_Binder中:
- 通過gBinderOffsets,儲存Java層Binder類的資訊,為JNI層訪問Java層提供通道;
- 通過RegisterMethodsOrDie,將gBinderMethods陣列完成對映關係,從而為Java層訪問JNI層提供通道。
3.註冊BinderInternal
static int int_register_android_os_BinderInternal(JNIEnv* env) {
//其中kBinderInternalPathName = "com/android/internal/os/BinderInternal"
jclass clazz = FindClassOrDie(env, kBinderInternalPathName);
gBinderInternalOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
gBinderInternalOffsets.mForceGc = GetStaticMethodIDOrDie(env, clazz, "forceBinderGc", "()V");
return RegisterMethodsOrDie(
env, kBinderInternalPathName,
gBinderInternalMethods, NELEM(gBinderInternalMethods));
}
上面是BinderInternal類的jni方法,gBinderInternalOffsets儲存了BinderInternal的forceBinderGc()方法。
gBinderInternalOffsets:
//BinderInternal類的JNI方法註冊:
static const JNINativeMethod gBinderInternalMethods[] = {
/* name, signature, funcPtr */
{ "getContextObject", "()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject },
{ "joinThreadPool", "()V", (void*)android_os_BinderInternal_joinThreadPool },
{ "disableBackgroundScheduling", "(Z)V", (void*)android_os_BinderInternal_disableBackgroundScheduling },
{ "handleGc", "()V", (void*)android_os_BinderInternal_handleGc }
};
和上面的類似,也是給Native層與framework層之間的相互呼叫的橋樑。
4. 註冊BinderProxy
static int int_register_android_os_BinderProxy(JNIEnv* env) {
//gErrorOffsets儲存了Error類資訊
jclass clazz = FindClassOrDie(env, "java/lang/Error");
gErrorOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
//gBinderProxyOffsets儲存了BinderProxy類的資訊
//其中kBinderProxyPathName = "android/os/BinderProxy"
clazz = FindClassOrDie(env, kBinderProxyPathName);
gBinderProxyOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
gBinderProxyOffsets.mConstructor = GetMethodIDOrDie(env, clazz, "<init>", "()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");
//gClassOffsets儲存了Class.getName()方法
clazz = FindClassOrDie(env, "java/lang/Class");
gClassOffsets.mGetName = GetMethodIDOrDie(env, clazz, "getName", "()Ljava/lang/String;");
return RegisterMethodsOrDie(
env, kBinderProxyPathName,
gBinderProxyMethods, NELEM(gBinderProxyMethods));
}
gBinderProxyMethods中:
//下面BinderProxy類的JNI方法註冊:
static const JNINativeMethod gBinderProxyMethods[] = {
/* name, signature, funcPtr */
{"pingBinder", "()Z", (void*)android_os_BinderProxy_pingBinder},
{"isBinderAlive", "()Z", (void*)android_os_BinderProxy_isBinderAlive},
{"getInterfaceDescriptor", "()Ljava/lang/String;", (void*)android_os_BinderProxy_getInterfaceDescriptor},
{"transactNative", "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact},
{"linkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath},
{"unlinkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath},
{"destroy", "()V", (void*)android_os_BinderProxy_destroy},
};
和上面一樣,也是Native層與framework層之間的相互呼叫的橋樑
三.註冊服務
1.SM.addService
從framework的ServiceManager.java開始
public static void addService(String name, IBinder service, boolean allowIsolated) {
try {
//先獲取SMP物件,則執行註冊服務操作【見小節3.2/3.4】
getIServiceManager().addService(name, service, allowIsolated);
} catch (RemoteException e) {
Log.e(TAG, "error in addService", e);
}
}
在addService中先獲去ServiceManagerProxy
2.獲取SMP
getIServiceManager
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
return sServiceManager;
}
獲取SMP有兩步關鍵步驟,即BinderInternal.getContextObject(),和ServiceManagerNative.asInterface()
BinderInternal.getContextObject()中最終會去獲取JNI( android_util_binder.cpp)中android_os_BinderInternal_getContextObject方法,
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
return javaObjectForIBinder(env, b);
}
對於ProcessState::self()->getContextObject(),在上一節中以及解決過,即ProcessState::self()->getContextObject()等價於 new BpBinder(0);
繼續看javaObjectForIBinder():
object javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val) {
if (val == NULL) return NULL;
if (val->checkSubclass(&gBinderOffsets)) { //返回false
jobject object = static_cast<JavaBBinder*>(val.get())->object();
return object;
}
AutoMutex _l(mProxyLock);
jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
if (object != NULL) { //第一次object為null
jobject res = jniGetReferent(env, object);
if (res != NULL) {
return res;
}
android_atomic_dec(&gNumProxyRefs);
val->detachObject(&gBinderProxyOffsets);
env->DeleteGlobalRef(object);
}
//建立BinderProxy物件
object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
if (object != NULL) {
//BinderProxy.mObject成員變數記錄BpBinder物件
env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
val->incStrong((void*)javaObjectForIBinder);
jobject refObject = env->NewGlobalRef(
env->GetObjectField(object, gBinderProxyOffsets.mSelf));
//將BinderProxy物件資訊附加到BpBinder的成員變數mObjects中
val->attachObject(&gBinderProxyOffsets, refObject,
jnienv_to_javavm(env), proxy_cleanup);
sp<DeathRecipientList> drl = new DeathRecipientList;
drl->incStrong((void*)javaObjectForIBinder);
//BinderProxy.mOrgue成員變數記錄死亡通知物件
env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jlong>(drl.get()));
android_atomic_inc(&gNumProxyRefs);
incRefsCreated(env);
}
return object;
}
根據BpBinder(C++)生成BinderProxy(Java)物件. 主要工作是建立BinderProxy物件,並把BpBinder物件地址儲存到BinderProxy.mObject成員變數. 到此,可知ServiceManagerNative.asInterface(BinderInternal.getContextObject()) 等價於
ServiceManagerNative.asInterface(new BinderProxy())
回到上面的ServiceManagerNative.asInterface()中
static public IServiceManager asInterface(IBinder obj) {
if (obj == null) { //obj為BpBinder
return null;
}
//由於obj為BpBinder,該方法預設返回null
IServiceManager in = (IServiceManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ServiceManagerProxy(obj);
}
所以ServiceManagerNative.asInterface(BinderInternal.getContextObject())等價於
new ServiceManagerProxy(new BinderProxy()).
來看看 ServiceManagerProxy()的建構函式
class ServiceManagerProxy implements IServiceManager {
public ServiceManagerProxy(IBinder remote) {
mRemote = remote;
}
}
mRemote為BinderProxy物件,該BinderProxy物件對應於BpBinder(0),其作為binder代理端,指向native層大管家service Manager。
3.SMP.addService()
通過上面的分析可知getIServiceManager()最終獲取的是ServiceManagerProxy(),所以我們來看看ServiceManagerProxy()的addService方法。
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);
//mRemote為BinderProxy【見下文】
mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
reply.recycle();
data.recycle();
}
這裡我們發現,和Native層註冊服務的步驟幾乎一模一樣。
所以問題變為FrameWork層的Binder轉換為Native層。
當時我們分析Native層的時候,主要看的是writeStrongBinder和transact方法,這裡我們繼續看這兩個方法是如何從java到c++的。
4.writeStrongBinder
public writeStrongBinder(IBinder val){
//此處為Native呼叫
nativewriteStrongBinder(mNativePtr, val);
}
看呼叫JNI的方法
static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object) {
//將java層Parcel轉換為native層Parcel
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) {
//ibinderForJavaObject【見下】
const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
if (err != NO_ERROR) {
signalExceptionForError(env, clazz, err);
}
}
}
繼續看ibinderForJavaObject
sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
{
if (obj == NULL) return NULL;
//Java層的Binder物件
if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
JavaBBinderHolder* jbh = (JavaBBinderHolder*)
env->GetLongField(obj, gBinderOffsets.mObject);
return jbh != NULL ? jbh->get(env, obj) : NULL;
}
//Java層的BinderProxy物件
if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
return (IBinder*)env->GetLongField(obj, gBinderProxyOffsets.mObject);
}
return NULL;
}
在這裡面將Binde(Java)生成JavaBBinderHolder(C++)物件. 主要工作是建立JavaBBinderHolder物件,並把JavaBBinderHolder物件地址儲存到Binder.mObject成員變數。
我們看看 ibinderForJavaObject最終返回的結果,即JavaBBinderHolder.get()
sp<JavaBBinder> get(JNIEnv*