Android應(yīng)用程序窗口(Activity)與WindowManagerService服務(wù)的連接過程分析_第1頁
Android應(yīng)用程序窗口(Activity)與WindowManagerService服務(wù)的連接過程分析_第2頁
Android應(yīng)用程序窗口(Activity)與WindowManagerService服務(wù)的連接過程分析_第3頁
Android應(yīng)用程序窗口(Activity)與WindowManagerService服務(wù)的連接過程分析_第4頁
Android應(yīng)用程序窗口(Activity)與WindowManagerService服務(wù)的連接過程分析_第5頁
已閱讀5頁,還剩36頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、Android應(yīng)用程序窗口(Activity)與WindowManagerService服務(wù)的連接過程分析在前兩文中,我們分析了Activity組件的窗口對(duì)象和視圖對(duì)象的創(chuàng)建過程。Activity組件在其窗口對(duì)象和視圖對(duì)象創(chuàng)建完成之后,就會(huì)請求與WindowManagerService建立一個(gè)連接,即請求WindowManagerService為其增加一個(gè)WindowState對(duì)象,用來描述它的窗口狀態(tài)。在本文中,我們就詳細(xì)分析Activity組件與WindowManagerService的連接過程。 我們從兩方面來看Activity組件與WindowManagerService服務(wù)之間的連接

2、。一方面是從Activity組件到WindowManagerService服務(wù)的連接,另一方面是從WindowManagerService服務(wù)到Activity組件的連接。從Activity組件到WindowManagerService服務(wù)的連接是以Activity組件所在的應(yīng)用程序進(jìn)程為單位來進(jìn)行的。當(dāng)一個(gè)應(yīng)用程序進(jìn)程在啟動(dòng)第一個(gè)Activity組件的時(shí)候,它便會(huì)打開一個(gè)到WindowManagerService服務(wù)的連接,這個(gè)連接以應(yīng)用程序進(jìn)程從WindowManagerService服務(wù)處獲得一個(gè)實(shí)現(xiàn)了IWindowSession接口的Session代理對(duì)象來標(biāo)志。從WindowMana

3、gerService服務(wù)到Activity組件的連接是以Activity組件為單位來進(jìn)行的。在應(yīng)用程序進(jìn)程這一側(cè),每一個(gè)Activity組件都關(guān)聯(lián)一個(gè)實(shí)現(xiàn)了IWindow接口的W對(duì)象,這個(gè)W對(duì)象在Activity組件的視圖對(duì)象創(chuàng)建完成之后,就會(huì)通過前面所獲得一個(gè)Session代理對(duì)象來傳遞給WindowManagerService服務(wù),而WindowManagerService服務(wù)接收到這個(gè)W對(duì)象之后,就會(huì)在內(nèi)部創(chuàng)建一個(gè)WindowState對(duì)象來描述與該W對(duì)象所關(guān)聯(lián)的Activity組件的窗口狀態(tài),并且以后就通過這個(gè)W對(duì)象來控制對(duì)應(yīng)的Activity組件的窗口狀態(tài)。 上述Activity組件

4、與WindowManagerService服務(wù)之間的連接模型如圖1所示:從圖1還可以看出,每一個(gè)Activity組件在ActivityManagerService服務(wù)內(nèi)部,都對(duì)應(yīng)有一個(gè)ActivityRecord對(duì)象,這個(gè)ActivityRecord對(duì)象是Activity組件啟動(dòng)的過程中創(chuàng)建的,用來描述Activity組件的運(yùn)行狀態(tài),這一點(diǎn)可以參考前面一文。這樣,每一個(gè)Activity組件在應(yīng)用程序進(jìn)程、WindowManagerService服務(wù)和ActivityManagerService服務(wù)三者之間就分別一一地建立了連接。在本文中,我們主要關(guān)注Activity組件在應(yīng)用程序進(jìn)程和Wind

