日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

getSystemService() in Android

發布時間:2025/3/15 Android 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。