【系統之音】WindowManager工做機制源碼剖析

前言html

       轉載請聲明,轉自【http://www.javashuo.com/article/p-srtoulvf-e.html】,多謝!java

       目光所及,皆有Window!Window,顧名思義,窗口,它是應用與用戶交互的一個窗口,咱們所見到視圖,都對應着一個Window。好比屏幕上方的狀態欄、下方的導航欄、按音量鍵調出來音量控制欄、充電時的充電界面、屏幕中間的應用顯示區域(Activity)、Dialog、Toast、PopWindow、菜單等,都依附於對應的Window。能夠認爲Window是View的實際直接管理者,因此理解Window相關的知識,對理解Android的視圖機制有很大的幫助。android

      本文將介紹Window相關的基礎知識,以及從源碼的角度分析WindowManager是如何將View呈如今界面的。本文主要包含以下內容:session

 

 

1、一個懸浮按鈕的demo架構

        本demo實現了在屏幕上顯示一個懸浮的Button,並能夠跟隨手指的移動而移動。代碼以下:app

 1 public void drawFloatButton() {
 2     requestWindowPermission();
 3     final WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
 4     final Button button = new Button(this);
 5     button.setText("button");
 6     final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
 7             WindowManager.LayoutParams.WRAP_CONTENT,
 8             WindowManager.LayoutParams.WRAP_CONTENT,
 9             0,
10             0,
11             PixelFormat.TRANSPARENT);
12     params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
13             | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
14             | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
15     params.gravity = Gravity.LEFT | Gravity.TOP;
16     params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
17     params.x = 500;
18     params.y = 500;
19     windowManager.addView(button, params);
20     button.setOnTouchListener(new View.OnTouchListener() {
21         @Override
22         public boolean onTouch(View v, MotionEvent event) {
23             int rawX = (int) event.getRawX();
24             int rawY = (int) event.getRawY();
25             switch (event.getAction()) {
26                 case MotionEvent.ACTION_MOVE:
27                     params.x = rawX;
28                     params.y = rawY;
29                     windowManager.updateViewLayout(button, params);
30                     break;
31                 default:
32                     break;
33             }
34             return false;
35         }
36     });
37 }

若是是在Android6.0及以上,須要處理權限問題,在AndroidManifest.xml中聲明權限:ide

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

並在代碼中動態申請佈局

 1 private void requestWindowPermission() {
 2         //android 6.0或者以後的版本須要發一個intent讓用戶受權
 3         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
 4             if (!Settings.canDrawOverlays(getApplicationContext())) {
 5                 Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
 6                         Uri.parse("package:" + getPackageName()));
 7                 startActivityForResult(intent, 100);
 8             }
 9         }
10     }

因爲該權限是一個敏感權限,因此啓動時系統還會彈出一個界面讓用戶手動開啓該權限:post

 

演示效果以下所示:學習

       該Button是個懸浮按鈕,它並非經過在xml佈局文件中加入,而後經過Activity的setContentView方法將其顯示在界面中的,而是經過第19行的WindowManager.addView方法實現的。gif中能夠看到,該Button能夠顯示到Title區域,也能夠在app退出後(不殺死進程)獨立顯示在桌面上。手指滑動過程當中,經過第29行WindowManager.updateViewLayout更新Button的LayoutParams的座標參數,不斷更新該Button的位置。後續咱們會對這兩個方法作詳細分析。

 

2、Window相關特性

       經過上述的demo,咱們能夠看到設置了LayoutParams的flags、type變量值,它們都是用來定義Window的特性的。

  一、flag

      flag變量用於設置window的屬性,控制其顯示特性,好比設置爲不獲取焦點、不接受觸屏事件、顯示在鎖屏之上等。在WindowManager.LayoutParams類中定義了不少的flag常量,來豐富Window的功能及屬性。

  二、type

       type變量用於表示Window的類型。系統規定了Window有三種類型,按取值由小到大依次爲:

    (1)應用Window:對應着一個Activity,要建立應用窗口就必須在Activity中完成。層級範圍:1~99

    (2)子Window:不能獨立存在,須要依附於特定的父Window。好比Dialog,PopWindow,菜單等。層級範圍:1000~1999

    (3)系統Window:擁有系統權限才能建立的Window。好比Toast、系統狀態欄、導航欄、手機低電量提示、輸入法Window、搜索條、來電顯示等。系統Window是獨立於應用程序的,理論上講應用程序沒有權限建立系統Window,只有系統進程纔有。層級範圍:2000~2999

      type的值越大,在Window體系中顯示的層級就越高。爲了理解這一點,咱們瞭解一下窗口的Z-Order管理。

      手機上採用的是層疊式的佈局,它是一個三維空間,將手機水平方向做爲X軸,豎直方向做爲Y軸,垂直於屏幕由裏向外的方向爲Z軸,全部窗口就按照type值的順序排列在Z軸上,type值越大Z值也就越大。以下圖所示,因此係統Window每每會在上層顯示:

 

