getSystemService過程

context.getSystemService()? ->contextImpl.getSystemService ->?SystemServiceRegistry.getSystemService

SystemServiceRegistry.put在static代碼塊注冊(cè)系統(tǒng)服務(wù)

registerService(Context.CLIPBOARD_SERVICE, ClipboardManager.class,

? ? ? ? new CachedServiceFetcher<ClipboardManager>() {

? ? @Override

? ? public ClipboardManager createService(ContextImpl ctx) throws ServiceNotFoundException {

? ? ? ? return new ClipboardManager(ctx.getOuterContext(),

? ? ? ? ? ? ? ? ctx.mMainThread.getHandler());

? ? }});

static abstract interface ServiceFetcher<T> {

? ? T getService(ContextImpl ctx);

}

泛型設(shè)定返回的系統(tǒng)服務(wù)類型,函數(shù)參數(shù)代表著具體的某一個(gè)實(shí)例去獲取

fetcher.getService(ctx)

ServiceManager.getSystemService()

ClipboardManager內(nèi)部含有一個(gè)

IClipboard mService = IClipboard.Stub.asInterface(

? ? ? ? ServiceManager.getServiceOrThrow(Context.CLIPBOARD_SERVICE));



第一步:ServiceManager.getService(name)

ServiceManager在每個(gè)進(jìn)程里都存在

而方法,則是從sCache中獲取, sCache中保存著所有的系統(tǒng)服務(wù)。

這里不得不提一下IBinder的作用:

內(nèi)部標(biāo)識(shí)這個(gè)服務(wù)是遠(yuǎn)程的還是本地的,通過queryLocalInterface(DESCIPTOR),如果能拿到Interface的就是本地的,拿不到就是遠(yuǎn)程的

提供transact和ontransact方法來做跨進(jìn)程調(diào)用方法

Binder的其他實(shí)現(xiàn)是Binder驅(qū)動(dòng)來做的

public static IBinder getService(String name) {

? ? ? ? try {

? ? ? ? ? ? IBinder service = sCache.get(name);

? ? ? ? ? ? if (service != null) {

? ? ? ? ? ? ? ? return service;

? ? ? ? ? ? } else {

? ? ? ? ? ? ? ? return Binder.allowBlocking(rawGetService(name));

? ? ? ? ? ? }

? ? ? ? } catch (RemoteException e) {

? ? ? ? ? ? Log.e(TAG, "error in getService", e);

? ? ? ? }

? ? ? ? return null;

? ? }



第二步:IClipboard.Stub.asInterface(IBinder)

這里就是通過拿到了系統(tǒng)服務(wù)IBinder,再通過IClipboard.Stub.asInterface的轉(zhuǎn)化。

obj.queryLocalInterface:查詢是否在本地。否則返回代理對(duì)象

所以最終走的的是new Stub.Proxy(object),返回了一個(gè)代理對(duì)象

我想過如果obj直接強(qiáng)制類型轉(zhuǎn)換會(huì)怎么樣?

如果是本進(jìn)程應(yīng)該OK,但是如果是其他進(jìn)程應(yīng)該會(huì)返回null,因?yàn)檫@個(gè)Ibinder代表的是一個(gè)proxy,也不是實(shí)際的對(duì)象。就算是實(shí)際的對(duì)象,也因?yàn)榇嬖诓煌倪M(jìn)程,內(nèi)存地址不同,導(dǎo)致訪問失敗。所以這里系統(tǒng)做了一下轉(zhuǎn)換

? public static android.content.IClipboard asInterface(android.os.IBinder obj) {

? ? ? ? ? ? if ((obj == null)) {

? ? ? ? ? ? ? ? return null;

? ? ? ? ? ? }

? ? ? ? ? ? android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);

? ? ? ? ? ? if (((iin != null) && (iin instanceof android.content.IClipboard))) {

? ? ? ? ? ? ? ? return ((android.content.IClipboard) iin);

? ? ? ? ? ? }

? ? ? ? ? ? return new android.content.IClipboard.Stub.Proxy(obj);

? ? ? ? }

Proxy對(duì)象和Stub對(duì)象交互

interface IClipboard extends android.os.IInterface

public static abstract class Stub extends android.os.Binder implements android.content.IClipboard

static class Proxy implements android.content.IClipboard

注意觀察這三個(gè)類:

IClipboard接口是繼承是IInterface接口:為了保證IBinder在query后拿到的IIterface接口可以強(qiáng)制類型轉(zhuǎn)換

Stub繼承自Binder,重寫三個(gè)方法:onTransact(用于方法調(diào)用),asInterface(用于查詢是否是本地對(duì)象),asBinder。但是Binder的其他方法并沒有讓重寫,原因在于這個(gè)方法由Binder驅(qū)動(dòng)來實(shí)現(xiàn)

Stub雖然寫了implements android.content.IClipboard,但是實(shí)際內(nèi)部內(nèi)沒有實(shí)現(xiàn)(Stub是一個(gè)抽象類),是為了標(biāo)識(shí)不同的Stub擁有的不同能力

Proxy 實(shí)現(xiàn)Clipboard的方式并不是直接對(duì)象調(diào)用,而是內(nèi)部持有一個(gè)IBinder接口,通過transact方法傳參數(shù)。



transact和onTransact方法調(diào)用

簡單來說,并沒有直接用對(duì)象方法的方式,而是用Parcel包裝數(shù)據(jù),然后把標(biāo)識(shí)符和參數(shù)信息,方法信息傳給遠(yuǎn)端

? ? @Override

? ? ? ? ? ? public int add(int a, int b) 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);

? ? ? ? ? ? ? ? ? ? _data.writeInt(a);

? ? ? ? ? ? ? ? ? ? _data.writeInt(b);

? ? ? ? ? ? ? ? ? ? mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);

? ? ? ? ? ? ? ? ? ? _reply.readException();

? ? ? ? ? ? ? ? ? ? _result = _reply.readInt();

? ? ? ? ? ? ? ? } finally {

? ? ? ? ? ? ? ? ? ? _reply.recycle();

? ? ? ? ? ? ? ? ? ? _data.recycle();

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? return _result;

? ? ? ? ? ? }

? ? ? ? }

3.遠(yuǎn)端呢? 遠(yuǎn)端接受到了這個(gè)數(shù)據(jù)包后,解析,并調(diào)用實(shí)際的this.add()方法,然后調(diào)用reply.write()把返回?cái)?shù)據(jù)寫入

? ? @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_add: {

? ? ? ? ? ? ? ? ? ? data.enforceInterface(DESCRIPTOR);

? ? ? ? ? ? ? ? ? ? int _arg0;

? ? ? ? ? ? ? ? ? ? _arg0 = data.readInt();

? ? ? ? ? ? ? ? ? ? int _arg1;

? ? ? ? ? ? ? ? ? ? _arg1 = data.readInt();

? ? ? ? ? ? ? ? ? ? int _result = this.add(_arg0, _arg1);

? ? ? ? ? ? ? ? ? ? reply.writeNoException();

? ? ? ? ? ? ? ? ? ? reply.writeInt(_result);

? ? ? ? ? ? ? ? ? ? return true;

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? ? ? return super.onTransact(code, data, reply, flags);

? ? ? ? }

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容