日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

理解Android Binder机制(3/3):Java层

發布時間:2025/3/15 Android 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 理解Android Binder机制(3/3):Java层 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文是Android Binder機制解析的第三篇,也是最后一篇文章。本文會講解Binder Framework Java部分的邏輯。

Binder機制分析的前面兩篇文章,請移步這里:

理解Android Binder機制(1/3):驅動篇

理解Android Binder機制(2/3):C++層):驅動篇

下文所講內容的相關源碼,在AOSP源碼樹中的路徑如下:

// Binder Framework 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// Binder Framework Java接口 /frameworks/base/core/java/android/os/Binder.java /frameworks/base/core/java/android/os/IBinder.java /frameworks/base/core/java/android/os/IInterface.java /frameworks/base/core/java/android/os/Parcel.java

主要結構

Android應用程序使用Java語言開發,Binder框架自然也少不了在Java層提供接口。

前文中我們看到,Binder機制在C++層已經有了完整的實現。因此Java層完全不用重復實現,而是通過JNI銜接了C++層以復用其實現。

下圖描述了Binder Framework Java層到C++層的銜接關系。

這里對圖中Java層和JNI層的幾個類做一下說明( 關于C++層的講解請看這里?):

名稱類型說明
IInterfaceinterface供Java層Binder服務接口繼承的接口
IBinderinterfaceJava層的IBinder類,提供了transact方法來調用遠程服務
Binderclass實現了IBinder接口,封裝了JNI的實現。Java層Binder服務的基類
BinderProxyclass實現了IBinder接口,封裝了JNI的實現。提供transact方法調用遠程服務
JavaBBinderHolderclass內部存儲了JavaBBinder
JavaBBinderclass將C++端的onTransact調用傳遞到Java端
ParcelclassJava層的數據包裝器,見C++層的Parcel類分析

這里的IInterface,IBinder和C++層的兩個類是同名的。這個同名并不是巧合:它們不僅僅同名,它們所起的作用,以及其中包含的接口都是幾乎一樣的,區別僅僅在于一個是C++層,一個是Java層而已。

除了IInterface,IBinder之外,這里Binder與BinderProxy類也是與C++的類對應的,下面列出了Java層和C++層類的對應關系:

C++Java層
IInterfaceIInterface
IBinderIBinder
BBinderBinder
BpProxyBinderProxy
ParcelParcel

JNI的銜接

JNI全稱是Java Native Interface,這個是由Java虛擬機提供的機制。這個機制使得native代碼可以和Java代碼互相通訊。簡單來說就是:我們可以在C/C++端調用Java代碼,也可以在Java端調用C/C++代碼。

關于JNI的詳細說明,可以參見Oracle的官方文檔:Java Native Interface?,這里不多說明。

實際上,在Android中很多的服務或者機制都是在C/C++層實現的,想要將這些實現復用到Java層,就必須通過JNI進行銜接。AOSP源碼中,/frameworks/base/core/jni/ 目錄下的源碼就是專門用來對接Framework層的JNI實現的。

看一下Binder.java的實現就會發現,這里面有不少的方法都是用native關鍵字修飾的,并且沒有方法實現體,這些方法其實都是在C++中實現的:

public static final native int getCallingPid();public static final native int getCallingUid();public static final native long clearCallingIdentity();public static final native void restoreCallingIdentity(long token);public static final native void setThreadStrictModePolicy(int policyMask);public static final native int getThreadStrictModePolicy();public static final native void flushPendingCommands();public static final native void joinThreadPool();

在android_util_Binder.cpp文件中的下面這段代碼,設定了Java方法與C++方法的對應關系:

static const JNINativeMethod gBinderMethods[] = {{ "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 },{ "blockUntilThreadAvailable", "()V", (void*)android_os_Binder_blockUntilThreadAvailable } };

這種對應關系意味著:當Binder.java中的getCallingPid方法被調用的時候,真正的實現其實是android_os_Binder_getCallingPid,當getCallingUid方法被調用的時候,真正的實現其實是android_os_Binder_getCallingUid,其他類同。

然后我們再看一下android_os_Binder_getCallingPid方法的實現就會發現,這里其實就是對接到了libbinder中了:

static jint android_os_Binder_getCallingPid(JNIEnv* env, jobject clazz) {return IPCThreadState::self()->getCallingPid(); }

這里看到了Java端的代碼是如何調用的libbinder中的C++方法的。那么,相反的方向是如何調用的呢?最關鍵的,libbinder中的BBinder::onTransact是如何能夠調用到Java中的Binder::onTransact的呢?

這段邏輯就是android_util_Binder.cpp中JavaBBinder::onTransact中處理的了。JavaBBinder是BBinder子類,其類結構如下:

JavaBBinder::onTransact關鍵代碼如下:

virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) {JNIEnv* env = javavm_to_jnienv(mVM);IPCThreadState* thread_state = IPCThreadState::self();const int32_t strict_policy_before = thread_state->getStrictModePolicy();jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);... }