3、WindowManager關係網

 

WindowManager在系統架構中的位置

       這裏必定要捋清楚ViewManager、WindowManager、WindowManagerImpl、WindowManagerGlobal之間的關係。下面先把關鍵代碼擺出來:

 1  public interface ViewManager
 2  {
 3      public void addView(View view, ViewGroup.LayoutParams params);
 4      public void updateViewLayout(View view, ViewGroup.LayoutParams params);
 5      public void removeView(View view);
 6  }
 7  
 8  public interface WindowManager extends ViewManager{
 9       ......
10  }
11  
12  public final class WindowManagerImpl implements WindowManager {
13      private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
14      @override
15      public void addView(view,params){
16          mGlobal.addView(...);
17      }
18      public void updateViewLayout(view,params){
19          mGlobal.updateViewLayout(...);
20      }
21      public void remove(view){
22          mGlobal.remove(...);
23      }
24  }
25  
26  public final class WindowManagerGlobal {
27      public void addView(...){
28          ......
29      }
30      public void updateViewLayout(...) {
31          ......
32      }
33      public void removeView(...) {
34          ......
35      }
36  }

       看到上述這段代碼,相信你必定已經清楚了它們之間的關係了。ViewManager是個接口,其中定義了三個方法,在Window體系中添加、更新、移除View的過程看起來比較複雜,但其實都是圍繞着這三個方法展開的。WindowManager是個接口,繼承了ViewManager,擴展了功能。WindowManagerImpl是個實現類,其中包含了WindowManagerGlobal實例。WindowManagerGlobal則真正完成了addView、updateViewLayout、removeView過程。因此,在demo中咱們在使用WindowManager的實例調用addView,updateViewLayout方法時,實際上都是WindowManagerGlobal來完成的。這種方式稱爲橋接模式,這在系統源碼種很常見,Context機制中也是這種方式,橋接模式這裏就不展開講了。

    第13行中經過WindowManagerGlobal.getInstance()來獲取的實例,這裏看看其實現:

 1 //=========WindowManagerGlobal.java========
 2 private static WindowManagerGlobal sDefaultWindowManager;
 3 public static WindowManagerGlobal getInstance() {
 4     synchronized (WindowManagerGlobal.class) {
 5         if (sDefaultWindowManager == null) {
 6             sDefaultWindowManager = new WindowManagerGlobal();
 7         }
 8         return sDefaultWindowManager;
 9     }
10 }

       可見,它是經過單例模式的方式對外提供的實例。若是對單例模式比較瞭解的話,就能看出這種實現方式是有問題的(對比DCL方式),但不明白系統源碼爲何要這樣實現,多是系統中調用該實例方法的場景比較簡單吧,我們本身在設計單例模式的時候可不能這樣作。

  在WindowMangerGlobal.java中維護着四個很是重要的list:
1 //=========WindowManagerGlobal.java=========
2 //全部Window對應的View
3 private final ArrayList<View> mViews = new ArrayList<View>();
4 //全部Window對應的ViewRootImpl
5 private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();
6 //全部Window對應的LayoutParams
7 private final ArrayList<WindowManager.LayoutParams> mParams = new ArrayList<WindowManager.LayoutParams>;
8 //正在被刪除的View,或者已經執行了removeView方法但尚未完成刪除操做的View
9 private final ArraySet<View> mDyingViews = new ArraySet<View>;
這四個list在addView、updateViewLayout、removeView的過程當中都會頻頻出現,理清楚這四個list和這三個方法,理解WindowManager工做機制時會清晰不少。
在下面的源碼中會詳細講到。

