- Binder在java層的實作其實是對native層的封裝(Binder.java中一堆的native方法),是以主要分析的應該是native層.
- android_util_Binder.cpp:
- 對于java層的native方法在這裡進行了register,已和c/c++層對應起來:
- 構造一個JNINativeMethod數組,裡面存儲了Binder的java方法和cpp方法的映射:
{ “getCallingPid”, “()I”, (void*)android_os_Binder_getCallingPid }……..
- 上面這些方法都是在Binder.java中定義的native方法.
- 映射到的native層的方法都在該.cpp内,但是也隻是對IPCThreadState::self()相應方法的轉發,一個簡單的封裝.
- Method映射的調用步驟:
- AndroidRuntime::start(…)->startReg(env)
- startReg(env) -> register_jni_procs(gRegJNI, NELEM(gRegJNI), env)
- 而 gRegJNI數組中包含了REG_JNI(register_android_os_Binder)
- android_util_Binder中的register_android_os_Binder(…)
- 會調用3個init_register_XXX方法:
- int_register_android_os_Binder
- int_register_android_os_BinderInternal
- int_register_android_os_BinderProxy
- 這三個方法最後都會調AndroidRuntime::registerNativeMethods(…)來将對應的Java層method與native層的函數對應起來.
- 三個method映射數組分别是:
- gBinderMethods[] (Binder.java中的native函數):
- getCallingPid
- getCallingUid
- clearCallingIdentity
- restoreCallingIdentity
- setThreadStrictModePolicy
- getThreadStrictModePolicy
- flushPendingCommands
- init
- destroy
- gBinderInternalMethods[]
- getContextObject
- joinThreadPool
- disableBackgroundScheduling
- handleGc
- gBinderProxyMethods[](BinderProxy.java中的native函數, 這個類也是在Binder.java中定義的,和class Binder一樣是implements了IBinder接口)
- pingBinder
- isBinderAlive
- getInterfaceDescriptor
- transact
- linkToDeath
- unlinkToDeath
- destroy
- gBinderMethods[] (Binder.java中的native函數):
- 構造一個JNINativeMethod數組,裡面存儲了Binder的java方法和cpp方法的映射:
- 對于java層的native方法在這裡進行了register,已和c/c++層對應起來:
- 很多方法都是直接轉交給IPCThreadState->self來調用的:
- IPCThreadState的self() 是static的函數,其實傳回的是一個TLS對象,裡面是該線程自己own的一個IPCThreadState對象,可見IPCThreadState對象基本是每個線程都有自己的一個專屬的, 注意如果已經shutdown(gShutdown), 那麼會傳回null. 如果目前線程的TLS還沒有對應的IPCThreadState,那麼就會new一個,注意,在IPCThreadState的構造函數中,會将自己放入到所線上程的TLS中(pthread_setspecific(gTLS, this)).
- IPCThreadState的shutdown函數也是一個static的函數,會将gShutdown設為true,但是隻會将自己線程的TLS先null,其他線程的則需要等待被使用過後的釋放.
- 在Java層使用時,一般隻有Binder類顯山露水,但是其實BinderProxy也是被使用的,隻不過通過一個IBinder的引用來使用的,是以看不到。
- Parcel的nativeReadStrongBinder最後被綁定到native層的android_os_Parcel_readStrongBinder上(android_os_Parcel.cpp).
- 進一步調用了android_util_binder的javaObjectForIBinder(JNIEnv* env, const sp& val)
- 在這個函數裡可以發現最重要的一部: object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);, gBinderProxyOffsets.mClass是在哪裡指派呢? 就是在int_register_android_os_BinderProxy這個綁定java層BinderProxy的函數裡,相應指派語句是gBinderProxyOffsets.mClass = (jclass) env->NewGlobalRef(clazz);,這裡的clazz就是clazz = env->FindClass(kBinderProxyPathName, 就是“android/os/BinderProxy”);
- 這裡就是很清晰了,本地通過在Parcel裡填充一個Binder對象并發給遠端來實作通信,遠端通過Parcel的readStrongBinder得到的其實是一個遠端本地new出來的BindProxy對象, 而這個BindProxy對象又和本地的Binder對象可以通信(transact/onTranscat).
- 從上面可以看出,在遠端通過Parcel的readStrongBinder得到一個IBinder對象用來向本地transact資料時,這個IBinder對象其實就是一個遠端本地的BinderProxy對象.
- 那麼通過transact發送資料其實調用的就是BinderProxy的transact:
- 這個函數也是native實作的: android_os_BinderProxy_transact
- 這個函數中最終調用的是target->transact(…)
- 而target其實是(IBinder*) env->GetIntField(obj, gBinderProxyOffsets.mObject) 拿到的.
- gBinderProxyOffsets.mObject其實也是在int_register_android_os_BinderProxy中初始化的,對應的是Java層BinderProxy的mObject對象成員(一個int型,因為其實儲存的是native層的一個對象).
- 也就是說target其實是BinderProxy中的mObject,而且這個對象是int型的,其實就是native層一個IBinder對象的指針位址, 最終的transact其實還是在native層發生的: target->transact(code, *data, reply, flags).
- 那麼這個target是什麼時候被設定的呢?就是上面說的在readStrongBinder調用的javaObjectForIBinder中,javaObjectForIBinder有一個輸入參數是const sp& val, 這個值會被塞進new出來的BinderProxy的mObject中.
- 進一步這個val值在Pacel.cpp中是通過readStrongBinder()->unflatten_binder(ProcessState::self(), *this, &val(被賦結果值))。
- unflatten_binder和flatten_binder類似與反序列化和序列化. writeStrongBinder對應的就是flatten_binder(ProcessState::self(), val, this).
- 在android_os_BinderProxy_transact中調用的target其實是一個BpBinder,而不是BBinder
- BpBinder中的transact函數調用的就是IPCThreadState::self()->transact(mHandle int32_t,知道和誰通信的關鍵, code, data, reply, flags), mHandler是在構造時就初始化了. 而BpBinder的new也隻在ProcessState的getStrongProxyForHandle(handle)/getWeakProxyForHandle(int32_t handle)被調用. 如果Bpbinder不是alive的,那麼會傳回DEAD_OBJECT.
- 繼續跟蹤IPCThreadState的transact(…) -> writeTransactionData(…), 同時如果不是ONE_WAY的話,還需要等待response(waitForResponse(…)).
- writeTransactionData: 将handle/code等資訊填充到一個binder_transaction_data對象,注意這裡的cmd是BC_TRANSACTION表示是一個Transaction而不是reply(BC_REPLY), 将cmd和binder_transaction_data對象寫入到mOut中(private Parcel是一個對象而非指針不需要再new來建構).
- IPCThreadState的構造函數接受一個關鍵值作為自己的mProcess: ProcessState::self(), 而後者傳回的是一個ProcessState全局單例對象, 可以認為每個程序隻有一個,并且是lazy-init的.
- 那麼就要跟蹤到ProcessState的構造函數了,看着好像啥都沒幹,其實有一個很重要的點是在初始化清單裡面調用的:mDriverFD(open_driver()).
- ProcessState::open_driver()是一個static函數,其操作是打開了“/dev/binder”這個驅動層的虛拟裝置檔案, 并且設定了BINDER的version和binder的max thread數量.然會傳回打開的裝置檔案的fd儲存在自己的mDriverFD中.
- ProcessState的初始化一般都會在Service init的時候就被調用,并且會調用其startThreadPool()來生成線程池 -> spawnPooledThread(…)可以看到new了一個PoolThread,而該PoolThread的操作則是: IPCThreadState::self()->joinThreadPool(mIsMain)調用目前線程的joinThreadPool(…), 會傳入一個isMain參數來标示是否是主線程, 在哪個線程上調用了ProcessState的spawnPooledThread,就會啟動一個線程,将這個線程上的IPCThreadState對象進行joinThreadPool. PooledThread繼承自Thread(Threads.cpp中定義),這個類通過在run()中調用androidCreateRawThreadEtc建立了一個Thread(pthread_create), 這個線程運作的函數則是 内部定義的 _threadLoop,_threadLoop裡面有一個doWhile循環不斷的調用Thread對象的threadLoop函數(PooledThread就是在override了,調用了IPCThreadState的joinThreadPool())
- IPCThreadState的joinThreadPool本質就是一個do while循環,隻有在ECONNREFUSED/EBADF/TIMED_OUT/不是主線程時才會break. 循環裡面調用的是IPCThreadState::getAndExecuteCommand().
- getAndExecuteCommand()裡面的重要操作是talkWithDriver()和executeCommand(cmd).
- talkWithDriver(…)裡沒有顯式的IO函數調用,因為用的是驅動層自定義的ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr), 裡面的bwr是一個binder_write_read對象,即包含了要write的資料,也包含了要read資料的存放地,一次操作,一個do while不斷的調用這個過程,遇到EINTR也會繼續,直到遇上了其他錯誤,在這一次循環結束以後,會将mOut中發送出去的資料清除,将read到的資料填充到mIn中
- executeCommand(int32_t cmd)就簡單了,根據上面得到mIn的資料進行操作并寫将回應寫回到mOut中.
- 不過寫出去的資料是如何送到對端之類的實作,還需要看binder驅動層的實作.