請注意這段代碼中的這一行:

jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);

這一行代碼其實是在調用mObject上offset為mExecTransact的方法。這里的幾個參數說明如下:

  • mObject 指向了Java端的Binder對象
  • gBinderOffsets.mExecTransact 指向了Binder類的execTransact方法
  • data 調用execTransact方法的參數
  • code, data, reply, flags都是傳遞給調用方法execTransact的參數

而JNIEnv.CallBooleanMethod這個方法是由虛擬機實現的。即:虛擬機會提供native方法來調用一個Java Object上的方法(關于Android上的Java虛擬機,今后我們會專門講解)。

這樣,就在C++層的JavaBBinder::onTransact中調用了Java層Binder::execTransact方法。而在Binder::execTransact方法中,又調用了自身的onTransact方法,由此保證整個過程串聯了起來:

private boolean execTransact(int code, long dataObj, long replyObj,int flags) {Parcel data = Parcel.obtain(dataObj);Parcel reply = Parcel.obtain(replyObj);boolean res;try {res = onTransact(code, data, reply, flags);} catch (RemoteException|RuntimeException e) {if (LOG_RUNTIME_EXCEPTION) {Log.w(TAG, "Caught a RuntimeException from the binder stub implementation.", e);}if ((flags & FLAG_ONEWAY) != 0) {if (e instanceof RemoteException) {Log.w(TAG, "Binder call failed.", e);} else {Log.w(TAG, "Caught a RuntimeException from the binder stub implementation.", e);}} else {reply.setDataPosition(0);reply.writeException(e);}res = true;} catch (OutOfMemoryError e) {RuntimeException re = new RuntimeException("Out of memory", e);reply.setDataPosition(0);reply.writeException(re);res = true;}checkParcel(this, code, reply, "Unreasonably large binder reply buffer");reply.recycle();data.recycle();StrictMode.clearGatheredViolations();return res; }

Java Binder服務舉例

和C++層一樣,這里我們還是通過一個具體的實例來看一下Java層的Binder服務是如何實現的。

下圖是ActivityManager實現的類圖:

下面是上圖中幾個類的說明:

類名說明
IActivityManagerBinder服務的公共接口
ActivityManagerProxy供客戶端調用的遠程接口
ActivityManagerNativeBinder服務實現的基類
ActivityManagerServiceBinder服務的真正實現

看過Binder C++層實現之后,對于這個結構應該也是很容易理解的,組織結構和C++層服務的實現是一模一樣的。

對于Android應用程序的開發者來說,我們不會直接接觸到上圖中的幾個類,而是使用android.app.ActivityManager中的接口。

這里我們就來看一下,android.app.ActivityManager中的接口與上圖的實現是什么關系。我們選取其中的一個方法來看一下:

public void getMemoryInfo(MemoryInfo outInfo) {try {ActivityManagerNative.getDefault().getMemoryInfo(outInfo);} catch (RemoteException e) {throw e.rethrowFromSystemServer();} }

這個方法的實現調用了ActivityManagerNative.getDefault()中的方法,因此我們在來看一下ActivityManagerNative.getDefault()返回到到底是什么。

static public IActivityManager getDefault() {return gDefault.get(); }private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {protected IActivityManager create() {IBinder b = ServiceManager.getService("activity");if (false) {Log.v("ActivityManager", "default service binder = " + b);}IActivityManager am = asInterface(b);if (false) {Log.v("ActivityManager", "default service = " + am);}return am;} };

這段代碼中我們看到,這里其實是先通過IBinder b = ServiceManager.getService("activity");?獲取ActivityManager的Binder對象(“activity”是ActivityManagerService的Binder服務標識),接著我們再來看一下asInterface(b)的實現:

static public IActivityManager asInterface(IBinder obj) {if (obj == null) {return null;}IActivityManager in =(IActivityManager)obj.queryLocalInterface(descriptor);if (in != null) {return in;}return new ActivityManagerProxy(obj); }