4、addView機制
 1 //=========WindowManagerGlobal=========
 2 public void addView(View view, ViewGroup.LayoutParams params,
 3         Display display, Window parentWindow) {
 4    ......
 5     final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
 6     ......
 7     ViewRootImpl root;
 8     View panelParentView = null;
 9     synchronized (mLock) {
10        ......
11          //view不能重複添加,若是要添加須要先removeView,不然拋異常
12          int index = findViewLocked(view, false);
13          if (index >= 0) {
14              if (mDyingViews.contains(view)) {
15                  // Don't wait for MSG_DIE to make it's way through root's queue.
16                  mRoots.get(index).doDie();
17              } else {
18                  throw new IllegalStateException("View " + view
19                          + " has already been added to the window manager.");
20              }
21              // The previous removeView() had not completed executing. Now it has.
22          }
23          //子window
24          // If this is a panel window, then find the window it is being
25          // attached to for future reference.
26          if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
27                  wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
28              final int count = mViews.size();
29              for (int i = 0; i < count; i++) {
30                  if (mRoots.get(i).mWindow.asBinder() == wparams.token) {
31                      panelParentView = mViews.get(i);
32                  }
33              }
34          }
35          root = new ViewRootImpl(view.getContext(), display);
36          view.setLayoutParams(wparams);
37          mViews.add(view);
38          mRoots.add(root);8
39          mParams.add(wparams);
40          // do this last because it fires off messages to start doing things
41          try {
42              root.setView(view, wparams, panelParentView);
43          } catch (RuntimeException e) {
44              // BadTokenException or InvalidDisplayException, clean up.
45              if (index >= 0) {
46                  removeViewLocked(index, true);
47              }
48              throw e;
49          }
50      }
51  }

上述代碼中除了關鍵方法外,注意留意mViews、mRoots、mParams集合的操做。

 1 //=========ViewRootImpl.java========== 
 2 /**
 3 * We have one child
 4 */
 5 public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
 6    synchronized (this) {
 7        if (mView == null) {
 8            mView = view;
 9            ......
10            mAdded = true;
11             int res; /* = WindowManagerImpl.ADD_OKAY; */
12             // Schedule the first layout -before- adding to the window
13             // manager, to make sure we do the relayout before receiving
14             // any other events from the system.
15             requestLayout();
16             ......
17             try {
18                 ......
19                 res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
20                         getHostVisibility(), mDisplay.getDisplayId(),
21                         mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
22                         mAttachInfo.mOutsets, mInputChannel);
23             } catch (RemoteException e) {
24                 mAdded = false;
25                 mView = null;
26                 ......
27                 throw new RuntimeException("Adding window failed", e);
28             } finally {
29                 ......
30             }
31             ......
32         }
33     }
34 }

       第15行requestLayout()方法會執行View的繪製流程,在我以前的博文【朝花夕拾】Android自定義View篇之(一)View繪製流程中第三節有相關介紹。這裏簡單截取了一段UML圖,讀者明白其做用就能夠了,想深刻研究的能夠去這篇文章看看。

 

 第19行的mWindowSession.addToDisplay(...)方法,addView的實際邏輯處理就在這裏面。咱們繼續分析mWindowSession和addToDisplay(...)的邏輯:

 1 //========ViewRootImpl.java=========
 2 public final class ViewRootImpl{
 3     final IWindowSession mWindowSession;
 4     public ViewRootImpl(...){
 5         ......
 6         mWindowSession = WindowManagerGlobal.getWindowSession();
 7         ......
 8     }
 9 }