5、owManagerService服務(wù)之間以及在WindowManagerService服務(wù)和ActivityManagerService服務(wù)之間的連接。 接下來我們就通過Session類、W類和WindowState類的實(shí)現(xiàn)來簡要描述Activity組件與WindowManagerService服務(wù)之間的連接,如圖2和圖3所示: W類實(shí)現(xiàn)了IWindow接口,它的類實(shí)例是一個(gè)Binder本地對(duì)象。從前面一文可以知道,一個(gè)Activity組件在啟動(dòng)的過程中,會(huì)創(chuàng)建一個(gè)關(guān)聯(lián)的ViewRoot對(duì)象,用來配合WindowManagerService服務(wù)來管理該Activity組件的窗口狀態(tài)。在這個(gè)Vi

6、ewRoot對(duì)象內(nèi)部,有一個(gè)類型為W的成員變量mWindow,它是在ViewRoot對(duì)象的創(chuàng)建過程中創(chuàng)建的。 ViewRoot類有一個(gè)靜態(tài)成員變量sWindowSession,它指向了一個(gè)實(shí)現(xiàn)了IWindowSession接口的Session代理對(duì)象。當(dāng)應(yīng)用程序進(jìn)程啟動(dòng)第一個(gè)Activity組件的時(shí)候,它就會(huì)請求WindowManagerService服務(wù)發(fā)送一個(gè)建立連接的Binder進(jìn)程間通信請求。WindowManagerService服務(wù)接收到這個(gè)請求之后,就會(huì)在內(nèi)部創(chuàng)建一個(gè)類型為Session的Binder本地對(duì)象,并且將這個(gè)Binder本地對(duì)象返回給應(yīng)用程序進(jìn)程,后者于是就會(huì)得到一個(gè)

7、Session代理對(duì)象,并且保存在ViewRoot類的靜態(tài)成員變量sWindowSession中。 有了這個(gè)Session代理對(duì)象之后,應(yīng)用程序進(jìn)程就可以在啟動(dòng)Activity組件的時(shí)候,調(diào)用它的成員函數(shù)add來將與該Activity組件所關(guān)聯(lián)的一個(gè)W對(duì)象傳遞給WindowManagerService服務(wù),后者于是就會(huì)得到一個(gè)W代理對(duì)象,并且會(huì)以這個(gè)W代理對(duì)象來創(chuàng)建一個(gè)WindowState對(duì)象,即將這個(gè)W代理對(duì)象保存在新創(chuàng)建的WindowState對(duì)象的成員變量mClient中。這個(gè)WindowState對(duì)象的其余成員變量的描述可以參考前面一文的圖7,這里不再詳述。 Session類的描述同

8、樣可以參考前面一文,這里我們主要描述一下它的作用。從圖3可以看出,Session類實(shí)現(xiàn)了IWindowSession接口,因此,應(yīng)用程序進(jìn)程就可以通過保存在ViewRoot類的靜態(tài)成員變量sWindowSession所描述的一個(gè)Session代理對(duì)象所實(shí)現(xiàn)的IWindowSession接口來與WindowManagerService服務(wù)通信,例如: 1. 在Activity組件的啟動(dòng)過程中,調(diào)用這個(gè)IWindowSession接口的成員函數(shù)add可以將一個(gè)關(guān)聯(lián)的W對(duì)象傳遞到WindowManagerService服務(wù),以便WindowManagerService服務(wù)可以為該Activity組件

9、創(chuàng)建一個(gè)WindowState對(duì)象。 2. 在Activity組件的銷毀過程中,調(diào)用這個(gè)這個(gè)IWindowSession接口的成員函數(shù)remove來請求WindowManagerService服務(wù)之前為該Activity組件所創(chuàng)建的一個(gè)WindowState對(duì)象,這一點(diǎn)可以參考前面一文的鍵盤消息接收通道注銷過程分析。 3. 在Activity組件的運(yùn)行過程中,調(diào)用這個(gè)這個(gè)IWindowSession接口的成員函數(shù)relayout來請求WindowManagerService服務(wù)來對(duì)該Activity組件的UI進(jìn)行布局,以便該Activity組件的UI可以正確地顯示在屏幕中。 我們再來看W類的作

