摘要:本節主要來說解Android10.0 Binder 在Framework的使用分析html
閱讀本文大約須要花費15分鐘。java
文章首發微信公衆號:IngresGelinux
專一於Android系統級源碼分析,Android的平臺設計,歡迎關注我,謝謝!android
[Android取經之路] 的源碼都基於Android-Q(10.0) 進行分析git
[Android取經之路] 系列文章:數組
《系統啓動篇》緩存
- Android系統架構
- Android是怎麼啓動的
- Android 10.0系統啓動之init進程
- Android10.0系統啓動之Zygote進程
- Android 10.0 系統啓動之SystemServer進程
- Android 10.0 系統服務之ActivityMnagerService
- Android10.0系統啓動之Launcher(桌面)啓動流程
- Android10.0應用進程建立過程以及Zygote的fork流程
- Android 10.0 PackageManagerService(一)工做原理及啓動流程
- Android 10.0 PackageManagerService(二)權限掃描
- Android 10.0 PackageManagerService(三)APK掃描
- Android 10.0 PackageManagerService(四)APK安裝流程
《日誌系統篇》微信
- Android10.0 日誌系統分析(一)-logd、logcat 指令說明、分類和屬性
- Android10.0 日誌系統分析(二)-logd、logcat架構分析及日誌系統初始化
- Android10.0 日誌系統分析(三)-logd、logcat讀寫日誌源碼分析
- Android10.0 日誌系統分析(四)-selinux、kernel日誌在logd中的實現
《Binder通訊原理》:cookie
- Android10.0 Binder通訊原理(一)Binder、HwBinder、VndBinder概要
- Android10.0 Binder通訊原理(二)-Binder入門篇
- Android10.0 Binder通訊原理(三)-ServiceManager篇
- Android10.0 Binder通訊原理(四)-Native-C\C++實例分析
- Android10.0 Binder通訊原理(五)-Binder驅動分析
- Android10.0 Binder通訊原理(六)-Binder數據如何完成定向打擊
- Android10.0 Binder通訊原理(七)-Framework binder示例
- Android10.0 Binder通訊原理(八)-Framework層分析
- Android10.0 Binder通訊原理(九)-AIDL Binder示例
1.概述
前面幾節,咱們已經把Native層和Binder驅動層的Binder數據流轉給理清楚了,也知道了相應的概念。這一節讓咱們繼續往上進行分析,咱們進入到Framework層,看看Framework是如何實現服務的註冊、獲取的流程。架構
2.Binder架構
Framework層要實現服務的註冊須要經過JNI 來調用Native C\C++層的相應接口,最終把服務註冊到Native層的ServiceManager中。
應用層的進行經過Framework的接口,也通過JNI技術進入Native C\C++,最終在Native層的ServiceManager中獲得服務handle,最終轉成相應的服務對象。
3.源碼分析
3.1 Binder-JNI
當Init進程啓動後,孵化Zygote進程時,會有一個虛擬機註冊過程,在這個過程當中完成了JNI的註冊,咱們如今不須要深刻去理解JNI的原理,後面有時間,我再單獨出一章來進行分析。
如今咱們只要知道 JAVA和Native側的函數對應關係在哪裏便可。
Binder的JNI中有個三個Binder的映射數組:gBinderMethods、gBinderInternalMethods、gBinderInternalMethods。
咱們在擼代碼時,是要根據JAVA的函數入口找到JNI的函數調用便可,不要太追求細枝末節。
gBinderMethods:
[/frameworks/base/core/jni/android_util_Binder.cpp] static const JNINativeMethod gBinderMethods[] = { /* name, signature, funcPtr */ // @CriticalNative { "getCallingPid", "()I", (void*)android_os_Binder_getCallingPid }, // @CriticalNative { "getCallingUid", "()I", (void*)android_os_Binder_getCallingUid }, // @CriticalNative { "isHandlingTransaction", "()Z", (void*)android_os_Binder_isHandlingTransaction }, // @CriticalNative { "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity }, { "restoreCallingIdentity", "(J)V", (void*)android_os_Binder_restoreCallingIdentity }, // @CriticalNative { "setThreadStrictModePolicy", "(I)V", (void*)android_os_Binder_setThreadStrictModePolicy }, // @CriticalNative { "getThreadStrictModePolicy", "()I", (void*)android_os_Binder_getThreadStrictModePolicy }, // @CriticalNative { "setCallingWorkSourceUid", "(I)J", (void*)android_os_Binder_setCallingWorkSourceUid }, // @CriticalNative { "getCallingWorkSourceUid", "()I", (void*)android_os_Binder_getCallingWorkSourceUid }, // @CriticalNative { "clearCallingWorkSource", "()J", (void*)android_os_Binder_clearCallingWorkSource }, { "restoreCallingWorkSource", "(J)V", (void*)android_os_Binder_restoreCallingWorkSource }, { "flushPendingCommands", "()V", (void*)android_os_Binder_flushPendingCommands }, { "getNativeBBinderHolder", "()J", (void*)android_os_Binder_getNativeBBinderHolder }, { "getNativeFinalizer", "()J", (void*)android_os_Binder_getNativeFinalizer }, { "blockUntilThreadAvailable", "()V", (void*)android_os_Binder_blockUntilThreadAvailable } };
gBinderInternalMethods:
[/frameworks/base/core/jni/android_util_Binder.cpp] 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 }, { "setMaxThreads", "(I)V", (void*)android_os_BinderInternal_setMaxThreads }, { "handleGc", "()V", (void*)android_os_BinderInternal_handleGc }, { "nSetBinderProxyCountEnabled", "(Z)V", (void*)android_os_BinderInternal_setBinderProxyCountEnabled }, { "nGetBinderProxyPerUidCounts", "()Landroid/util/SparseIntArray;", (void*)android_os_BinderInternal_getBinderProxyPerUidCounts }, { "nGetBinderProxyCount", "(I)I", (void*)android_os_BinderInternal_getBinderProxyCount }, { "nSetBinderProxyCountWatermarks", "(II)V", (void*)android_os_BinderInternal_setBinderProxyCountWatermarks} };
gBinderInternalMethods:
[/frameworks/base/core/jni/android_util_Binder.cpp] 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 }, { "setMaxThreads", "(I)V", (void*)android_os_BinderInternal_setMaxThreads }, { "handleGc", "()V", (void*)android_os_BinderInternal_handleGc }, { "nSetBinderProxyCountEnabled", "(Z)V", (void*)android_os_BinderInternal_setBinderProxyCountEnabled }, { "nGetBinderProxyPerUidCounts", "()Landroid/util/SparseIntArray;", (void*)android_os_BinderInternal_getBinderProxyPerUidCounts }, { "nGetBinderProxyCount", "(I)I", (void*)android_os_BinderInternal_getBinderProxyCount }, { "nSetBinderProxyCountWatermarks", "(II)V", (void*)android_os_BinderInternal_setBinderProxyCountWatermarks} };
3.2 服務註冊
在上一節的Framework Binder Demo示例中,咱們知道服務註冊的時候,調用的是ServiceManager.java的addService(),那咱們就拿addService()開刀。
註冊服務調用棧:
3.2.1 addService()
[/frameworks/base/core/java/android/os/ServiceManager.java] public static void addService(String name, IBinder service, boolean allowIsolated, int dumpPriority) { try { //獲取ServiceManagerProxy對象,執行addService操做 getIServiceManager().addService(name, service, allowIsolated, dumpPriority); } catch (RemoteException e) { Log.e(TAG, "error in addService", e); } }
拿到ServiceManagerProxy對象,來執行addService操做,這個ServiceManagerProxy對象須要咱們來揭開面紗。
3.2.2 getIServiceManager()
[/frameworks/base/core/java/android/os/ServiceManager.java] private static IServiceManager getIServiceManager() { if (sServiceManager != null) { return sServiceManager; } // Find the service manager sServiceManager = ServiceManagerNative .asInterface(Binder.allowBlocking(BinderInternal.getContextObject())); return sServiceManager; }
這裏也採用了單例模式來獲取ServiceManagerProxy對象,減小對象重複建立。
[/frameworks/base/core/java/android/os/ServiceManagerNative.java] static public IServiceManager asInterface(IBinder obj) { if (obj == null) { return null; } IServiceManager in = (IServiceManager)obj.queryLocalInterface(descriptor); if (in != null) { return in; } return new ServiceManagerProxy(obj); }
asInterface()中的主要做用就是建立ServiceManagerProxy()對象,可是須要帶一個IBinder的 obj,我來看看這個obj是如何拿到的。
3.2.3 getContextObject()
[/frameworks/base/core/java/com/android/internal/os/BinderInternal.java] public static final native IBinder getContextObject();
BinderInternal.java中有一個native方法getContextObject(),JNI調用執行上述方法,在JNI的 gBinderInternalMethods數組中找到了getContextObject的對應關係,即爲android_os_BinderInternal_getContextObject。
android_os_BinderInternal_getContextObject() [/frameworks/base/core/jni/android_util_Binder.cpp] static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz) { sp<IBinder> b = ProcessState::self()->getContextObject(NULL); return javaObjectForIBinder(env, b); }
ProcessState::self()->getContextObject(NULL) 在《Binder--Native-C\C++實例分析》 的[5.3.1]節已經進行了詳細分析,最終等價於 new BpBinder(0),這裏就不重複展開了。
javaObjectForIBinder()
若是參數是JavaBBinder,返回用於建立它的Java對象;不然返回一個BinderProxy的對象。
若是上一個調用被傳遞給同一個IBinder,而原來的BinderProxy還活着,返回一樣的BinderProxy。
[/frameworks/base/core/jni/android_util_Binder.cpp] jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val) { if (val == NULL) return NULL; if (val->checkSubclass(&gBinderOffsets)) { //若是參數是JavaBBinder,返回用於建立它的Java對象;不然返回一個BinderProxy的對象。 jobject object = static_cast<JavaBBinder*>(val.get())->object(); LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object); return object; } //申請一個BinderProxyNativeData的內存 BinderProxyNativeData* nativeData = new BinderProxyNativeData(); nativeData->mOrgue = new DeathRecipientList; nativeData->mObject = val; //建立BinderProxy對象,設置BinderProxy的相關參數,可以與JAVA層的BinderProx參與工做 jobject object = env->CallStaticObjectMethod(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mGetInstance, (jlong) nativeData, (jlong) val.get()); if (env->ExceptionCheck()) { return NULL; } BinderProxyNativeData* actualNativeData = getBPNativeData(env, object); if (actualNativeData == nativeData) { // Created a new Proxy uint32_t numProxies = gNumProxies.fetch_add(1, std::memory_order_relaxed); uint32_t numLastWarned = gProxiesWarned.load(std::memory_order_relaxed); if (numProxies >= numLastWarned + PROXY_WARN_INTERVAL) { if (gProxiesWarned.compare_exchange_strong(numLastWarned, numLastWarned + PROXY_WARN_INTERVAL, std::memory_order_relaxed)) { ALOGW("Unexpectedly many live BinderProxies: %d\n", numProxies); } } } else { delete nativeData; } return object; }
javaObjectForIBinder()中,申請一個BinderProxyNativeData的內存,傳入的BpBinder的對象地址保存到BinderProxyNativeData.mObject成員變量中,經過虛擬機的轉換,BinderProxyNativeData在JAVA空間會被轉換成 BinderProxy對象。
最終,BinderInternal.getContextObject()等價於 new BinderProxy(),因此getIServiceManager等價於new ServiceManagerProxy(new BinderProxy())。
3.2.4 ServiceManagerProxy.addService()
上一節,咱們已經拿到了ServiceManager在JAVA空間的代理,即ServiceManagerProxy,接着調用addService()來進行服務的註冊。
[/frameworks/base/core/java/android/os/IServiceManager.java] public void addService(String name, IBinder service, boolean allowIsolated, int dumpPriority) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IServiceManager.descriptor); data.writeString(name); //將Binder對象扁平化,轉換成flat_binder_object對象,這裏爲服務註冊,對應的是Binder實體 data.writeStrongBinder(service); data.writeInt(allowIsolated ? 1 : 0); data.writeInt(dumpPriority); //Code:ADD_SERVICE_TRANSACTION ,parcel的數據 發到C空間,進行事務處理,註冊服務。 mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0); reply.recycle(); data.recycle(); }
組裝一個Parcel數據,把服務的名稱和對象寫入Parcel中,而後把它拍扁,服務轉成flat_binder_object對象,在Native層爲Binder實體。
3.2.5 writeStrongBinder()
把傳入的服務對象拍扁,轉成flat_binder_object對象,代碼流程太羅嗦,這裏列出如下調用棧流程:
data.writeStrongBinder(service)等價於parcel->writeStrongBinder(new JavaBBinder(env, obj));最終調用的是flatten_binder(),目的是把一個Binder實體「壓扁」並寫入Parcel。
這裏"壓扁"的含義,其實就是把Binder對象整理成flat_binder_object變量。若是壓扁的是Binder實體,那麼flat_binder_object用cookie域記錄binder實體的指針,即BBinder指針,而若是打扁的是Binder代理,那麼flat_binder_object用handle域記錄的binder代理的句柄值。
接着flatten_binder()調用了一個關鍵的finish_flatten_binder()函數。這個函數內部會記錄下剛剛被扁平化的flat_binder_object在parcel中的位置。說得更詳細點兒就是,parcel對象內部會有一個buffer,記錄着parcel中全部扁平化的數據,有些扁平數據是普通數據,而另外一些扁平數據則記錄着binder對象。因此parcel中會構造另外一個mObjects數組,專門記錄那些binder扁平數據所在的位置,示意圖以下:
flatten_binder()的流程能夠參考《Binder--Native-C\C++實例分析》 的[5.4]節
3.2.6 mRemote對象
class ServiceManagerProxy implements IServiceManager { public ServiceManagerProxy(IBinder remote) { mRemote = remote; } @UnsupportedAppUsage private IBinder mRemote; }
mRemote 是ServiceManagerProxy的一個成員,執行一個IBinder對象,mRemote在ServiceManagerProxy()構造函數中進行了賦值,從[4.2.3]和[4.2.4] 可知getIServiceManager()中調用了 以下內容:
sServiceManager = ServiceManagerNative.asInterface(Binder.allowBlocking(BinderInternal.getContextObject()))
從而可知 mRemote = BinderInternal.getContextObject() = new BinderProxy(),因此mRemote就是BinderProxy的對象。
mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0) 等價於BinderProxy.transact(ADD_SERVICE_TRANSACTION, data, reply, 0)
3.2.7 BiderProxy.transact()
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { //檢查Parcel的大小是否大於800K Binder.checkParcel(this, code, data, "Unreasonably large binder buffer"); try { return transactNative(code, data, reply, flags); } finally { ... } }
邏輯很簡單,先檢查Parcel的大小是否大於800K,而後調用了transactNative()進行數據傳遞。
public native boolean transactNative(int code, Parcel data, Parcel reply, int flags) throws RemoteException;
transactNative()一個Native方法,根據以前的JNI數組表,能夠查到JNI的對應入口。
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj, jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException { ... Parcel* data = parcelForJavaObject(env, dataObj); ... Parcel* reply = parcelForJavaObject(env, replyObj); ... IBinder* target = getBPNativeData(env, obj)->mObject.get(); ... //根據咱們以前獲取的對象流程來看,BinderProxy在Native空間,對應的是BpBinder,target即爲BpBinder對象 status_t err = target->transact(code, *data, reply, flags); ... return JNI_FALSE; }
根據咱們以前獲取的對象流程來看,BinderProxy在Native空間,對應的是BpBinder,target即爲BpBinder對象。因此target->transact() 等價於BpBinder::transact(), 接下來的流程參考前面Native-C\C++層的分析,這裏的細節再也不闡述,參考 《Binder--Native-C\C++實例分析》 和 《Binder數據如何定向打擊》,也能夠看到上面註冊服務的調用棧。
3.2.8 服務註冊總結
framework層的ServiceManager的調用實際的工做確實交給ServiceManagerProxy的成員變量BinderProxy;而BinderProxy經過jni方式,最終會調用BpBinder對象;可見上層binder架構的核心功能依賴native架構的服務來完成的。
註冊服務的核心部分,就是JAVA側把服務名稱和對象,轉入Parcel「扁平」數據,經過Native BpBinder,把code:ADD_SERVICE_TRANSACTION發給Binder驅動,再轉到Native的ServiceManager,ServiceManager把服務名稱和轉換後的handler進行存儲,供Client進行服務獲取。
3.3 服務獲取
在上一節的Framework Binder Demo示例中,咱們知道服務註冊的時候,調用的是ServiceManager.java的getService(),那麼獲取服務就從getService()入口。
[/frameworks/base/core/java/android/os/ServiceManager.java] public static IBinder getService(String name) { try { //從緩存中獲取服務對象 IBinder service = sCache.get(name); if (service != null) { return service; } else { //從Native層服務列表中取服務對象 return Binder.allowBlocking(rawGetService(name)); } } catch (RemoteException e) { Log.e(TAG, "error in getService", e); } return null; }
3.3.2 rawGetService()
[/frameworks/base/core/java/android/os/ServiceManager.java] private static IBinder rawGetService(String name) throws RemoteException { ... // //即爲ServiceManagerProxy().getService final IBinder binder = getIServiceManager().getService(name); ... return binder; }
從上面可知getIServiceManager() 等價於 new ServiceManagerProxy(new BinderProxy()),getIServiceManager().getService(name)等價於ServiceManagerProxy().getService(name)
3.3.3 getService()
[/frameworks/base/core/java/android/os/ServiceManagerNative.java] public IBinder getService(String name) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IServiceManager.descriptor); data.writeString(name); mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0); IBinder binder = reply.readStrongBinder(); reply.recycle(); data.recycle(); return binder; }
從[4.2.6]可知,mRemote.transact(XXX) 等價於BinderProxy.transact(xx),這裏不展開,和[4.2.7流程]同樣,只是ServiceManager獲取到服務的handle後,存入了reply信息中,這裏會再調用reply.readStrongBinder()把binder對象給取出來。
3.3.4 readStrongBinder()
public final IBinder readStrongBinder() { return nativeReadStrongBinder(mNativePtr); }
調用棧以下:
Parcel.cpp -> readStrongBinder() 參考 《Binder--Native-C\C++實例分析》 中的[6.4]節, javaObjectForIBinder()參考[4.2.3]
readStrongBinder()最終是從reply的Parcel數據中得到BpBinder對象,再轉成BinderProxy對象,參與JAVA層的工做。
3.3.5 allowBlocking
[/frameworks/base/core/java/android/os/Binder.java] public static IBinder allowBlocking(IBinder binder) { try { //若是binder是代理類,則設置非阻塞式 if (binder instanceof BinderProxy) { ((BinderProxy) binder).mWarnOnBlocking = false; } else if (binder != null && binder.getInterfaceDescriptor() != null && binder.queryLocalInterface(binder.getInterfaceDescriptor()) == null) { //若是binder是本地對象,binder描述符不爲空,且和本地binder描述符不相同 Log.w(TAG, "Unable to allow blocking on interface " + binder); } } catch (RemoteException ignored) { } return binder; }
做用:
- 容許在給定接口上阻塞調用,重寫請求的{setWarnOnBlocking(boolean)}值。
- 只有當您徹底肯定遠程接口是一個永遠沒法升級的內置系統組件時,才應該不多調用此命令。尤爲是,決不能對包託管的、可升級或替換的接口調用此命令,不然,若是遠程接口接入,將有系統不穩定的風險。
3.3.6 獲取服務小結
和註冊服務相似,都是須要依賴Native層的接口與Binder驅動通訊,獲取服務主要是從Native的ServieManager取到Binder對象。
3.4 Client-Server接口調用
在[3.2] 和[3.3]中,咱們知道了服務註冊addService()和獲取服務getService()的流程,接下來咱們再看一看接口調用是如何進行的。
[MyServiceProxy.java] public void setValue(String str) throws RemoteException { Parcel data = Parcel.obtain(); //準備發送數據,結構爲Parcel Parcel reply = Parcel.obtain();//準備返回數據,結構爲Parcel try { //寫入服務的Token,用來驗證服務的準確性 data.writeInterfaceToken(IMyService.descriptor); data.writeString(str); //把參數寫入Parcel,服務端會獲取該參數 mRemote.transact(SET_VALUE_TRANSACTION, data, reply, 0); //code:SET_VALUE_TRANSACTION reply.readException(); } finally { reply.recycle(); data.recycle(); } }
上面調用的流程,其實和addService()、getService()相似,都是組裝Parcel數據,準備服務端的code,調用BinderProxy.transact()發送到服務端。
可是和服務註冊不一樣的是,在服務註冊中,Native的ServiceManager是Server端,服務實體是Client端。接口調用時,服務實體是Server端。
服務端接收到CLient的請求後,根據下圖的流程,最終流轉到服務實體的onTransact()中,對解析出來的Parcel數據進行處理。
4.總結
Framework層獲取服務、註冊服務,其實都是由JAVA層的ServiceManager代理 ServiecManagerProxy ,經過Binder驅動,訪問Native層的ServiceManager,進行服務註冊和獲取動做。
這一節只是單獨在Framework層進行了分析,不少狀況下咱們都是在應用層進行處理流程,經過AIDL接口進行通訊,下一節會對AIDL進行一下分析。
代碼路徑:
Framework:
/frameworks/base/core/java/android/os/Binder.java
/frameworks/base/core/java/android/os/IBinder.java
/frameworks/base/core/java/android/os/BinderProxy.java
/frameworks/base/core/java/android/os/BinderProxy.java
/frameworks/base/core/java/android/os/ServiceManager.java
/frameworks/base/core/java/android/os/IServiceManager.java
/frameworks/base/core/java/android/os/ServiceManagerNative.java
/frameworks/base/core/java/com/android/internal/os/BinderInternal.java
JNI:
/frameworks/base/core/jni/android_util_Binder.h
/frameworks/base/core/jni/android_util_Binder.cpp
/frameworks/base/core/jni/android_os_Parcel.h
/frameworks/base/core/jni/android_os_Parcel.cpp
參考:
個人微信公衆號:IngresGe