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