這里應該是比較明白了:首先通過queryLocalInterface確定有沒有本地Binder,如果有的話直接返回,否則創建一個ActivityManagerProxy對象。很顯然,假設在ActivityManagerService所在的進程調用這個方法,那么queryLocalInterface將直接返回本地Binder,而假設在其他進程中調用,這個方法將返回空,由此導致其他調用獲取到的對象其實就是ActivityManagerProxy。而在拿到ActivityManagerProxy對象之后在調用其方法所走的路線我想讀者應該也能明白了:那就是通過Binder驅動跨進程調用ActivityManagerService中的方法。

這里的asInterface方法的實現會讓我們覺得似曾相識。是的,因為這里的實現方式和C++層的實現是一樣的模式。

Java層的ServiceManager

源碼路徑:

frameworks/base/core/java/android/os/IServiceManager.java frameworks/base/core/java/android/os/ServiceManager.java frameworks/base/core/java/android/os/ServiceManagerNative.java frameworks/base/core/java/com/android/internal/os/BinderInternal.java frameworks/base/core/jni/android_util_Binder.cpp

有Java端的Binder服務,自然也少不了Java端的ServiceManager。我們先看一下Java端的ServiceManager的結構:

通過這個類圖我們看到,Java層的ServiceManager和C++層的接口是一樣的。

然后我們再選取addService方法看一下實現:

public static void addService(String name, IBinder service, boolean allowIsolated) {try {getIServiceManager().addService(name, service, allowIsolated);} catch (RemoteException e) {Log.e(TAG, "error in addService", e);} }private static IServiceManager getIServiceManager() {if (sServiceManager != null) {return sServiceManager;}// Find the service managersServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());return sServiceManager; }

很顯然,這段代碼中,最關鍵就是下面這個調用:

ServiceManagerNative.asInterface(BinderInternal.getContextObject());

然后我們需要再看一下BinderInternal.getContextObject()和ServiceManagerNative.asInterface兩個方法。

BinderInternal.getContextObject()是一個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); }

而ServiceManagerNative.asInterface的實現和其他的Binder服務是一樣的套路:

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

先通過queryLocalInterface查看能不能獲得本地Binder,如果無法獲取,則創建并返回ServiceManagerProxy對象。

而ServiceManagerProxy自然也是和其他Binder Proxy一樣的實現套路:

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.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);reply.recycle();data.recycle(); }

有了上文的講解,這段代碼應該都是比較容易理解的了。

關于AIDL

作為Binder機制的最后一個部分內容,我們來講解一下開發者經常使用的AIDL機制是怎么回事。

AIDL全稱是Android Interface Definition Language,它是Android SDK提供的一種機制。借助這個機制,應用可以提供跨進程的服務供其他應用使用。AIDL的詳細說明可以參見官方開發文檔:https://developer.android.com/guide/components/aidl.html 。

這里,我們就以官方文檔上的例子看來一下AIDL與Binder框架的關系。