10 
11 //=======WindowManagerGlobal.java==========
12 public static IWindowSession getWindowSession() {
13     synchronized (WindowManagerGlobal.class) {
14         if (sWindowSession == null) {
15             try {
16                 ......
17                 IWindowManager windowManager = getWindowManagerService();
18                 sWindowSession = windowManager.openSession(
19                         new IWindowSessionCallback.Stub() {
20                             @Override
21                             public void onAnimatorScaleChanged(float scale) {
22                                 ValueAnimator.setDurationScale(scale);
23                             }
24                         },
25                         ......
26             } catch (RemoteException e) {
27                 throw e.rethrowFromSystemServer();
28             }
29         }
30         return sWindowSession;
31     }
32 }
33 
34 public static IWindowManager getWindowManagerService() {
35     synchronized (WindowManagerGlobal.class) {
36         if (sWindowManagerService == null) {
37             sWindowManagerService = IWindowManager.Stub.asInterface(
38                     ServiceManager.getService("window"));
39             ......
40         }
41         return sWindowManagerService;
42     }
43 }
44 
45 //============WindowManagerService.java=======
46 @Override
47 public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client,
48         IInputContext inputContext) {
49     if (client == null) throw new IllegalArgumentException("null client");
50     if (inputContext == null) throw new IllegalArgumentException("null inputContext");
51     Session session = new Session(this, callback, client, inputContext);
52     return session;
53 }
54 
55 public int addWindow(Session session, IWindow client, int seq,
56             WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
57             Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
58             InputChannel outInputChannel) {
59       //在wms中真正實現
60       ......
61 }
62 
63 //===========Session.java=========
64 final WindowManagerService mService;
65 public Session(WindowManagerService service, ......) {
66       mService = service;
67       ......
68 }
69 
70 @Override
71 public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
72         int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,
73         Rect outOutsets, InputChannel outInputChannel) {
74     return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
75             outContentInsets, outStableInsets, outOutsets, outInputChannel);
76 }

這裏面的代碼邏輯很容易理解,最後是把addView的工做交給了WMS的addWindow方法,因此真正添加view的邏輯是在WMS中完成的。這裏面邏輯比較複雜繁瑣,就不繼續深刻了,當目前爲止就已經清楚整個流程了。

 

 5、updateViewLayout更新機制

 1 //============WindowManagerGlobal.java==========
 2 public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
 3     ......
 4     final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params;
 5     view.setLayoutParams(wparams);
 6     synchronized (mLock) {
 7         int index = findViewLocked(view, true);
 8         ViewRootImpl root = mRoots.get(index);
 9         mParams.remove(index);
10         mParams.add(index, wparams);
11         root.setLayoutParams(wparams, false);
12      }
13  }

這裏面對mParams進行了操做,將舊有的LayoutParams進行了替換。第11行執行了更新邏輯:

1 //=============ViewRootImpl.java==========
2  void setLayoutParams(WindowManager.LayoutParams attrs, boolean newView) {
3       ...... //對新的LayoutParams參數作一些操做
4       scheduleTraversals(); //調用繪製流程
5  }

從上述過程能夠發現更新過程相對比較簡單,更新view的過程簡單來講就是,將新的LayoutParams替換掉舊的,並啓用繪製流程。

 

6、removeView移除機制

1 //============WindowManagerImpl.java==========
2  @Override
3  public void removeView(View view) {
4      mGlobal.removeView(view, false);
5  }
6  @Override
7  public void removeViewImmediate(View view) {
8      mGlobal.removeView(view, true);
9 }

