摘要:也同時可以看到責(zé)任鏈的應(yīng)用,一個請求從上到下會經(jīng)過很多層,每層都只處理和自己相關(guān)的部分,如果沒有則交由下層繼續(xù)傳遞,如果有直接返回。因此雖然看著費勁點,但是在此還是要對搞操作系統(tǒng)的以及研究操作系統(tǒng)的人們給予敬意。
承接上篇,serviceManager是怎么被調(diào)用的呢?如何為app提供服務(wù)支持?怎么銜接的?。這次我打算從最上層開始逐步把脈絡(luò)屢清楚。
首先,我們在寫app的時候需要使用AudioManager這類東西的時候,都要調(diào)用context.getSystemService(Context.AUDIO_SERVICE);獲取服務(wù)。逐層看下代碼:
a.activity的getSystemService:
@Override public Object getSystemService(String name) { if (getBaseContext() == null) { throw new IllegalStateException( "System services not available to Activities before onCreate()"); } if (WINDOW_SERVICE.equals(name)) { return mWindowManager; } else if (SEARCH_SERVICE.equals(name)) { ensureSearchManager(); return mSearchManager; } return super.getSystemService(name); }
如果是WINDOW_SERVICE或者SEARCH_SERVICE,直接在activity這里就做了處理返回了,否則調(diào)用super的同名方法。
b.ContextThemeWrapper的getSystemService:
@Override public Object getSystemService(String name) { if (LAYOUT_INFLATER_SERVICE.equals(name)) { if (mInflater == null) { mInflater = LayoutInflater.from(mBase).cloneInContext(this); } return mInflater; } return mBase.getSystemService(name); }
如果是LAYOUT_INFLATER_SERVICE,在這里直接返回,否則調(diào)用mBase的同名方法。
mBase是Context類型,那么其實就是ContextImpl。看下:
1363 @Override 1364 public Object getSystemService(String name) { 1365 return SystemServiceRegistry.getSystemService(this, name); 1366 }
SystemServiceRegistry.java:
716 /** 717 * Gets a system service from a given context. 718 */ 719 public static Object getSystemService(ContextImpl ctx, String name) { 720 ServiceFetcher> fetcher = SYSTEM_SERVICE_FETCHERS.get(name); 721 return fetcher != null ? fetcher.getService(ctx) : null; 722 }
133 private static final HashMap> SYSTEM_SERVICE_FETCHERS = 134 new HashMap >();
這么逐層看來,你請求的內(nèi)容在每層都分別回應(yīng)自己所關(guān)心的,如果不關(guān)心,交給父類處理,最后會走到SystemServiceRegistry類中,看定義就明白,使用一個hashmap來存儲名字和ServiceFetcher的對應(yīng)關(guān)系。那么看到這里大體應(yīng)該有個了解了,SystemServiceRegistry來維護(hù)注冊進(jìn)去的所有服務(wù),當(dāng)然是其他層級上不關(guān)心的。
也同時可以看到責(zé)任鏈的應(yīng)用,一個請求從上到下會經(jīng)過很多層,每層都只處理和自己相關(guān)的部分,如果沒有則交由下層繼續(xù)傳遞,如果有直接返回。這種模式的使用其實已經(jīng)在很多年前就非常廣泛了,比如tcp/ip的封包和解包過程,比如windows下的層級調(diào)用,再比如android的ui event相應(yīng)等都采用了類似的思想。不要較真兒說這里是繼承那邊是調(diào)用鏈?zhǔn)裁吹?,我覺得還是看整體思想為好,不需要拘泥于具體什么什么模式,什么什么規(guī)則。
再繼續(xù)看SystemServiceRegistry這個類,靜態(tài)類一個,連構(gòu)造都隱藏了,但不是單例,直接在static中進(jìn)行了很多服務(wù)的注冊:
140 static { 141 registerService(Context.ACCESSIBILITY_SERVICE, AccessibilityManager.class, 142 new CachedServiceFetcher() { 143 @Override 144 public AccessibilityManager createService(ContextImpl ctx) { 145 return AccessibilityManager.getInstance(ctx); 146 }}); 147 148 registerService(Context.CAPTIONING_SERVICE, CaptioningManager.class, 149 new CachedServiceFetcher () { 150 @Override 151 public CaptioningManager createService(ContextImpl ctx) { 152 return new CaptioningManager(ctx); 153 }}); 154 ...... 707 }
這里使用了靜態(tài)代碼塊static,在類被加載的時候必然會走這里。
往下看registerService:
732 * Statically registers a system service with the context. 733 * This method must be called during static initialization only. 734 */ 735 private staticvoid registerService(String serviceName, Class serviceClass, 736 ServiceFetcher serviceFetcher) { 737 SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName); 738 SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher); 739 }
只是向兩個hashmap中填充了名字和class而已。在這里已經(jīng)實例化了。
簡單看下ServiceFetcher:
741 /** 742 * Base interface for classes that fetch services. 743 * These objects must only be created during static initialization. 744 */ 745 static abstract interface ServiceFetcher{ 746 T getService(ContextImpl ctx); 747 }
只是個包裝interface,根據(jù)類型不同提供了3種子類供各個服務(wù)使用:
749 /** 750 * Override this class when the system service constructor needs a 751 * ContextImpl and should be cached and retained by that context. 752 */ 753 static abstract class CachedServiceFetcherimplements ServiceFetcher { 754 private final int mCacheIndex; 755 756 public CachedServiceFetcher() { 757 mCacheIndex = sServiceCacheSize++; 758 } 759 760 @Override 761 @SuppressWarnings("unchecked") 762 public final T getService(ContextImpl ctx) { 763 final Object[] cache = ctx.mServiceCache; 764 synchronized (cache) { 765 // Fetch or create the service. 766 Object service = cache[mCacheIndex]; 767 if (service == null) { 768 service = createService(ctx); 769 cache[mCacheIndex] = service; 770 } 771 return (T)service; 772 } 773 } 774 775 public abstract T createService(ContextImpl ctx); 776 } 777 778 /** 779 * Override this class when the system service does not need a ContextImpl 780 * and should be cached and retained process-wide. 781 */ 782 static abstract class StaticServiceFetcher implements ServiceFetcher { 783 private T mCachedInstance; 784 785 @Override 786 public final T getService(ContextImpl unused) { 787 synchronized (StaticServiceFetcher.this) { 788 if (mCachedInstance == null) { 789 mCachedInstance = createService(); 790 } 791 return mCachedInstance; 792 } 793 } 794 795 public abstract T createService(); 796 } 797 798 /** 799 * Like StaticServiceFetcher, creates only one instance of the service per process, but when 800 * creating the service for the first time, passes it the outer context of the creating 801 * component. 802 * 803 * TODO: Is this safe in the case where multiple applications share the same process? 804 * TODO: Delete this once its only user (ConnectivityManager) is known to work well in the 805 * case where multiple application components each have their own ConnectivityManager object. 806 */ 807 static abstract class StaticOuterContextServiceFetcher implements ServiceFetcher { 808 private T mCachedInstance; 809 810 @Override 811 public final T getService(ContextImpl ctx) { 812 synchronized (StaticOuterContextServiceFetcher.this) { 813 if (mCachedInstance == null) { 814 mCachedInstance = createService(ctx.getOuterContext()); 815 } 816 return mCachedInstance; 817 } 818 } 819 820 public abstract T createService(Context applicationContext); 821 } 822 823}
暫時不深究到底這3種是什么用途,不過都可看到getService內(nèi)部會走到createService(ctx);中,而這個抽象方法是必須被實現(xiàn)的。然后在static代碼塊中注冊服務(wù)的時候都要有選擇的去根據(jù)這3種類型實現(xiàn)ServiceFetcher,實現(xiàn)createService。那么無論這個服務(wù)是單例非單例,或者在創(chuàng)建的時候需要做什么事情,都可以在這個createService中來進(jìn)行。那么這3類里面又使用了惰性加載,如果緩存有或者單例有就不用走createService,沒有的時候就走。
回過頭來看,getService最終返回的是一個注冊過的服務(wù)的實例化對象。
說了這么半天,跟servicemanager有什么關(guān)系?其實在于getService的實現(xiàn)上。以AudioManager為例 /frameworks/base/media/java/android/media/AudioManager.java:
655 private static IAudioService getService() 656 { 657 if (sService != null) { 658 return sService; 659 } 660 IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE); 661 sService = IAudioService.Stub.asInterface(b); 662 return sService; 663 }
看到了吧,這里已經(jīng)開始對ServiceManager的使用了,并且是通過binder來得到的。那么結(jié)合之前的分析,ServiceManager是在一個獨立的進(jìn)程中的,那么其他進(jìn)程要是想通過它拿到Service等操作,就需要借助Binder這個跨進(jìn)程的通訊方式。再往下看:
/frameworks/base/core/java/android/os/ServiceManager.java:
43 /**
44 * Returns a reference to a service with the given name.
45 *
46 * @param name the name of the service to get
47 * @return a reference to the service, or null
if the service doesn"t exist
48 */
49 public static IBinder getService(String name) {
50 try {
51 IBinder service = sCache.get(name);
52 if (service != null) {
53 return service;
54 } else {
55 return getIServiceManager().getService(name);
56 }
57 } catch (RemoteException e) {
58 Log.e(TAG, "error in getService", e);
59 }
60 return null;
61 }
簡單說:先從緩存中拿,如果沒有通過getIServiceManager()去拿,看getIServiceManager:
33 private static IServiceManager getIServiceManager() { 34 if (sServiceManager != null) { 35 return sServiceManager; 36 } 37 38 // Find the service manager 39 sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject()); 40 return sServiceManager; 41 }
單例,然后調(diào)用到ServiceManagerNative.asInterface,繼續(xù)看:
/frameworks/base/core/java/android/os/ServiceManagerNative.java:
33 static public IServiceManager asInterface(IBinder obj) 34 { 35 if (obj == null) { 36 return null; 37 } 38 IServiceManager in = 39 (IServiceManager)obj.queryLocalInterface(descriptor); 40 if (in != null) { 41 return in; 42 } 43 44 return new ServiceManagerProxy(obj); 45 }
通過IBinder對象去查詢本地接口,如果沒查到需要幫助,就建立一個ServiceManagerProxy。這個代理對象是這樣的:
109class ServiceManagerProxy implements IServiceManager { 110 public ServiceManagerProxy(IBinder remote) { 111 mRemote = remote; 112 } 113 114 public IBinder asBinder() { 115 return mRemote; 116 } 117 118 public IBinder getService(String name) throws RemoteException { 119 Parcel data = Parcel.obtain(); 120 Parcel reply = Parcel.obtain(); 121 data.writeInterfaceToken(IServiceManager.descriptor); 122 data.writeString(name); 123 mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0); 124 IBinder binder = reply.readStrongBinder(); 125 reply.recycle(); 126 data.recycle(); 127 return binder; 128 } 129 130 public IBinder checkService(String name) throws RemoteException { 131 Parcel data = Parcel.obtain(); 132 Parcel reply = Parcel.obtain(); 133 data.writeInterfaceToken(IServiceManager.descriptor); 134 data.writeString(name); 135 mRemote.transact(CHECK_SERVICE_TRANSACTION, data, reply, 0); 136 IBinder binder = reply.readStrongBinder(); 137 reply.recycle(); 138 data.recycle(); 139 return binder; 140 } 141 142 public void addService(String name, IBinder service, boolean allowIsolated) 143 throws RemoteException { 144 Parcel data = Parcel.obtain(); 145 Parcel reply = Parcel.obtain(); 146 data.writeInterfaceToken(IServiceManager.descriptor); 147 data.writeString(name); 148 data.writeStrongBinder(service); 149 data.writeInt(allowIsolated ? 1 : 0); 150 mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0); 151 reply.recycle(); 152 data.recycle(); 153 } 154 155 public String[] listServices() throws RemoteException { 156 ArrayListservices = new ArrayList (); 157 int n = 0; 158 while (true) { 159 Parcel data = Parcel.obtain(); 160 Parcel reply = Parcel.obtain(); 161 data.writeInterfaceToken(IServiceManager.descriptor); 162 data.writeInt(n); 163 n++; 164 try { 165 boolean res = mRemote.transact(LIST_SERVICES_TRANSACTION, data, reply, 0); 166 if (!res) { 167 break; 168 } 169 } catch (RuntimeException e) { 170 // The result code that is returned by the C++ code can 171 // cause the call to throw an exception back instead of 172 // returning a nice result... so eat it here and go on. 173 break; 174 } 175 services.add(reply.readString()); 176 reply.recycle(); 177 data.recycle(); 178 } 179 String[] array = new String[services.size()]; 180 services.toArray(array); 181 return array; 182 } 183 184 public void setPermissionController(IPermissionController controller) 185 throws RemoteException { 186 Parcel data = Parcel.obtain(); 187 Parcel reply = Parcel.obtain(); 188 data.writeInterfaceToken(IServiceManager.descriptor); 189 data.writeStrongBinder(controller.asBinder()); 190 mRemote.transact(SET_PERMISSION_CONTROLLER_TRANSACTION, data, reply, 0); 191 reply.recycle(); 192 data.recycle(); 193 } 194 195 private IBinder mRemote; 196}
至此,已經(jīng)開始進(jìn)入binder的跨進(jìn)程部分,可以看到其中的getService函數(shù)是怎么運作的:
1.建立2個Parcel數(shù)據(jù)data和reply,一個是入口數(shù)據(jù),一個是出口數(shù)據(jù);
2.data中寫入要獲取的service的name;
3.關(guān)鍵:走mRemote的transact函數(shù);
4.讀取出口數(shù)據(jù);
5.回收資源,返回讀取到的binder對象;
夠暈吧,這一通調(diào)用,但是這部分沒辦法,實在不好層級總結(jié),只能是一口氣跟著調(diào)用走下來,然后回過頭再看。上面那么多步驟的調(diào)用都是為了這最后一步做準(zhǔn)備,那么為什么要分為這么多層次呢?任何一個操作系統(tǒng)都是非常復(fù)雜的,每個地方都要考慮到很多的擴展性及健壯性,隨時可以在某個版本或補丁上去除或擴展出一些內(nèi)容來。也為了利于多人協(xié)作,那么分層的調(diào)用能夠保證在每一個層級上都有可擴展的余地,再進(jìn)行修改的時候不至于要動很多代碼,動的越少就越不容易出錯。因此雖然看著費勁點,但是在此還是要對搞操作系統(tǒng)的以及研究操作系統(tǒng)的人們給予敬意。
最后總結(jié)一下,這篇主要說的是從應(yīng)用層開始與servicemanager銜接的過程,是怎么將servicemanager應(yīng)用起來的。寫這篇的原因也是發(fā)現(xiàn)網(wǎng)上這部分的銜接的資料較少,我覺得梳理一下還是有助于理解系統(tǒng)的機制的,難點并不多,只是幫助理解系統(tǒng)的機制,作為參考吧。順便再說下,如果你的興趣在于底層,那么不看此文也罷,不過我的建議是不僅要了解各個環(huán)節(jié)的運作機制,還要在一個更高的角度去看待每個環(huán)節(jié)的銜接過程,否則可能你費勁心血在底層做了各種優(yōu)化后發(fā)現(xiàn)效率還是上不來,那么往往問題出在銜接過程。當(dāng)然這么龐大復(fù)雜的系統(tǒng)不可能是一個人寫的,每個人的能力也各有差別,瓶頸總會有的,但是如果你站的夠高,那么架構(gòu)的角度去理解每個細(xì)節(jié)及銜接,就能夠找出問題所在。不是嗎?總之都是個人愚見而已,各位海涵。
下面該說binder的遠(yuǎn)程通訊機制內(nèi)部的內(nèi)容了,下一篇文我會繼續(xù)的。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/65001.html
摘要:抱歉,此文暫時作廢,不會使用的刪除功能。我會在后面重新整理后再繼續(xù)寫下去。是內(nèi)部的一個機制,通過設(shè)備驅(qū)動的協(xié)助能夠起到進(jìn)程間通訊的的作用。這個應(yīng)該是個全局表,統(tǒng)計所有結(jié)構(gòu)。實際上是保存在打開的設(shè)備文件的結(jié)構(gòu)中。目前還未涉及到其他操作,只是。 抱歉,此文暫時作廢,不會使用segmentfault的刪除功能。我會在后面重新整理后再繼續(xù)寫下去。 繼續(xù)上篇的文,這篇打算進(jìn)入到android的內(nèi)...
摘要:以版本源碼為例。源碼位于下打開驅(qū)動設(shè)備,將自己作為的管理者,進(jìn)入循環(huán),作為等待的請求位于首先,建立一個結(jié)構(gòu)體,然后剩下的就是給這個結(jié)構(gòu)體的成員賦值。同屬于這一層,因此我們看看具體內(nèi)容剛才從驅(qū)動設(shè)備讀取的的前位取出來作為進(jìn)行判斷處理。 前一陣子在忙項目,沒什么更新,這次開始寫點android源碼內(nèi)部的東西分析下。以6.0.1_r10版本android源碼為例。servicemanager...
摘要:的構(gòu)造傳遞進(jìn)入的就是。如果狀態(tài)是,直接返回。到底是否正確呢看代碼先創(chuàng)建一個對象,這個對象是個存儲讀寫內(nèi)容的對象。然后終于進(jìn)入了內(nèi)核驅(qū)動的部分。 承接上文,從getService開始,要開始走binder的通訊機制了。首先是上文的java層 /frameworks/base/core/java/android/os/ServiceManagerNative.java: 118 pu...
閱讀 1165·2021-11-25 09:43
閱讀 2976·2019-08-30 15:54
閱讀 3363·2019-08-30 15:54
閱讀 3010·2019-08-30 15:44
閱讀 1636·2019-08-26 12:18
閱讀 2266·2019-08-26 11:42
閱讀 887·2019-08-26 11:35
閱讀 3306·2019-08-23 18:22