開發一個基于AIDL的Service需要三個步驟:

  • 定義一個.aidl文件
  • 實現接口
  • 暴露接口給客戶端使用
  • aidl文件使用Java語言的語法來定義,每個.aidl文件只能包含一個interface,并且要包含interface的所有方法聲明。

    默認情況下,AIDL支持的數據類型包括:

    • 基本數據類型(即int,long,char,boolean等)
    • String
    • CharSequence
    • List(List的元素類型必須是AIDL支持的)
    • Map(Map中的元素必須是AIDL支持的)

    對于AIDL中的接口,可以包含0個或多個參數,可以返回void或一個值。所有非基本類型的參數必須包含一個描述是數據流向的標簽,可能的取值是:in,out或者inout。

    下面是一個aidl文件的示例:

    // IRemoteService.aidl package com.example.android;// Declare any non-default types here with import statements/** Example service interface */ interface IRemoteService {/** Request the process ID of this service, to do evil things with it. */int getPid();/** Demonstrates some basic types that you can use as parameters* and return values in AIDL.*/void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,double aDouble, String aString); }

    這個文件中包含了兩個接口 :

    • getPid 一個無參的接口,返回值類型為int
    • basicTypes,包含了幾個基本類型作為參數的接口,無返回值

    對于包含.aidl文件的工程,Android IDE(以前是Eclipse,現在是Android Studio)在編譯項目的時候,會為aidl文件生成對應的Java文件。

    針對上面這個aidl文件生成的java文件中包含的結構如下圖所示:

    在這個生成的Java文件中,包括了:

    • 一個名稱為IRemoteService的interface,該interface繼承自android.os.IInterface并且包含了我們在aidl文件中聲明的接口方法
    • IRemoteService中包含了一個名稱為Stub的靜態內部類,這個類是一個抽象類,它繼承自android.os.Binder并且實現了IRemoteService接口。這個類中包含了一個onTransact方法
    • Stub內部又包含了一個名稱為Proxy的靜態內部類,Proxy類同樣實現了IRemoteService接口

    仔細看一下Stub類和Proxy兩個中包含的方法,是不是覺得很熟悉?是的,這里和前面介紹的服務實現是一樣的模式。這里我們列一下各層類的對應關系:

    C++Java層AIDL
    BpXXXXXXProxyIXXX.Stub.Proxy
    BnXXXXXXNativeIXXX.Stub

    為了整個結構的完整性,最后我們還是來看一下生成的Stub和Proxy類中的實現邏輯。

    Stub是提供給開發者實現業務的父類,而Proxy的實現了對外提供的接口。Stub和Proxy兩個類都有一個asBinder的方法。

    Stub類中的asBinder實現就是返回自身對象:

    @Override public android.os.IBinder asBinder() {return this; }

    而Proxy中asBinder的實現是返回構造函數中獲取的mRemote對象,相關代碼如下:

    private android.os.IBinder mRemote;Proxy(android.os.IBinder remote) {mRemote = remote; }@Override public android.os.IBinder asBinder() {return mRemote; }

    而這里的mRemote對象其實就是遠程服務在當前進程的標識。

    上文我們說了,Stub類是用來提供給開發者實現業務邏輯的父類,開發者者繼承自Stub然后完成自己的業務邏輯實現,例如這樣:

    private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {public int getPid(){return Process.myPid();}public void basicTypes(int anInt, long aLong, boolean aBoolean,float aFloat, double aDouble, String aString) {// Does something} };

    而這個Proxy類,就是用來給調用者使用的對外接口。我們可以看一下Proxy中的接口到底是如何實現的:

    Proxy中getPid方法實現如下所示:

    @Override public int getPid() throws android.os.RemoteException {android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();int _result;try {_data.writeInterfaceToken(DESCRIPTOR);mRemote.transact(Stub.TRANSACTION_getPid, _data, _reply, 0);_reply.readException();_result = _reply.readInt();} finally {_reply.recycle();_data.recycle();}return _result; }

    這里就是通過Parcel對象以及transact調用對應遠程服務的接口。而在Stub類中,生成的onTransact方法對應的處理了這里的請求:

    @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)throws android.os.RemoteException {switch (code) {case INTERFACE_TRANSACTION: {reply.writeString(DESCRIPTOR);return true;}case TRANSACTION_getPid: {data.enforceInterface(DESCRIPTOR);int _result = this.getPid();reply.writeNoException();reply.writeInt(_result);return true;}case TRANSACTION_basicTypes: {data.enforceInterface(DESCRIPTOR);int _arg0;_arg0 = data.readInt();long _arg1;_arg1 = data.readLong();boolean _arg2;_arg2 = (0 != data.readInt());float _arg3;_arg3 = data.readFloat();double _arg4;_arg4 = data.readDouble();java.lang.String _arg5;_arg5 = data.readString();this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5);reply.writeNoException();return true;}}return super.onTransact(code, data, reply, flags); }

    onTransact所要做的就是:

  • 根據code區分請求的是哪個接口
  • 通過data來獲取請求的參數
  • 調用由子類實現的抽象方法
  • 有了前文的講解,對于這部分內容應當不難理解了。

    到這里,我們終于講解完Binder了。

    恭喜你,已經掌握了Android系統最復雜的模塊,的其中之一了 :)

    – 以上 –

    參考資料和推薦讀物

    • Android Binder
    • Android Interface Definition Language
    • Android Bander設計與實現 - 設計篇
    • Binder系列—開篇
    • 徹底理解Android Binder通信架構
    • binder驅動——-之內存映射篇
    • Android Binder機制(一) Binder的設計和框架

    • Android Binder 分析——內存管理

    原文:?http://qiangbo.space/2017-03-15/AndroidAnatomy_Binder_Java/

    總結

    以上是生活随笔為你收集整理的理解Android Binder机制(3/3):Java层的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。