WindowManagerImpl類中提供了兩個方法用於移除view,從方法名稱能夠推測其差異在於Immediate,也就是是否當即移除的意思。

 1 //==========WindowManagerGlobal.java=========
 2 public void removeView(View view, boolean immediate) {
 3    ......
 4     synchronized (mLock) {
 5         int index = findViewLocked(view, true);
 6         View curView = mRoots.get(index).getView();
 7         removeViewLocked(index, immediate);
 8         ......
 9     }
10 }
11 
12 private void removeViewLocked(int index, boolean immediate) {
13     ViewRootImpl root = mRoots.get(index);
14     View view = root.getView();
15     ......
16     boolean deferred = root.die(immediate);
17     if (view != null) {
18         view.assignParent(null);
19         if (deferred) {
20             mDyingViews.add(view);
21         }
22     }
23 }
24 
25 //========ViewRootImpl.java=========
26 private final static int MSG_DIE = 3;
27 final ViewRootHandler mHandler = new ViewRootHandler();
28 /**
29  * @param immediate True, do now if not in traversal. False, put on queue and do later.
30  * @return True, request has been queued. False, request has been completed.
31  */
32 boolean die(boolean immediate) {
33     // Make sure we do execute immediately if we are in the middle of a traversal or the damage
34     // done by dispatchDetachedFromWindow will cause havoc on return.
35     if (immediate && !mIsInTraversal) {
36         doDie();
37         return false;
38     }
39     ......
40     mHandler.sendEmptyMessage(MSG_DIE);
41     return true;
42 }
43 
44 final class ViewRootHandler extends Handler {
45        ......
46       @Override
47         public void handleMessage(Message msg) {
48             switch (msg.what) {
49                  case MSG_DIE:
50                        doDie();
51                         break;
52                   ......
53             }
54         }
55 }

 如上代碼驗證了以前的猜測,removeView(View)和removeViewImmediate(View)的區別確實就在因而否當即移除。若是調用removeView,會經過handler來調用doDie(),而咱們知道handler對應了一個MessageQueue的,須要排隊等待執行的,這樣就實現了延後執行。而若是調用removeViewImmediate,若是當前沒有執行view的遍歷,那就直接調用doDie()了。

 1 //==========ViewRootImpl.java========
 2 void doDie() {
 3     ......
 4     synchronized (this) {
 5         if (mRemoved) {
 6             return;
 7         }
 8         mRemoved = true;
 9         if (mAdded) {
10             dispatchDetachedFromWindow();
11         }
12         ......
13         mAdded = false;
14     }
15     WindowManagerGlobal.getInstance().doRemoveView(this);
16 }
17 //移除的主要邏輯都在該方法內完成
18 void dispatchDetachedFromWindow() {
19      mView.dispatchDetachedFromWindow();
20      ......
21      try {
22            mWindowSession.remove(mWindow);
23         } catch (RemoteException e) {
24         }
25      ......
26      unscheduleTraversals();//中止繪製View
27 }
28 
29 //======View.java======
30 void dispatchDetachedFromWindow() {
31       ......
32       onDetachedFromWindow();
33       ......
34 }
35 
36 @CallSuper
37 protected void onDetachedFromWindow() {
38     //在view從window移除後會回調該方法,能夠在其中作一些資源回收的操做,如終止動畫、中止線程等。
39 }
40 
41 //========WindowManagerGlobal.java=======
42 //該方法主要用於刷新數據
43 void doRemoveView(ViewRootImpl root) {
44     synchronized (mLock) {
45         final int index = mRoots.indexOf(root);
46         if (index >= 0) {
47             mRoots.remove(index);
48             mParams.remove(index);
49             final View view = mViews.remove(index);
50             mDyingViews.remove(view);
51         }
52     }
53     ......
54 }
55 
56 //==========Session.java=======
57 @Override
58 public void remove(IWindow window) {
59     mService.removeWindow(this, window);
60 }
61 
62 //==========WindowManagerService.java=======
63 void removeWindow(Session session, IWindow client) {
64     synchronized(mWindowMap) {
65         WindowState win = windowForClientLocked(session, client, false);
66         if (win == null) {
67             return;
68         }
69         win.removeIfPossible();
70     }
71 }

       上述doDie()過程比較容易理解,第22行,參考addView中的邏輯分析可知,這裏也是IPC方式,流程最終進入到了WMS中的removeWindow方法,一樣到這裏我們不繼續往下深刻了。上述流程中,mRoots、mParams、mViews、mDyingViews四個集合也作了相應的操做。

       上面講到的三個主要方法中,能夠看到它們都對mRoots、mParams、mViews、mDyingViews進行了刷新。

 

