getSystemService() in Android
在之前研究了那么久的bindService()這個API,一直沒搞清楚一個問題:
為什么我看到的基本上都是和AMS相關的代碼,而之前所學到說如果application要和service打交道都是需要通過ServiceManager獲得某個service的binder才可以。那么AMS和ServiceManager到底是什么關系呢?如果AMS是通過ServiceManager獲得的service binder,那么相關的代碼又是在哪里呢?
這個問題困擾了我很久,直到我看到一個博客,我才發現其實我把一個很重要的概念混起來了:
Android中主要通過2種方法來獲得service binder:
- 通過一些API如bindService,來獲得application service的binder。因為app service都是直接和AMS注冊的,AMS運行在system_server進程;
- 通過ServiceManager.getService(String Descriptor)來獲得Service Manager管理的service的binder,ServiceManager運行在servicemanager進程。
也就是說,尼瑪bindService只是用來bind application level的service!!!
而我們更在意的system service應該是由ServiceManager.getService()來獲得的!!!
發現這個問題之后我整個人都有些凌亂了。。。不過靜下來想想其實自己從bindService這里入手也學到很多東西,也就不糾結了!
那么現在的問題是,應用程序到底是如何獲得system service的binder的?
在這個問題的探索過程初期,我又一次驚奇地發現android.os.ServiceManager竟然是@hide的!!!!
尼瑪hide的啊!!!也就是如果不是和framework一起編譯的話是找不到的啊!我在網上看到一個很無語的解決方案,但是,我還是不知道應用程序到底是怎么調用system service的啊?總不可能每個人都懂得什么變態的“隱藏類的使用”吧?
后來不知道是怎么回事,我突然發現在android里面竟然有一個API叫getSystemService()!我問了下乃正,他竟然和我說“你們干嘛不問我,這不是很顯然的嗎?應用里面就是調用這個獲得system service的啊”!尼瑪傷不起啊,一個沒寫過android應用程序的還要研究android framework的人傷不起啊!!
getSystemService()
好了,還是言歸正傳吧,到底getSystemService()是如何得到system service的呢?其實這個也沒有想象的那么好理解。而且我查了下網上的資料,大部分還是講ServiceManager.getService()是如何得到system service的,而基本上都沒有涉及到getSystemService()是怎么和ServiceManager.getService()搭上關系的。
于是經過一番研究,我終于搞清楚了這里面所涉及的種種“復雜而又充滿基情”的關系,請聽我娓娓道來:
在一個月黑風高的夜晚,一個郁郁不得志的少年Activity調用了一個具有扭轉乾坤概率的大API—getSystemService()。
算了,沒有寫小說的潛質。。。還是老實點正常寫著吧。。。早點寫完早點洗洗睡吧。。。
在調用Activity.getSystemService()之后,就進入ContextImpl.getSystemService()。
至于是怎么進來的,其實也很簡單,Activity繼承ContextThemeWrapper,再繼承ContextWrapper。里面會調用mBase.getSystemService()。這個mBase是一個ContextImpl實例變量,于是就調到了。
于是在ContextImpl.getSystemService()是這樣的:
| 1 2 3 4 5 | @Override public Object getSystemService(String name) { ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name); return fetcher == null ? null : fetcher.getService(this); } |
話說這個SYSTEM_SERVICE_MAP是怎么來的呢?這就要扯得遠點了:
在每個Activity啟動的時候都要運行一大段的static的代碼(在android.app.ContextImpl.java)里面:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | static { registerService(ACCESSIBILITY_SERVICE, new ServiceFetcher() { public Object getService(ContextImpl ctx) { return AccessibilityManager.getInstance(ctx); }}); registerService(ACCOUNT_SERVICE, new ServiceFetcher() { public Object createService(ContextImpl ctx) { IBinder b = ServiceManager.getService(ACCOUNT_SERVICE); IAccountManager service = IAccountManager.Stub.asInterface(b); return new AccountManager(ctx, service); }}); registerService(ACTIVITY_SERVICE, new ServiceFetcher() { public Object createService(ContextImpl ctx) { return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler()); }}); ... |
它會在自己的SYSTEM_SERVICE_MAP為每一個系統服務注冊一個ServiceFetcher的類,在這個類中,大部分的服務為重寫一個函數叫createService(ContextImpl),這個方法之后會用到,現在只需要知道我們從SYSTEM_SERVICE_MAP獲得了某個服務的ServiceFetcher對象fetcher,并通過fetcher.getService(this)獲得了該服務的對象。
fetcher.getService(ContextImpl):
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public Object getService(ContextImpl ctx) { ArrayList<Object> cache = ctx.mServiceCache; Object service; synchronized (cache) { if (cache.size() == 0) { // Initialize the cache vector on first access. // At this point sNextPerContextServiceCacheIndex // is the number of potential services that are // cached per-Context. for (int i = 0; i < sNextPerContextServiceCacheIndex; i++) { cache.add(null); } } else { service = cache.get(mContextCacheIndex); if (service != null) { return service; } } service = createService(ctx); cache.set(mContextCacheIndex, service); return service; } } |
也就是說每個Activity都有一個mServiceCache,它cache了所有用到的service的ServiceFetcher類。如果hit了,那么直接返回該對象,否則會調用這個fetcher的createService()方法,這也就是我們剛才提到的每一個ServiceFetcher在注冊的時候會重寫的那個方法。
可以看到,大部分重寫的方式都是類似于這樣的:
| 1 2 3 4 5 | public Object createService(ContextImpl ctx) { IBinder b = ServiceManager.getService(XXX_SERVICE); IXXXManager service = IXXXManager.Stub.asInterface(b); return new XXXManager(ctx, service); }}); |
于是乎,getSystemService()就在這里和ServiceManager.getService()無縫地結合在了一起!
對于ServiceManager.getService(),在網上有很多關于它的說明和討論,這里推薦其中兩篇:
在老羅的博客中兩篇,
第一篇是這篇文章,主要介紹了怎么從java里面的ServiceManager.getService()開始的流程;
還有一篇是這篇文章,深入介紹了在C++和driver層是如何調用getService的
原文地址:?http://ytliu.info/blog/2012/11/11/getsystemservice-in-android/
總結
以上是生活随笔為你收集整理的getSystemService() in Android的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微信自动回复和自动抢红包实现原理(三):
- 下一篇: Android 5.0及以上实现屏幕截图