10、用。從圖2可以看出,W類實(shí)現(xiàn)了IWindow接口,因此,WindowManagerService服務(wù)就可以通過它在內(nèi)部所創(chuàng)建的WindowState對(duì)象的成員變量mClient來要求運(yùn)行在應(yīng)用程序進(jìn)程這一側(cè)的Activity組件來配合管理窗口的狀態(tài),例如: 1. 當(dāng)一個(gè)Activity組件的窗口的大小發(fā)生改變后,WindowManagerService服務(wù)就會(huì)調(diào)用這個(gè)IWindow接口的成員函數(shù)resized來通知該Activity組件,它的大小發(fā)生改變了。 2. 當(dāng)一個(gè)Activity組件的窗口的可見性之后,WindowManagerService服務(wù)就會(huì)調(diào)用這個(gè)IWindow接口的成員函數(shù)

11、dispatchAppVisibility來通知該Activity組件,它的可見性發(fā)生改變了。 3. 當(dāng)一個(gè)Activity組件的窗口獲得或者失去焦點(diǎn)之后,WindowManagerService服務(wù)就會(huì)調(diào)用這個(gè)IWindow接口的成員函數(shù)windowFoucusChanged來通知該Activity組件,它的焦點(diǎn)發(fā)生改變了。 理解了Activity組件在應(yīng)用程序進(jìn)程和WindowManagerService服務(wù)之間的連接模型之后,接下來我們再通過簡要分析Activity組件在WindowManagerService服務(wù)和ActivityManagerService服務(wù)之間的連接。 Activ

12、ity組件在WindowManagerService服務(wù)和ActivityManagerService服務(wù)之間的連接是通過一個(gè)AppWindowToken對(duì)象來描述的。AppWindowToken類的實(shí)現(xiàn)如圖4所示: 每一個(gè)Activity組件在啟動(dòng)的時(shí)候,ActivityManagerService服務(wù)都會(huì)內(nèi)部為該Activity組件創(chuàng)建一個(gè)ActivityRecord對(duì)象,并且會(huì)以這個(gè)ActivityRecord對(duì)象所實(shí)現(xiàn)的一個(gè)IApplicationToken接口為參數(shù),請求WindowManagerService服務(wù)為該Activity組件創(chuàng)建一個(gè)AppWindowToken對(duì)象,即將

13、這個(gè)IApplicationToken接口保存在新創(chuàng)建的AppWindowToken對(duì)象的成員變量appToken中。同時(shí),這個(gè)ActivityRecord對(duì)象還會(huì)傳遞給它所描述的Activity組件所運(yùn)行在應(yīng)用程序進(jìn)程,于是,應(yīng)用程序進(jìn)程就可以在啟動(dòng)完成該Activity組件之后,將這個(gè)ActivityRecord對(duì)象以及一個(gè)對(duì)應(yīng)的W對(duì)象傳遞給WindowManagerService服務(wù),后者接著就會(huì)做兩件事情: 1. 根據(jù)獲得的ActivityRecord對(duì)象的IApplicationToken接口來找到與之對(duì)應(yīng)的一個(gè)AppWindowToken對(duì)象; 2. 根據(jù)獲得的AppWindowT

14、oken對(duì)象以及前面?zhèn)鬟f過來的W代理對(duì)象來為正在啟動(dòng)的Activity組件創(chuàng)建一個(gè)WindowState對(duì)象,并且將該AppWindowToken對(duì)象保存在新創(chuàng)建的WindowState對(duì)象的成員變量mAppToken中。 順便提一下,AppWindowToken類是從WindowToken類繼續(xù)下來的。WindowToken類也是用來標(biāo)志一個(gè)窗口的,不過這個(gè)窗口類型除了是應(yīng)用程序窗口,即Activity組件窗口之外,還可以是其它的,例如,輸入法窗口或者壁紙窗口類型等,而AppWindowToken類只是用來描述Activity組件窗口。當(dāng)WindowToken類是用來描述Activity組件

15、窗口的時(shí)候,它的成員變量token指向的就是用來描述該Activity組件的一個(gè)ActivityRecord對(duì)象所實(shí)現(xiàn)的一個(gè)IBinder接口,而成員變量appWindowToken指向的就是其子類AppWindowToken對(duì)象。當(dāng)另一方面,當(dāng)WindowToken類是用來描述非Activity組件窗口的時(shí)候,它的成員變量appWindowToken的值就會(huì)等于null。這樣,我們就可以通過WindowToken類的成員變量appWindowToken的值來判斷一個(gè)WindowToken對(duì)象是否是用來描述一個(gè)Activity組件窗口的,即是否是用來描述一個(gè)應(yīng)用程序窗口的。 上面所描述的Act

