By 高煥堂(台北)、桂立華(上海)
2009.7.31
AMS是ActivityManagerService之簡稱。當你從Activity呼叫bindService()時候,會轉而呼叫AMS::bindService()函數。此AMS::bindService()再呼叫AMS::requestServiceBindingLocked()函數。此AMS::requestServiceBindingLocked()再呼叫ActivityThread::scheduleBindService()函數。
ActivityThread::scheduleBindService()函數的動作包括:
*********************** *************************
依據Acivity呼叫bindService(參數)時候的參數內容(如data.token),而從HashMap<IBinder, Service >:mServices裡找出目的Service。如下指令:
Service s = mServices.get(data.token);
接著呼叫:
data.intent.setExtrasClassLoader(s.getClassLoader());
IBinder binder = s.onBind(data.intent);
將data的intent(來自Acivity呼叫bindService(參數)的intent)傳給onBind(),
執行了onBind()函數,就回傳myBinder物件了。
*********************** *************************
取得myBinder物件之後;接著,AMP.publishService(data.token, data.intent, binder);呼叫JNI Native函數:android_os_Parcel_writeStrongBinder()
執行其內的:parcel->writeStrongBinder( ibinderForJavaObject(env, object));
其中,ibinderForJavaObject()取得與myBinder物件相對的JavaBBinderHolder物件。然後,env->IsInstanceOf(obj, gBinderOffsets.mClass)判斷是不是myBinder的物件。此時是True! 於是,執行:env->GetIntField(obj, gBinderOffsets.mObject);就從myBinder::mObject欄位取得JavaBBinderHolder物件參考。如下圖:
接著,呼叫JavaBBinderHolder的get()函數來創建 javaBBinder物件:
此get()函數的動作:
---- 執行new JavaBBinder(env, mObject); 來誕生JavaBBinder 物件。
---- 此時,傳入的mObject 是先前JavaBBinderHolder建立時所存入的
mObject值,它是myBinder物件參考。
---- mObject(env->NewGlobalRef(object)) 也將myBinder物件參考存入於
javaBBinder物件的mObject變數裡。如下圖:
*********************** *************************
** 建立了右邊的橋墩(即JavaBBinder物件)之後,也必須建立左邊的橋墩。Android的Binder System可以幫忙建立左邊的橋墩:BpBinder物件。如何建立呢?
其過程如下:
繼續執行:parcel->writeStrongBinder( ibinderForJavaObject(env, object));
在這時把 javaBBinder 寫入了 flat_binder_object 這個結構裏
ActivityManagerNative::publishService() --->Parcel::readStrongBinder()去讀取 flat_binder_object 這個結構,也就得到BpBinder of JavaBBinder了。讀取後呼叫 javaObjectForIBinder()函數來誕生BinderProxy物件。並且,將BindProxy物件的mObject欄位ID存入Native公用變數gBinderProxyOffsets.mObject裡。還將BpBinder物件的參考存入BinderProxy物件的mObject欄位裡。如下圖:
以上說明了AMS如何呼叫Service::onBind()函數,並敘述呼叫onBind()函數之後的有關動作