7、WMS簡介

      在前面的addView和removeView機制中,咱們會發現具體的處理邏輯都交給了WMS(即WindowManagerService的簡寫)中,那WMS是什麼呢?

      WMS是一個很是重要的系統服務。它支撐着視圖相關的各項業務,這很是符合軟件設計的單一職責原則,其業務和ActivityManagerService(簡稱AMS)一塊兒幾乎佔據了framework業務的半壁江山,可見其重要性。關於WMS的內容實在太多了,這裏只簡單介紹其大體功能以及啓動流程。

  一、WMS功能介紹

        WMS的大概功能以下圖所示:

 

       這裏先簡單描述一下各項功能:

       窗口管理:WMS是窗口管理者,結合WindowManager實現窗口的啓動、添加、刪除,以及管理窗口的大小、層級等。

       窗口動畫:在窗口切換時,使用窗口動畫可使這個過程看起來更炫更生動,這個窗口動畫就是由WMS的動畫子系統來負責的,動畫子系統的管理者即是WindowAnimator。

       輸入系統的中轉站: 觸摸設備屏幕上的窗口時會產生觸摸事件,InputManagerService(IMS)會對觸摸事件進行處理,找到最合適的窗口來反饋事件。而WMS是這些窗口的管理者,那天然而然就成爲了輸入系統的中轉站了。

       Surface管理:窗口並不具有繪製功能,因此每一個窗口都須要一個Surface來供本身繪製,WMS就是這個Surface的管理者。

       該部分參考:Android解析WindowManagerService(一)WMS的誕生

   二、WMS的啓動流程

       在我以前的文章:【系統之音】Android系統啓動篇 中有介紹過系統的啓動過程,其中提到過WMS的啓動時機,這裏從源碼入手再稍微詳細闡述一下:

 1 //===========SystemServer.java==========
 2 /**
 3  * The main entry point from zygote.
 4  */
 5 public static void main(String[] args) {
 6     new SystemServer().run();
 7 }
 8 
 9 private void run() {
10      ......
11      startBootstrapServices();
12      startCoreServices();
13      startOtherServices();
14      ......
15 }
16 
17 private void startOtherServices() {
18      ......
19      WindowManagerService wm = null;
20      ......
21      wm = WindowManagerService.main(context, inputManager,
22      mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
23         !mFirstBoot, mOnlyCore, new PhoneWindowManager());
24      ServiceManager.addService(Context.WINDOW_SERVICE, wm);
25      ......
26 }

在第21行中獲得了WMS的實例:

 1 //=========WindowManagerService.java=======
 2 private static WindowManagerService sInstance;
 3 ......
 4 public static WindowManagerService main(final Context context, final InputManagerService im,
 5         final boolean haveInputMethods, final boolean showBootMsgs, final boolean onlyCore,
 6         WindowManagerPolicy policy) {
 7     DisplayThread.getHandler().runWithScissors(() ->
 8             sInstance = new WindowManagerService(context, im, haveInputMethods, showBootMsgs,
 9                     onlyCore, policy), 0);
10     return sInstance;
11 }

第7行調用了Handler的runWithScissors方法,該方法的做用是執行一個同步的task,即執行完第8行後纔會執行第10行,因此main方法返回的是一個WMS實例。

第24行就是一個將WMS加入到系統服務的過程:

 1 //============ServiceManager.java=========
 2 /**
 3  * Place a new @a service called @a name into the service
 4  * manager.
 5  *
 6  * @param name the name of the new service
 7  * @param service the service object
 8  */
 9 public static void addService(String name, IBinder service) {
10     try {
11         getIServiceManager().addService(name, service, false);
12     } catch (RemoteException e) {
13         Log.e(TAG, "error in addService", e);
14     }
15 }
16 
17 private static IServiceManager sServiceManager;
18 private static IServiceManager getIServiceManager() {
19     if (sServiceManager != null) {
20         return sServiceManager;
21     }
22     // Find the service manager
23     sServiceManager = ServiceManagerNative
24             .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
25     return sServiceManager;
26 }

       這裏調用的addService就是一個IPC過程,若是有閱讀過AIDL實現Binder時編譯生成的代碼,看到ServiceManagerNative類後就會很是眼熟,它就是實現Binder的中間類。至於提供addService功能實現的Server是誰,筆者目前還未找到,因此先研究到這裏,後續研究透徹了再補上。

       到這裏咱們就清楚了,在SystemServer進程啓動過程當中,WMS啓動,並經過ServiceManager中的addServie方法添加到系統中,供其它進程調用。

 

結語

       關於Window、WindowManager、WMS等的內容很是多,這裏只寫了一些筆者在學習過程當中作的一些研究。 因爲筆者水平有限,若是有些地方描述不妥或者不許確的地方,請讀者不吝賜教。

      本文參考資料有:

       【朝花夕拾】Android自定義View篇之(一)View繪製流程

       Android解析WindowManagerService(一)WMS的誕生

       【系統之音】Android系統啓動篇 

      《Android開發藝術探索》

相關文章
相關標籤/搜索