16、ivity組件在ActivityManagerService服務(wù)和WindowManagerService服務(wù)之間以及應(yīng)用程序進(jìn)程和WindowManagerService服務(wù)之間的連接模型比較抽象,接下來,我們再通過三個(gè)過程來分析它們彼此之間的連接模型,如下所示: 1. ActivityManagerService服務(wù)請求WindowManagerService服務(wù)為一個(gè)Activity組件創(chuàng)建一個(gè)AppWindowToken對(duì)象的過程; 2. 應(yīng)用程序進(jìn)程請求WindowManagerService服務(wù)創(chuàng)建一個(gè)Session對(duì)象的過程; 3. 應(yīng)用程序進(jìn)程請求WindowManagerSe

17、rvice服務(wù)為一個(gè)Activity組件創(chuàng)建一個(gè)WindowState對(duì)象的過程。 通過這三個(gè)過程的分析,我們就可以對(duì)應(yīng)用程序進(jìn)程、ActivityManagerService服務(wù)和WindowManagerService服務(wù)的關(guān)系有一個(gè)深刻的認(rèn)識(shí)了。 一. AppWindowToken對(duì)象的創(chuàng)建過程 從前面一文的Step 9可以知道,Activity組件在啟動(dòng)的過程中,會(huì)調(diào)用到ActivityStack類的成員函數(shù)startActivityLocked,該函數(shù)會(huì)請求WindowManagerService服務(wù)為當(dāng)前正在啟動(dòng)的Activity組件創(chuàng)建一個(gè)AppWindowToken對(duì)象。接下來

18、,我們就從ActivityStack類的成員函數(shù)startActivityLocked開始分析一個(gè)AppWindowToken對(duì)象的創(chuàng)建過程,如圖5所示:這個(gè)過程可以分為3步,接下來我們就詳細(xì)分析每一個(gè)步驟。 Step 1. ActivityStack.startActivityLockedjava view plain copy 在CODE上查看代碼片派生到我的代碼片public class ActivityStack . final ActivityManagerService mService; . final ArrayList mHistory = new ArrayList();

19、. private final void startActivityLocked(ActivityRecord r, boolean newTask, boolean doResume) final int NH = mHistory.size(); int addPos = -1; if (!newTask) / If starting in an existing task, find where that is. boolean startIt = true; for (int i = NH-1; i >= 0; i-) ActivityRecord p = (ActivityRe

20、cord)mHistory.get(i); if (p.finishing) continue; if (p.task = r.task) / Here it is! Now, if this is not yet visible to the / user, then just add it without starting; it will / get started when the user navigates back to it. addPos = i+1; if (!startIt) mHistory.add(addPos, r); . mService.mWindowManag

21、er.addAppToken(addPos, r, r.task.taskId, .screenOrientation, r.fullscreen); . return; break; if (p.fullscreen) startIt = false; / Place a new activity at top of stack, so it is next to interact / with the user. if (addPos < 0) addPos = NH; . / Slot the activity into the history stack and pr

22、oceed mHistory.add(addPos, r); . if (NH > 0) . mService.mWindowManager.addAppToken( addPos, r, r.task.taskId, .screenOrientation, r.fullscreen); . else / If this is the first activity, don't do any fancy animations, / because there is nothing for it to animate on top of. mService.mWindo

23、wManager.addAppToken(addPos, r, r.task.taskId, .screenOrientation, r.fullscreen); . if (doResume) resumeTopActivityLocked(null); . 這個(gè)函數(shù)定義在文件frameworks/base/services/java/com/android/server/am/ActivityStack.java中。 參數(shù)r是一個(gè)ActivityRecord對(duì)象,用來描述的是要啟動(dòng)的Activity組件,參數(shù)newTask是一個(gè)布爾變量,用來描述要啟動(dòng)的Activity組件是否

24、是在新任務(wù)中啟動(dòng)的,參數(shù)doResume也是一個(gè)布爾變量,用來描述是否需要馬上將Activity組件啟動(dòng)起來。 ActivityStack類的成員變量mService指向的是系統(tǒng)的ActivityManagerService,另外一個(gè)成員變量mHistory是一個(gè)數(shù)組列表,用來描述系統(tǒng)的Activity組件堆棧。 當(dāng)參數(shù)newTask的值等于false時(shí),就說明參數(shù)r所描述的Activity組件是在已有的一個(gè)任務(wù)中啟動(dòng)的,因此,這時(shí)候ActivityStack類的成員函數(shù)startActivityLocked就會(huì)從上到下遍歷保存成員變量mHistory,找到一個(gè)已有的Activity組件,它與

25、參數(shù)r所描述的Activity組件是屬于同一個(gè)任務(wù)的,即它們的成員變量task的值相等。找到這樣的一個(gè)Activity組件之后,如果位于它上面的其它Activity組件的窗口至少有一個(gè)全屏的,即變量startIt的值等于true,那么ActivityStack類的成員函數(shù)startActivityLocked就只是將參數(shù)r所描述的Activity組件加入到成員變量mHistory所描述的一個(gè)Activity組件堆棧中,以及調(diào)用成員變量mService所描述的ActivityManagerService服務(wù)的成員變量mWindowManager所描述的WindowManagerService服務(wù)

26、的成員函數(shù)addAppToken來為它創(chuàng)建一個(gè)AppWindowToken對(duì)象,然后就返回了,即不會(huì)執(zhí)行下面的代碼來啟動(dòng)參數(shù)r所描述的Activity組件。這相當(dāng)于是延遲到參數(shù)r所描述的Activity組件可見時(shí),才將它啟動(dòng)起來。 當(dāng)參數(shù)newTask的值等于true時(shí),就說明參數(shù)r所描述的Activity組件是在一個(gè)任務(wù)中啟動(dòng)的,這時(shí)候ActivityStack類的成員函數(shù)startActivityLocked就會(huì)首先將它添加到成員變量mHistory所描述的一個(gè)Activity組件堆棧,接著再判斷它是否是系統(tǒng)中第一個(gè)啟動(dòng)的Activity組件。如果是系統(tǒng)中第一個(gè)啟動(dòng)的Activity組件,

27、那么ActivityStack類的成員函數(shù)startActivityLocked就只是簡單地調(diào)用WindowManagerService服務(wù)的成員函數(shù)addAppToken來為它創(chuàng)建一個(gè)AppWindowToken對(duì)象就完事了。如果不是系統(tǒng)系統(tǒng)中第一個(gè)啟動(dòng)的Activity組件,那么ActivityStack類的成員函數(shù)startActivityLocked除了會(huì)調(diào)用WindowManagerService服務(wù)的成員函數(shù)addAppToken來為它創(chuàng)建一個(gè)AppWindowToken對(duì)象之外,還會(huì)為它創(chuàng)建一些啟動(dòng)動(dòng)畫等,我們忽略這些代碼。 從上面的分析就可以看出,無論如何,ActivitySt

28、ack類的成員函數(shù)startActivityLocked都會(huì)調(diào)用WindowManagerService服務(wù)的成員函數(shù)addAppToken為正在啟動(dòng)的Activity組件創(chuàng)建一個(gè)AppWindowToken對(duì)象。創(chuàng)建完成這個(gè)AppWindowToken對(duì)象之后,如果參數(shù)doResume的值等于true,那么ActivityStack類的成員函數(shù)startActivityLocked就會(huì)繼續(xù)調(diào)用另外一個(gè)成員函數(shù)resumeTopActivityLocked來繼續(xù)執(zhí)行啟動(dòng)參數(shù)r所描述的一個(gè)Activity組件,這一步可以參考前面一文的Step 10。 接下來,我們就繼續(xù)分析WindowManag

29、erService類的成員函數(shù)addAppToken的實(shí)現(xiàn),以便可以了解WindowManagerService服務(wù)是如何為一個(gè)Activity組件創(chuàng)建一個(gè)AppWindowToken對(duì)象的。 Step 2. WindowManagerService.addAppTokenjava view plain copy 在CODE上查看代碼片派生到我的代碼片public class WindowManagerService extends IWindowManager.Stub implements Watchdog.Monitor . /* * Mapping from a token IBind

30、er to a WindowToken object. */ final HashMap<IBinder, WindowToken> mTokenMap = new HashMap<IBinder, WindowToken>(); /* * The same tokens as mTokenMap, stored in a list for efficient iteration * over them. */ final ArrayList<WindowToken> mTokenList = new ArrayList<WindowToken>

31、(); . /* * Z-ordered (bottom-most first) list of all application tokens, for * controlling the ordering of windows in different applications. This * contains WindowToken objects. */ final ArrayList<AppWindowToken> mAppTokens = new ArrayList<AppWindowToken>(); . public void addAppToken(in

32、t addPos, IApplicationToken token, int groupId, int requestedOrientation, boolean fullscreen) . long inputDispatchingTimeoutNanos; try inputDispatchingTimeoutNanos = token.getKeyDispatchingTimeout() * 1000000L; catch (RemoteException ex) . inputDispatchingTimeoutNanos = DEFAULT_INPUT_DISPATCHING_TIM

