前言
這個知識點是Android進階學習必須掌握的知識點之一,也是高階Android架構師經常問到的點。在這裏分想給大家,希望對大家的工作和學習有所幫助。喜歡本文的記得點贊關注哦~
在前面的Android Binder原理(三)系統服務的註冊過程這篇文章中,我介紹的是Native Binder中的系統服務的註冊過程,這一過程的核心是ServiceManager,而在Java Binder中,也有一個ServiceManager,只不過這個ServiceManager是Java文件。
既然要將系統服務註冊到ServiceManager,那麼需要選擇一個系統服務爲例,這裏以常見的AMS爲例。
1.將AMS註冊到ServiceManager
在AMS的setSystemProcess方法中,會調用ServiceManager的addService方法,如下所示。
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public void setSystemProcess() {
try {
ServiceManager.addService(Context.ACTIVITY_SERVICE, this, /* allowIsolated= */ true,
DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PROTO);//1
....
} catch (PackageManager.NameNotFoundException e) {
throw new RuntimeException(
"Unable to find android system package", e);
}
...
}
註釋1處的Context.ACTIVITY_SERVICE
的值爲"activity",作用就是將AMS註冊到ServiceManager中。接着來看
ServiceManager的addService方法。
frameworks/base/core/java/android/os/ServiceManager.java
public static void addService(String name, IBinder service, boolean allowIsolated,
int dumpPriority) {
try {
getIServiceManager().addService(name, service, allowIsolated, dumpPriority);
} catch (RemoteException e) {
Log.e(TAG, "error in addService", e);
}
}
主要分析getIServiceManager方法返回的是什麼,代碼如下所示。
frameworks/base/core/java/android/os/ServiceManager.java
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
sServiceManager = ServiceManagerNative
.asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
return sServiceManager;
}
講到這裏,已經積累了幾個點需要分析,分別是:
- BinderInternal.getContextObject()
- ServiceManagerNative.asInterface()
- getIServiceManager().addService()
現在我們來各個擊破它們。
1.1 BinderInternal.getContextObject()
Binder.allowBlocking的作用是將BinderProxy的sWarnOnBlocking值置爲false。主要來分析BinderInternal.getContextObject()做了什麼,這個方法是一個Native方法,找到它對應的函數:
frameworks/base/core/jni/android_util_Binder.cpp
static const JNINativeMethod gBinderInternalMethods[] = {
{ "getContextObject", "()Landroid/os/IBinder;", (void*)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);//1
return javaObjectForIBinder(env, b);
}
ProcessState::self()的作用是創建ProcessState,註釋1處最終返回的是BpBinder,不理解的可以查看Android Binder原理(二)ServiceManager中的Binder機制這篇文章。
BpBinder是Native Binder中的Client端,這說明Java層的ServiceManager需要Native層的BpBinder,但是這個BpBinder在Java層是無法直接使用,那麼就需要傳入javaObjectForIBinder函數來做處理,其內部會創建一個BinderProxy對象,這樣我們得知 BinderInternal.getContextObject()最終得到的是BinderProxy。
在Android Binder原理(六)Java Binder的初始化這篇文章我們講過,BinderProxy是Java Binder的客戶端的代表。
需要注意的一點是,這個傳入的BpBinder會保存到BinderProxy的成員變量mObject中,後續會再次提到這個點。
1.2 ServiceManagerNative.asInterface()
說到asInterface方法,在Native Binder中也有一個asInterface函數。在Android Binder原理(二)ServiceManager中的Binder機制這篇文章中講過IServiceManager的asInterface函數,它的作用是用BpBinder做爲參數創建BpServiceManager。那麼在Java Binder中的asInterface方法的作用又是什麼?
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);
}
根據1.1小節,我們得知obj的值爲BinderProxy,那麼asInterface方法的作用就是用BinderProxy作爲參數創建ServiceManagerProxy。
BinderProxy和BpBinder分別在Jave Binder和Native Binder作爲客戶端的代表,BpServiceManager通過BpBinder來實現通信,同樣的,ServiceManagerProxy也會將業務的請求交給BinderProxy來處理。
分析到這裏,那麼:
sServiceManager = ServiceManagerNative
.asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
可以理解爲:
sServiceManager = new ServiceManagerProxy(BinderProxy);
}
1.3 getIServiceManager().addService()
根據1.2節的講解,getIServiceManager()返回的是ServiceManagerProxy,ServiceManagerProxy是ServiceManagerNative的內部類,它實現了IServiceManager接口。
來查看ServiceManagerProxy的addService方法,
frameworks/base/core/java/android/os/ServiceManagerNative.java::ServiceManagerProxy
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);
data.writeStrongBinder(service);//1
data.writeInt(allowIsolated ? 1 : 0);
data.writeInt(dumpPriority);
mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);//2
reply.recycle();
data.recycle();
}
註釋1處的data.writeStrongBinder很關鍵,後續會進行分析。這裏又看到了Parcel,它是一個數據包裝器,將請求數據寫入到Parcel類型的對象data中,通過註釋1處的mRemote.transact發送出去,mRemote實際上是BinderProxy,BinderProxy.transact是native函數,實現的函數如下所示。
frameworks/base/core/jni/android_util_Binder.cpp
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{
if (dataObj == NULL) {
jniThrowNullPointerException(env, NULL);
return JNI_FALSE;
}
Parcel* data = parcelForJavaObject(env, dataObj);//1
if (data == NULL) {
return JNI_FALSE;
}
Parcel* reply = parcelForJavaObject(env, replyObj);//2
if (reply == NULL && replyObj != NULL) {
return JNI_FALSE;
}
IBinder* target = getBPNativeData(env, obj)->mObject.get();//3
if (target == NULL) {
jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!");
return JNI_FALSE;
}
...
status_t err = target->transact(code, *data, reply, flags);//4
return JNI_FALSE;
}
註釋1和註釋2處,將Java層的Parcel對象轉化成爲Native層的Parcel對象。在1.1小節中,我們得知BpBinder會保存到BinderProxy的成員變量mObject中,因此在註釋3處,從BinderProxy的成員變量mObject中獲取BpBinder。最終會在註釋4處調用BpBinder的transact函數,向Binder驅動發送數據,可以看出Java Binder是需要Native Binder支持的,最終的目的就是向Binder驅動發送和接收數據。
2.引出JavaBBinder
接着回過頭來分析1.3小節遺留下來的data.writeStrongBinder(service),代碼如下所示。
frameworks/base/core/java/android/os/Parcel.java
public final void writeStrongBinder(IBinder ll) {
nativeWriteStrongBinder(mNativePtr, val);
}
nativeWriteStrongBinder是Native方法,實現的函數爲android_os_Parcel_writeStrongBinder:
frameworks/base/core/jni/android_os_Parcel.cpp
static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) {
const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));//1
if (err != NO_ERROR) {
signalExceptionForError(env, clazz, err);
}
}
}
接着查看註釋1處ibinderForJavaObject函數:
frameworks/base/core/jni/android_util_Binder.cpp
sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
{
if (obj == NULL) return NULL;
if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {//1
JavaBBinderHolder* jbh = (JavaBBinderHolder*)
env->GetLongField(obj, gBinderOffsets.mObject);
return jbh->get(env, obj);//2
}
if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
return getBPNativeData(env, obj)->mObject;
}
ALOGW("ibinderForJavaObject: %p is not a Binder object", obj);
return NULL;
}
註釋2處,如果obj是Java層的BinderProxy類,則返回BpBinder。
註釋1處,如果obj是Java層的Binder類,那麼先獲取JavaBBinderHolder對象,然後在註釋2處調用JavaBBinderHolder的get函數,代碼如下所示。
frameworks/base/core/jni/android_util_Binder.cpp::JavaBBinderHolder
class JavaBBinderHolder
{
public:
sp<JavaBBinder> get(JNIEnv* env, jobject obj)
{
AutoMutex _l(mLock);
sp<JavaBBinder> b = mBinder.promote();//1
if (b == NULL) {
//obj是一個Java層Binder對象
b = new JavaBBinder(env, obj);//2
mBinder = b;
ALOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%" PRId32 "\n",
b.get(), b->getWeakRefs(), obj, b->getWeakRefs()->getWeakCount());
}
return b;
}
sp<JavaBBinder> getExisting()
{
AutoMutex _l(mLock);
return mBinder.promote();
}
private:
Mutex mLock;
wp<JavaBBinder> mBinder;
};
成員變量mBinder是wp<JavaBBinder>
類型的弱引用,在註釋1處得到sp<JavaBBinder>
類型的強引用b,在註釋2處創建JavaBBinder並賦值給b。那麼,JavaBBinderHolder的get函數返回的是JavaBBinder。
data.writeStrongBinder(service)在本文中等價於:
data.writeStrongBinder(new JavaBBinder(env,Binder))。
講到這裏可以得知ServiceManager.addService()傳入的並不是AMS本身,而是JavaBBinder。
3.解析JavaBBinder
接着來分析JavaBBinder,查看它的構造函數:
frameworks/base/core/jni/android_util_Binder.cpp::JavaBBinderHolder::JavaBBinder
class JavaBBinder : public BBinder
{
public:
JavaBBinder(JNIEnv* env, jobject /* Java Binder */ c)
: mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object))
{
ALOGV("Creating JavaBBinder %p\n", this);
gNumLocalRefsCreated.fetch_add(1, std::memory_order_relaxed);
gcIfManyNewRefs(env);
}
...
可以發現JavaBBinder繼承了BBinder,那麼JavaBBinder的作用是什麼呢?當Binder驅動得到客戶端的請求,緊接着會將響應發送給JavaBBinder,這時會調用JavaBBinder的onTransact函數,代碼如下所示。
frameworks/base/core/jni/android_util_Binder.cpp::JavaBBinderHolder::JavaBBinder
virtual status_t onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)
{
JNIEnv* env = javavm_to_jnienv(mVM);
ALOGV("onTransact() on %p calling object %p in env %p vm %p\n", this, mObject, env, 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);//1
...
return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION;
}
在註釋1處會調用Java層Binder的execTransact函數:
frameworks/base/core/java/android/os/Binder.java
private boolean execTransact(int code, long dataObj, long replyObj,
int flags) {
...
try {
if (tracingEnabled) {
Trace.traceBegin(Trace.TRACE_TAG_ALWAYS, getClass().getName() + ":" + code);
}
res = onTransact(code, data, reply, flags);//1
} catch (RemoteException|RuntimeException e) {
...
}
...
return res;
}
關鍵點是註釋1處的onTransact函數,AMS實現了onTransact函數,從而完成業務實現。
從這裏可有看出,JavaBBinder並沒有實現什麼業務,當它接收到請求時,會調用Binder類的execTransact函數,execTransact函數內部又調用了onTransact函數,系統服務會重寫onTransact函數來實現自身的業務功能。
4.Java Binder架構
Binder架構如下圖所示。
Native Binder的部分在此前的文章已經講過,這裏主要來說說Java Binder部分,從圖中可以看到:
1.Binder是服務端的代表,JavaBBinder繼承BBinder,JavaBBinder通過mObject變量指向Binder。
2.BinderProxy是客戶端的代表,ServiceManager的addService等方法會交由ServiceManagerProxy處理。
3.ServiceManagerProxy的成員變量mRemote指向BinderProxy對象,所以ServiceManagerProxy的addService等方法會交由BinderProxy來處理。
4.BinderProxy的成員變量mObject指向BpBinder對象,因此BinderProxy可以通過BpBinder和Binder驅動發送數據。
感謝
《深入理解Android卷二》
《深入理解Android卷三》
http://gityuan.com/2015/11/21/binder-framework/
最後
千里之行始於足下 。
Android學習是一條漫長的道路,我們要學習的東西不僅僅只有表面的 技術,還要深入底層,弄明白下面的 原理,只有這樣,我們才能夠提高自己的競爭力,在當今這個競爭激烈的世界裏立足。
我把自己這段時間整理的Android最重要最熱門的學習方向資料放在了我的GitHub:https://github.com/xieyuliang/Android-P7-(點擊藍色字體可以獲取),裏面還有不同方向的自學編程路線、面試題集合/面經、及系列技術文章等。
資源持續更新中,歡迎大家一起學習和探討。
部分資料截圖展示: