android servicemanager與binder源碼分析二 ------ servicemanager服務提供者

承接上篇,serviceManager是怎麼被調用的呢?如何爲app提供服務支持?怎麼銜接的?。此次我打算從最上層開始逐步把脈絡屢清楚。
首先,咱們在寫app的時候須要使用AudioManager這類東西的時候,都要調用context.getSystemService(Context.AUDIO_SERVICE);獲取服務。逐層看下代碼:java

a.activity的getSystemService:android

@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這裏就作了處理返回了,不然調用super的同名方法。
b.ContextThemeWrapper的getSystemService:windows

@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,在這裏直接返回,不然調用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<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
134            new HashMap<String, ServiceFetcher<?>>();

這麼逐層看來,你請求的內容在每層都分別迴應本身所關心的,若是不關心,交給父類處理,最後會走到SystemServiceRegistry類中,看定義就明白,使用一個hashmap來存儲名字和ServiceFetcher的對應關係。那麼看到這裏大致應該有個瞭解了,SystemServiceRegistry來維護註冊進去的全部服務,固然是其餘層級上不關心的。
也同時能夠看到責任鏈的應用,一個請求從上到下會通過不少層,每層都只處理和本身相關的部分,若是沒有則交由下層繼續傳遞,若是有直接返回。這種模式的使用其實已經在不少年前就很是普遍了,好比tcp/ip的封包和解包過程,好比windows下的層級調用,再好比android的ui event相應等都採用了相似的思想。不要較真兒說這裏是繼承那邊是調用鏈什麼的,我以爲仍是看總體思想爲好,不須要拘泥於具體什麼什麼模式,什麼什麼規則。
再繼續看SystemServiceRegistry這個類,靜態類一個,連構造都隱藏了,但不是單例,直接在static中進行了不少服務的註冊:app

140    static {
141        registerService(Context.ACCESSIBILITY_SERVICE, AccessibilityManager.class,
142                new CachedServiceFetcher<AccessibilityManager>() {
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<CaptioningManager>() {
150            @Override
151            public CaptioningManager createService(ContextImpl ctx) {
152                return new CaptioningManager(ctx);
153            }});
154        ......
707    }

這裏使用了靜態代碼塊static,在類被加載的時候必然會走這裏。
往下看registerService:tcp

732     * Statically registers a system service with the context.
733     * This method must be called during static initialization only.
734     */
735    private static <T> void registerService(String serviceName, Class<T> serviceClass,
736            ServiceFetcher<T> serviceFetcher) {
737        SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
738        SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
739    }

只是向兩個hashmap中填充了名字和class而已。在這裏已經實例化了。
簡單看下ServiceFetcher:ide

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<T> {
746        T getService(ContextImpl ctx);
747    }

只是個包裝interface,根據類型不一樣提供了3種子類供各個服務使用:函數

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 CachedServiceFetcher<T> implements ServiceFetcher<T> {
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<T> implements ServiceFetcher<T> {
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<T> implements ServiceFetcher<T> {
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內部會走到createService(ctx);中,而這個抽象方法是必須被實現的。而後在static代碼塊中註冊服務的時候都要有選擇的去根據這3種類型實現ServiceFetcher,實現createService。那麼不管這個服務是單例非單例,或者在建立的時候須要作什麼事情,均可以在這個createService中來進行。那麼這3類裏面又使用了惰性加載,若是緩存有或者單例有就不用走createService,沒有的時候就走。
回過頭來看,getService最終返回的是一個註冊過的服務的實例化對象。
說了這麼半天,跟servicemanager有什麼關係?其實在於getService的實現上。以AudioManager爲例 /frameworks/base/media/java/android/media/AudioManager.java:fetch

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    }

看到了吧,這裏已經開始對ServiceManager的使用了,而且是經過binder來獲得的。那麼結合以前的分析,ServiceManager是在一個獨立的進程中的,那麼其餘進程要是想經過它拿到Service等操做,就須要藉助Binder這個跨進程的通信方式。再往下看:
/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 <code>null</code> 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    }

單例,而後調用到ServiceManagerNative.asInterface,繼續看:
/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        ArrayList<String> services = new ArrayList<String>();
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}

至此,已經開始進入binder的跨進程部分,能夠看到其中的getService函數是怎麼運做的:
1.創建2個Parcel數據data和reply,一個是入口數據,一個是出口數據;
2.data中寫入要獲取的service的name;
3.關鍵:走mRemote的transact函數;
4.讀取出口數據;
5.回收資源,返回讀取到的binder對象;

夠暈吧,這一通調用,可是這部分沒辦法,實在很差層級總結,只能是一口氣跟着調用走下來,而後回過頭再看。上面那麼多步驟的調用都是爲了這最後一步作準備,那麼爲何要分爲這麼多層次呢?任何一個操做系統都是很是複雜的,每一個地方都要考慮到不少的擴展性及健壯性,隨時能夠在某個版本或補丁上去除或擴展出一些內容來。也爲了利於多人協做,那麼分層的調用可以保證在每個層級上都有可擴展的餘地,再進行修改的時候不至於要動不少代碼,動的越少就越不容易出錯。所以雖然看着費勁點,可是在此仍是要對搞操做系統的以及研究操做系統的人們給予敬意。

最後總結一下,這篇主要說的是從應用層開始與servicemanager銜接的過程,是怎麼將servicemanager應用起來的。寫這篇的緣由也是發現網上這部分的銜接的資料較少,我以爲梳理一下仍是有助於理解系統的機制的,難點並很少,只是幫助理解系統的機制,做爲參考吧。順便再說下,若是你的興趣在於底層,那麼不看此文也罷,不過個人建議是不只要了解各個環節的運做機制,還要在一個更高的角度去看待每一個環節的銜接過程,不然可能你費勁心血在底層作了各類優化後發現效率仍是上不來,那麼每每問題出在銜接過程。固然這麼龐大複雜的系統不多是一我的寫的,每一個人的能力也各有差異,瓶頸總會有的,可是若是你站的夠高,那麼架構的角度去理解每一個細節及銜接,就可以找出問題所在。不是嗎?總之都是我的愚見而已,各位海涵。

下面該說binder的遠程通信機制內部的內容了,下一篇文我會繼續的。

相關文章
相關標籤/搜索