33、EOUT_NANOS; synchronized(mWindowMap) AppWindowToken wtoken = findAppWindowToken(token.asBinder(); if (wtoken != null) . return; wtoken = new AppWindowToken(token); wtoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos; wtoken.groupId = groupId; wtoken.appFullscreen = fullscreen; wtoken.

34、requestedOrientation = requestedOrientation; mAppTokens.add(addPos, wtoken); . mTokenMap.put(token.asBinder(), wtoken); mTokenList.add(wtoken); / Application tokens start out hidden. wtoken.hidden = true; wtoken.hiddenRequested = true; /dump(); . 這個(gè)函數(shù)定義在文件frameworks/base/services/Java/com/Android/se

35、rver/WindowManagerService.java中。 WindowManagerService類有三個(gè)成員變量mTokenMap、mTokenList和mAppTokens,它們都是用來描述系統(tǒng)中的窗口的。 成員變量mTokenMap指向的是一個(gè)HashMap,它里面保存的是一系列的WindowToken對(duì)象,每一個(gè)WindowToken對(duì)象都是用來描述一個(gè)窗口的,并且是以描述這些窗口的一個(gè)Binder對(duì)象的IBinder接口為鍵值的。例如,對(duì)于Activity組件類型的窗口來說,它們分別是以用來描述它們的一個(gè)ActivityRecord對(duì)象的IBinder接口保存在成員變量mTo

36、kenMap所指向的一個(gè)HashMap中的。 成員變量mTokenList指向的是一個(gè)ArrayList,它里面保存的也是一系列WindowToken對(duì)象,這些WindowToken對(duì)象與保存在成員變量mTokenMap所指向的一個(gè)HashMap中的WindowToken對(duì)象是一樣的。成員變量mTokenMap和成員變量mTokenList的區(qū)別就在于,前者在給定一個(gè)IBinder接口的情況下,可以迅速指出是否存在一個(gè)對(duì)應(yīng)的窗口,而后者可以迅速遍歷系統(tǒng)中的窗口。 成員變量mAppTokens指向的也是一個(gè)ArrayList,不過它里面保存的是一系列AppWindowToken對(duì)象,每一個(gè)App

37、WindowToken對(duì)象都是用來描述一個(gè)Activity組件的窗口的,而這些AppWindowToken對(duì)象是以它們描述的窗口的Z軸坐標(biāo)由小到大保存在這個(gè)ArrayList中的,這樣我們就可以通過這個(gè)ArrayList來從上到下或者從下到上地遍歷系統(tǒng)中的所有Activity組件窗口。由于這些AppWindowToken對(duì)象所描述的Activity組件窗口也是一個(gè)窗口,并且AppWindowToken類是從WindowToken繼承下來的,因此,這些AppWindowToken對(duì)象還會(huì)同時(shí)被保存在成員變量mTokenMap所指向的一個(gè)HashMap和成員變量mTokenList所指向的一個(gè)Ar

38、rayList中。 理解了WindowManagerService類的成員變量mTokenMap、mTokenList和mAppTokens的作用之后,WindowManagerService類的成員函數(shù)addAppToken的實(shí)現(xiàn)就容易理解了。由于參數(shù)token描述的是一個(gè)Activity組件窗口,因此,函數(shù)就會(huì)為它創(chuàng)建一個(gè)AppWindowToken對(duì)象,并且將這個(gè)AppWindowToken對(duì)象分別保存在 WindowManagerService類的三個(gè)成員變量mTokenMap、mTokenList和mAppTokens中。不過在創(chuàng)建對(duì)象,首先會(huì)檢查與參數(shù)token所對(duì)應(yīng)的AppWin

39、dowToken對(duì)象已經(jīng)存在。如果已經(jīng)存在,就什么也不做就返回了。注意,參數(shù)addPos用來指定參數(shù)token描述的是一個(gè)Activity組件在系統(tǒng)Activity組件堆棧中的位置,這個(gè)位置同時(shí)也指定了為該Activity組件在成員變量成員變量mAppTokens所指向的一個(gè)ArrayList中的位置。由于保存在系統(tǒng)Activity組件堆棧的Activity組件本來就是按照它們的Z軸坐標(biāo)從小到大的順序來排列的,因此,保存在成員變量mAppTokens所指向的一個(gè)ArrayList中的AppWindowToken對(duì)象也是按照它們的Z軸坐標(biāo)從小到大的順序來排列的。 函數(shù)在為參數(shù)token所描述一個(gè)

40、Activity組件窗口創(chuàng)建了一個(gè)AppWindowToken對(duì)象之后,還會(huì)初始化它的一系列成員變量,這些成員變量的含義如下所示: 1. inputDispatchingTimeoutNanos,表示Activity組件窗口收到了一個(gè)IO輸入事件之后,如果沒有在規(guī)定的時(shí)間內(nèi)處理完成該事件,那么系統(tǒng)就認(rèn)為超時(shí)。這個(gè)超時(shí)值可以由Activity組件本身來指定,即可以通過調(diào)用一個(gè)對(duì)應(yīng)的ActivityRecord對(duì)象的成員函數(shù)getKeyDispatchingTimeout來獲得。假如Activity組件沒有指定的話,那么就會(huì)使用默認(rèn)值DEFAULT_INPUT_DISPATCHING_TIMEOU

41、T_NANOS,即5000 * 1000000納秒。 2. groupId,表示Activity組件所屬的任務(wù)的ID。從前面一文可以知道,每一個(gè)Activity組件都是屬于某一個(gè)任務(wù)的,而每一個(gè)任務(wù)都用來描述一組相關(guān)的Activity組件的,這些Activity組件用來完成用戶的某一個(gè)操作。 3. appFullscreen,表示Activity組件的窗口是否是全屏的。如果一個(gè)Activity組件的窗口是全屏的,那么它就會(huì)將位于它下面的所有窗口都擋住,這樣就可以在渲染系統(tǒng)UI時(shí)進(jìn)行優(yōu)化,即不用渲染位于全屏窗口以下的其它窗口。 4. requestedOrientation,表示Activity

42、組件所請求的方向。這個(gè)方向可以是橫的(LANDSCAPE),也可以是豎的(PORTRAIT)。 5. hidden,表示Activity組件是否是處于不可見狀態(tài)。 6. hiddenRequested,與hidden差不多,也是表示Activity組件是否是處于不可見狀態(tài)。兩者的區(qū)別在于,在設(shè)置目標(biāo)Activity組件的可見狀態(tài)時(shí),如果系統(tǒng)等待執(zhí)行Activity組件切換操作,那么目標(biāo)Activity組件的可見狀態(tài)不會(huì)馬上被設(shè)置,即它的hidden值不會(huì)馬上被設(shè)置,而只是設(shè)置它的hiddenRequested值,表示它的可見性狀態(tài)正在等待被設(shè)置。等到系統(tǒng)執(zhí)行完成Activity組件切換操作之后

43、,兩者的值就會(huì)一致了。 接下來,我們繼續(xù)分析一個(gè)AppWindowToken對(duì)象的創(chuàng)建過程,它AppWindowToken類的構(gòu)造函數(shù)的實(shí)現(xiàn)。 Step 3. new AppWindowTokenjava view plain copy 在CODE上查看代碼片派生到我的代碼片public class WindowManagerService extends IWindowManager.Stub implements Watchdog.Monitor . class WindowToken / The actual token. final IBinder token; / The type

44、of window this token is for, as per WindowManager.LayoutParams. final int windowType; / Set if this token was explicitly added by a client, so should / not be removed when all windows are removed. final boolean explicit; . / If this is an AppWindowToken, this is non-null. AppWindowToken appWindowTok

45、en; . WindowToken(IBinder _token, int type, boolean _explicit) token = _token; windowType = type; explicit = _explicit; . class AppWindowToken extends WindowToken / Non-null only for application tokens. final IApplicationToken appToken; . AppWindowToken(IApplicationToken _token) super(_token.asBinde

46、r(), WindowManager.LayoutParams.TYPE_APPLICATION, true); appWindowToken = this; appToken = _token; . . 這個(gè)函數(shù)定義在文件frameworks/base/services/java/com/android/server/WindowManagerService.java中。 AppWindowToken類的構(gòu)造函數(shù)首先調(diào)用父類WindowToken的構(gòu)造函數(shù)來執(zhí)行父類的初始化工作,然后從父類WindowToken繼承下來的成員變量appWindowToken以及自己的成員變量appToken的

47、值。參數(shù)_token指向的是一個(gè)ActivityRecord對(duì)象的IBinder接口,因此,AppWindowToken類的成員變量appToken描述的就是一個(gè)ActivityRecord對(duì)象。 WindowToken類的構(gòu)造函數(shù)用來初始化token、windowType和explicit這三個(gè)成員變量。在我們這個(gè)場景中,成員變量token指向的也是一個(gè)ActivityRecord對(duì)象的IBinder接口,用來標(biāo)志一個(gè)Activity組件的窗口,成員變量windowType用來描述窗口的類型,它的值等于WindowManager.LayoutParams.TYPE_APPLICATION,表

48、示這是一個(gè)Activity組件窗口,成員變量explicit用來表示窗口是否是由應(yīng)用程序進(jìn)程請求添加的。 注意,當(dāng)一個(gè)WindowToken對(duì)象的成員變量appWindowToken的值不等于null時(shí),就表示它實(shí)際描述的是Activity組件窗口,并且這個(gè)成員變量指向的就是與該Activity組件所關(guān)聯(lián)的一個(gè)AppWindowToken對(duì)象。 至此,我們就分析完成一個(gè)AppWindowToken對(duì)象的創(chuàng)建過程了,通過這個(gè)過程我們就可以知道,每一個(gè)Activity組件,在ActivityManagerService服務(wù)內(nèi)部都有一個(gè)對(duì)應(yīng)的ActivityRecord對(duì)象,并且在WindowMan

49、agerService服務(wù)內(nèi)部關(guān)聯(lián)有一個(gè)AppWindowToken對(duì)象。 二. Session對(duì)象的創(chuàng)建過程 應(yīng)用程序進(jìn)程在啟動(dòng)第一個(gè)Activity組件的時(shí)候,就會(huì)請求與WindowManagerService服務(wù)建立一個(gè)連接,以便可以配合WindowManagerService服務(wù)來管理系統(tǒng)中的所有窗口。具體來說,就是應(yīng)用程序進(jìn)程在為它里面啟動(dòng)的第一個(gè)Activity組件的視圖對(duì)象創(chuàng)建一個(gè)關(guān)聯(lián)的ViewRoot對(duì)象的時(shí)候,就會(huì)向WindowManagerService服務(wù)請求返回一個(gè)類型為Session的Binder本地對(duì)象,這樣應(yīng)用程序進(jìn)程就可以獲得一個(gè)類型為Session的Binder代理對(duì)象,以后就可以通過這個(gè)Binder代理對(duì)象來和WindowManagerService服務(wù)進(jìn)行通信了。 從前面一文可以知道,應(yīng)用程序進(jìn)程在為它里面啟動(dòng)的Activity組件的視圖對(duì)象創(chuàng)建關(guān)聯(lián)ViewRoot對(duì)象是通過調(diào)用Wind

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論