中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當前位置: 首頁 > news >正文

wordpress整站隱藏百度一下手機版

wordpress整站隱藏,百度一下手機版,長春網(wǎng)站建設seo,十大傳媒公司排名在安卓源碼的設計中,將將屏幕分為了37層,不同的窗口將在不同的層級中顯示。 對這一塊的概念以及相關源碼做了詳細分析,整理出以下幾篇。 【Android 13源碼分析】WindowContainer窗口層級-1-初識窗口層級樹 【Android 13源碼分析】WindowCon…

在安卓源碼的設計中,將將屏幕分為了37層,不同的窗口將在不同的層級中顯示。
對這一塊的概念以及相關源碼做了詳細分析,整理出以下幾篇。

【Android 13源碼分析】WindowContainer窗口層級-1-初識窗口層級樹

【Android 13源碼分析】WindowContainer窗口層級-2-構建流程

【Android 13源碼分析】WindowContainer窗口層級-3-實例分析

【Android 13源碼分析】WindowContainer窗口層級-4-Surface樹

本篇為第四篇,前面三篇已經(jīng)將Android窗口樹介紹完了,但是我們知道安卓真正控制顯示的是在SurfaceFlinger層,難道說SurfaceFlinger層也有這么一個窗口樹嗎?如果有,Framework層構建窗口樹的代碼這么復雜,難道SurfaceFlinger也有這么一段復雜的邏輯嗎?

首先回答第一個問題:SurfaceFlinger層也有這么一個窗口樹,嚴格來說是SurfaceFlinger也有一個對應的Layer樹。

在這里插入圖片描述
這是使用Winscope工具看到的當前屏幕信息,可以看到在SurfaceFlinger層也有一個和窗口樹應用的層級關系,并且在WindowState層下面還多了一級,多出來的這層右邊的屬性中有一項“isBuffLayer= true”。

先以黑盒的形式補充幾個Surface相關的知識點,對這塊有了解的可跳過。

1. Surface知識黑盒概念

    1. 觸發(fā)創(chuàng)建Surface時就會觸發(fā)創(chuàng)建出一個Layer,所以Surface和Layer是一一對應的,只不過在framework層側重Surface,在SurfaceFlinger側重Layer。
    1. 應用層只要有Surface,就可以將View的數(shù)據(jù)繪制保存到Surface中,也就可以顯示到屏幕上
    1. Layer有多種類型,最常見的是“容器類型”和“buff類型”,只有“buff類型”的Layer才能保存UI數(shù)據(jù)。

2 容器類型的創(chuàng)建

前面幾篇介紹窗口樹的時候,知道那些類其實都是“容器”,作為容器他們本身是沒有UI數(shù)據(jù)的,真正有顯示數(shù)據(jù)的就是 “isBuffLayer= true”的這層Layer。

再回答第二個問題:SurfaceFlinger沒有這么復雜構建Layer樹的邏輯,因為只要Framework創(chuàng)建一個“容器”類的同時也觸發(fā)創(chuàng)建一個Surface,這樣SurfaceFlinger層就也能同步構造出一個Layer(Surface)樹。

2.1 DisplayContent的Surface構建

首先看一下 屏幕(DisplayContent)對應的Surface是怎么創(chuàng)建的。

在構建流程開始的時候就為 DisplayContent的創(chuàng)建了Surface,代碼如下:

    # DisplayContentprivate void configureSurfaces(Transaction transaction) {// 構建一個SurfaceControlfinal SurfaceControl.Builder b = mWmService.makeSurfaceBuilder(mSession).setOpaque(true).setContainerLayer() // 設置為容器類型的Layer.setCallsite("DisplayContent");// 設置名字后構建 (Display 0 name="XXX")mSurfaceControl = b.setName(getName()).setContainerLayer().build();// 設置策略并構建顯示區(qū)域層次結構if (mDisplayAreaPolicy == null) {// WMS的getDisplayAreaPolicyProvider方法按返回 DisplayAreaPolicy.Provider// 然后其 instantiate的實現(xiàn) 目前只有DisplayAreaPolicy的內部類DefaultProvidermDisplayAreaPolicy = mWmService.getDisplayAreaPolicyProvider().instantiate(mWmService, this /* content */, this /* root */,mImeWindowsContainer);}......}

在構建窗口樹源碼分析的時候知道DisplayContent::configureSurfaces 是在 DisplayContent構造方法里執(zhí)行的,也就是說在構建窗口樹的時候,創(chuàng)建了DisplayContent容器的同時,也創(chuàng)建好了對應的Surface,這是第一個映射關系。

注意build的時候 setContainerLayer這個設置, 將其設置為容器類型的Layer

2.2 其他容器Surface的創(chuàng)建與掛載

層級樹其他的各個容器創(chuàng)建的也會觸發(fā)創(chuàng)建出對應的一個Surface,具體的調用鏈如下:

    WindowContainer::addChildWindowContainer::setParentWindowState::onParentChangedWindowContainer::createSurfaceControlWindowContainer::setInitialSurfaceControlPropertiesSurfaceControl.Builder::buildSurfaceControl::init

調用鏈從WindowContainer::addChild 開始是因為每個容器類創(chuàng)建的時候,都會掛載到父節(jié)點下,掛載的方式也就是執(zhí)行WindowContainer::addChild方法,添加到父容器的孩子集合下。

以一個應用的Task容器創(chuàng)建掛載為例:
在這里插入圖片描述
假設其他窗口樹已經(jīng)構建好(也已經(jīng)有了一個對應的Layer樹,暫時不知道是怎么來的沒關系,稍后就明白了),這個時候應用啟動了,肯定是需要創(chuàng)建一個Task,Task創(chuàng)建好后是還是一個單獨的容器,這個時候會執(zhí)行 WindowContainer::addChild 和 WindowContainer::setParent方法,執(zhí)行完后Task就掛著到窗口樹上了。

先看一下這2個方法的代碼:

    # WindowContainer// 當前容器的孩子容器集合protected final WindowList<E> mChildren = new WindowList<E>();@CallSuperprotected void addChild(E child, Comparator<E> comparator) {......// 1. 添加到集合中,也就是掛載if (positionToAdd == -1) {mChildren.add(child);} else {mChildren.add(positionToAdd, child);}// Set the parent after we've actually added a child in case a subclass depends on this.// 2. 調用孩子容器設置父節(jié)點的方法child.setParent(this);}

首先將子容器添加到 mChildren 集合中,然后調用子容器的 setParent 方法。 這么2步執(zhí)行后, 孩子與父容器就有綁定關系了,也就是成功掛載到了父節(jié)點執(zhí)行。(細品,其實就是java集合操作)
先看一下這2個方法的代碼:

    # WindowContainer// 當前容器的孩子容器集合protected final WindowList<E> mChildren = new WindowList<E>();@CallSuperprotected void addChild(E child, Comparator<E> comparator) {......// 1. 添加到集合中,也就是掛載if (positionToAdd == -1) {mChildren.add(child);} else {mChildren.add(positionToAdd, child);}// Set the parent after we've actually added a child in case a subclass depends on this.// 2. 調用孩子容器設置父節(jié)點的方法child.setParent(this);}

首先將子容器添加到 mChildren 集合中,然后調用子容器的 setParent 方法。 這么2步執(zhí)行后, 孩子與父容器就有綁定關系了,也就是成功掛載到了父節(jié)點執(zhí)行。(細品,其實就是java集合操作)

setParent 方法具體代碼如下:

    # WindowContainer// 父節(jié)點private WindowContainer<WindowContainer> mParent = null;final protected void setParent(WindowContainer<WindowContainer> parent) {if (parent == null) {Slog.d(TAG, "setParent old=" + mParent + ",new=" + parent + ",this window=" +this + ",callers=" + Debug.getCallers(6));}final WindowContainer oldParent = mParent;mParent = parent;......onParentChanged(mParent, oldParent);......}

現(xiàn)在 Task 就成功找到組織了,掛著到窗口樹上了。

在這里插入圖片描述
但是這個時候,SurfaceFlinger那邊還是沒變化的,所以繼續(xù)看后續(xù)流程。

    # WindowContainervoid onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent,PreAssignChildLayersCallback callback) {super.onParentChanged(newParent, oldParent);// 正常肯定是有父節(jié)點的if (mParent == null) {return;}if (mSurfaceControl == null) {// If we don't yet have a surface, but we now have a parent, we should// build a surface.// 父親有了,但是自身還為null,則觸發(fā)創(chuàng)建自身Surface的邏輯createSurfaceControl(false /*force*/);} else {......// 有則進行 reparentreparentSurfaceControl(getSyncTransaction(), mParent.mSurfaceControl);}......}// 重點,觸發(fā)Surface的創(chuàng)建void createSurfaceControl(boolean force) {setInitialSurfaceControlProperties(makeSurface());}

注釋比較詳細就不多說了,這里肯定是走createSurfaceControl()邏輯,然后注意makeSurface()方法會創(chuàng)建出Surface,然后再調用setInitialSurfaceControlProperties。先看 makeSurface 方法

    # WindowContainer// 當前容器的Surfaceprotected SurfaceControl mSurfaceControl;SurfaceControl.Builder makeSurface() {// 拿到父節(jié)點,調用makeChildSurfacefinal WindowContainer p = getParent();// 傳遞當前,也就是Taskreturn p.makeChildSurface(this);}SurfaceControl.Builder makeChildSurface(WindowContainer child) {// 拿到父親final WindowContainer p = getParent();// Give the parent a chance to set properties. In hierarchy v1 we rely// on this to set full-screen dimensions on all our Surface-less Layers.// 調用父親的makeChildSurface方法,再調用setParent return p.makeChildSurface(child).setParent(mSurfaceControl);}

這里方法雖然不多,但是邏輯有點繞,做一下解釋:

    1. 是子容器調用的 makeChildSurface 方法,那子容器類就是 Task,父容器就是 DefaultTaskDisplayArea
    1. 執(zhí)行 父容器 makeChildSurface方法的時候,又調用了getParent 獲取父容器,執(zhí)行 makeChildSurface,(眉頭一皺,事情并不簡單)這是開始遞歸了。
    1. 先不管遞歸,總之肯定的是 makeChildSurface方法不管怎么遞歸返回的還是一個SurfaceControl.Builder,然后調用setParent將DefaultTaskDisplayArea的Surface設置為其父節(jié)點。

這樣一來,結果就是 :Task調用 父容器的makeChildSurface后,創(chuàng)建出了一個Surface,并且掛載到了父容器(DefaultTaskDisplayArea)的下面。
知道結果后,還是要弄清楚 遞歸方法是怎么創(chuàng)建 Task對應的Surface的

    1. 對于遞歸調用,最終要的就是找到遞歸結束的條件,當前這個遞歸結束的條件就是 DisplayContent 類重寫了makeChildSurface方法,也就是說調到 DisplayContent::makeChildSurface 就意味著遞歸的結束。

DisplayContent作為一個屏幕的最底層的容器,肯定是會調用到的,畢竟 DefaultTaskDisplayArea也是掛載在這個樹上的。

所以現(xiàn)在來看看 DisplayContent::makeChildSurface方法

    # DisplayContent@OverrideSurfaceControl.Builder makeChildSurface(WindowContainer child) {SurfaceSession s = child != null ? child.getSession() : getSession();// 創(chuàng)建一個容器類型 Surface的Builderfinal SurfaceControl.Builder b = mWmService.makeSurfaceBuilder(s).setContainerLayer();if (child == null) {return b;}// 設置容器名return b.setName(child.getName()).setParent(mSurfaceControl);}

這里的參數(shù) child 就是Task,

    1. 首先創(chuàng)建一個容器類型 SurfaceControl.Builder
    1. 設置name,當前場景是把Task的名字設置過去
    1. 然后設置一下父親為DisplayContent的Surface

這里要注意,這里設置父節(jié)點最終是無效的,會被覆蓋掉,因為上面分析看到了把 DefaultTaskDisplayArea設置為Task父容器。從代碼的執(zhí)行順序上來說,DisplayContent的這次setParent先執(zhí)行,會被后面的覆蓋掉。 從結果來看,Task也確實是掛在DefaultTaskDisplayArea下的。 (不可能每個容器都直接作為DisplayContent的子節(jié)點)

調用鏈執(zhí)行完了,SurfaceFlinger層也創(chuàng)建并且掛載好了Task的Surface。

在這里插入圖片描述
到這里,Framework層的窗口樹, SurfaceFlinger的Surface樹構建的差不多了,但是手機上還是不會有內容的,為什么呢? 因為這些都是 “容器”,真正的顯示需要有Buff類型的Surface。

在這里插入圖片描述
再看一次這個圖, 對應的窗口樹到了WindowState就結束了, SurfaceFliner 這邊可以看到WindowState下還有一個節(jié)點,這個節(jié)點才是真正有UI數(shù)據(jù)的 Layer。

需要體會一下區(qū)別

在Activity啟動流程中時執(zhí)行到目標應用進程創(chuàng)建時會觸發(fā)Task和ActivityRecord創(chuàng)建和掛載。 這個時候WindowState還沒出現(xiàn),另外到這一步Activity的onCreate也沒執(zhí)行到,所以界面上肯定是沒有UI顯示的。

Activity進程創(chuàng)建后,會先執(zhí)行[addWindow流程]觸發(fā) WindowState的創(chuàng)建和掛載,但是這步執(zhí)行完也還是沒有畫面的, 因為WindowState也是一個“容器”。
真正觸發(fā)顯示圖層創(chuàng)建的是在【relayoutWindow】流程,具體的流程不是當前的主題,目前只關注【relayoutWindow】流程中“Buff”類型圖層的創(chuàng)建。

3.1 流程概覽

這里才是第一次執(zhí)行relayoutWindow 創(chuàng)建真正顯示的surface的地方
relayoutWindow的調用鏈如下:

WindowManagerService::relayoutWindowWindowManagerService::createSurfaceControlWindowStateAnimator::createSurfaceLocked -- 創(chuàng)建“Buff” 類型SurfaceWindowStateAnimator::resetDrawState   -- 設置窗口狀態(tài)為DRAW_PENDINGWindowSurfaceController::initSurfaceControl.Builder::buildSurfaceControl::initWindowSurfaceController::getSurfaceControl  -- 給應用端Surface賦值

開始擼代碼

# WindowManagerService public int relayoutWindow(Session session, IWindow client, LayoutParams attrs,int requestedWidth, int requestedHeight, int viewVisibility, int flags,ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration,SurfaceControl outSurfaceControl, InsetsState outInsetsState,InsetsSourceControl[] outActiveControls, Bundle outSyncIdBundle) {......result = createSurfaceControl(outSurfaceControl, result, win, winAnimator);......}

createSurfaceControl 方法有4個參數(shù):

  • outSurfaceControl: WMS創(chuàng)建好一個Surface后,還需要返回給應用端用于View的繪制,就是通過這個參數(shù),由參數(shù)命名也可以知道這是一個“出參”。
  • result: 方法執(zhí)行結果
  • win: 當前窗口對應的WindowState,稍后創(chuàng)建Surface會掛載到這個WindowState節(jié)點之下
  • winAnimator:WindowStateAnimator對象,管理窗口狀態(tài)和動畫,稍后通過其內部方法創(chuàng)建Surface
# WindowManagerServiceprivate int createSurfaceControl(SurfaceControl outSurfaceControl, int result,WindowState win, WindowStateAnimator winAnimator) {// 1. 創(chuàng)建WindowSurfaceController對象WindowSurfaceController surfaceController;try {// 2. 創(chuàng)建“Buff”類型SurfaceTrace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "createSurfaceControl");surfaceController = winAnimator.createSurfaceLocked();} finally {Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);}if (surfaceController != null) {// 3. 出參給應用端surfaceController.getSurfaceControl(outSurfaceControl);// 打印日志,outSurfaceControl復制到了framework的值ProtoLog.i(WM_SHOW_TRANSACTIONS, "OUT SURFACE %s: copied", outSurfaceControl);}......return result;}

這個方法主要有三步,都是圍繞著 WindowSurfaceController 來的:

    1. 先創(chuàng)建出一個WindowSurfaceController 對象 surfaceController
    1. 通過WindowStateAnimator::createSurfaceLocked 對 surfaceController 賦值,根據(jù)方法名猜測是創(chuàng)建了一個Surface
    1. 通過 WindowSurfaceController::getSurfaceControl,給應用端 Surface 賦值

這么看來重點是在第二步 WindowStateAnimator::createSurfaceLocked 是如何創(chuàng)建Surface的。

# WindowStateAnimatorWindowSurfaceController mSurfaceController;// WindowState的狀態(tài)int mDrawState;WindowSurfaceController createSurfaceLocked() {final WindowState w = mWin;if (mSurfaceController != null) {return mSurfaceController;}w.setHasSurface(false);// 打印窗口狀態(tài)ProtoLog.i(WM_DEBUG_ANIM, "createSurface %s: mDrawState=DRAW_PENDING", this);// 重點* 1. 重置窗口狀態(tài)resetDrawState();......// 重點* 2. 創(chuàng)建WindowSurfaceControllermSurfaceController = new WindowSurfaceController(attrs.getTitle().toString(), format,flags, this, attrs.type);......return mSurfaceController;}

這里有2個重點:

    1. 設置窗口狀態(tài)為 DRAW_PENDING
    1. 創(chuàng)建Surface

3.2 設置窗口狀態(tài)–DRAW_PENDING

# WindowStateAnimatorvoid resetDrawState() {// 設置windowState狀態(tài)為DRAW_PENDINGmDrawState = DRAW_PENDING;if (mWin.mActivityRecord == null) {return;}if (!mWin.mActivityRecord.isAnimating(TRANSITION)) {mWin.mActivityRecord.clearAllDrawn();}}

WindowState有很多狀態(tài),以后會單獨說,這里需要注意

  1. WindowState狀態(tài)是保存在WindowStateAnimator中
  2. WindowStateAnimator::createSurfaceLocked方法會將WindowState狀態(tài)設置為DRAW_PENDING,表示等待繪制。

3.3 創(chuàng)建“Buff”類型Surface

繼續(xù)回到主流程,看看 WindowSurfaceController 的構造方法

# WindowSurfaceControllerSurfaceControl mSurfaceControl;WindowSurfaceController(String name, int format, int flags, WindowStateAnimator animator,int windowType) {mAnimator = animator;// 1. 也會作為Surface的nametitle = name;mService = animator.mService;// 2. 拿到WindowStatefinal WindowState win = animator.mWin;mWindowType = windowType;mWindowSession = win.mSession;Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "new SurfaceControl");// 3. 重點* 構建Surface(也是通過makeSurface 方法)final SurfaceControl.Builder b = win.makeSurface().setParent(win.getSurfaceControl()) // 設置為父節(jié)點.setName(name).setFormat(format).setFlags(flags).setMetadata(METADATA_WINDOW_TYPE, windowType).setMetadata(METADATA_OWNER_UID, mWindowSession.mUid).setMetadata(METADATA_OWNER_PID, mWindowSession.mPid).setCallsite("WindowSurfaceController");final boolean useBLAST = mService.mUseBLAST && ((win.getAttrs().privateFlags& WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST) != 0);// 高版本都為BLASTif (useBLAST) {// 4. 重點* 設置為“Buff”圖層b.setBLASTLayer();}// 觸發(fā)buildmSurfaceControl = b.build();Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);}

這個方法有4個點

  1. 第一個參數(shù)傳遞的字符串最終也會作為Surface的name
  2. 獲取到WindowState對象,后面會設置為創(chuàng)建Surface的父節(jié)點
  3. 構建出一個Surface對象, 注意name和 父節(jié)點的設置。 另外可以知道也是通過makeSurface()方法構建的, 這個方法在 2.1小結看到是構建出一個“容器”類型的Surface。
  4. 將Surface設置為“Buff”類型,這個非常重要,因為上一步默認還是“容器”類型,所以需要設置成“Buff”類型,再后面就是build出一個Surface了

那么到這里Surface的創(chuàng)建就完成了,這里可能有的人如果對Surface知識不太清楚的話會比較迷糊,WindowSurfaceController,SurfaceController,Surface到底是什么關系,這個不在當前流程的重點,暫且理解為同級吧,有WindowSurfaceController就可以拿到內部的SurfaceController,而SurfaceController又可以獲取到Surface。

3.4 返回Surface到應用端

最后再來看一下 WMS這邊創(chuàng)建好后的Surface是如何設置給應用端的。

應用端View的繪制信息都是保存到Surface上的,因為必定要有一個"Buff"類型的Surface,也就是上面流程中創(chuàng)建的這個Surface。

應用端的ViewRootImpl觸發(fā)WMS的relayoutWindow會傳遞一個出參 :outSurfaceControl過來, 現(xiàn)在WMS會通過以下方法將剛剛創(chuàng)建好是Surface傳遞到應用端。

這樣一來應用端就有了可以保持繪制數(shù)據(jù)的Surface,然后就可以執(zhí)行 View::draw。

# WindowSurfaceControllervoid getSurfaceControl(SurfaceControl outSurfaceControl) {// 將framework層的SurfaceControl copy給應用層傳遞過來的outSurfaceControloutSurfaceControl.copyFrom(mSurfaceControl, "WindowSurfaceController.getSurfaceControl");}
http://m.risenshineclean.com/news/60164.html

相關文章:

  • 馬云將來淘汰的十個行業(yè)網(wǎng)站建設跨境電商哪個平臺比較好
  • 哪家網(wǎng)站建設做的好百度賬號個人中心
  • 六年級做的網(wǎng)站的軟件下載互聯(lián)網(wǎng)推廣平臺有哪些公司
  • 上海網(wǎng)絡平臺網(wǎng)站建設cba排名最新排名
  • 溫州建設網(wǎng)站公司推廣策劃方案
  • 頁面設計藍色與什么顏色搭配最和諧優(yōu)化網(wǎng)站seo
  • 成都網(wǎng)站建設平臺排名優(yōu)化方法
  • 小地方的旅游網(wǎng)站怎么做網(wǎng)絡公司排名
  • 宜昌網(wǎng)站制作公司億騰百度風云排行榜官網(wǎng)
  • 網(wǎng)站優(yōu)化靠譜seoseo零基礎教學
  • 買外貿衣服的網(wǎng)站佛山抖音seo
  • 小紅書關鍵詞排名優(yōu)化網(wǎng)站優(yōu)化包括哪些內容
  • 宣傳冊設計與制作圖片網(wǎng)站排名優(yōu)化服務
  • 鄭州網(wǎng)站建設優(yōu)點如何注冊域名及網(wǎng)站
  • jsp 響應式網(wǎng)站模板下載seo網(wǎng)絡營銷外包
  • 鮮花網(wǎng)站建設主要內容it培訓機構排行榜
  • 做網(wǎng)站公司深圳國外產(chǎn)品推廣平臺
  • 網(wǎng)站建設要代碼有什么好處中國疫情最新數(shù)據(jù)
  • 做網(wǎng)站怎么自定義背景圖片管理系統(tǒng)
  • 做圖書網(wǎng)站的代碼熊貓seo實戰(zhàn)培訓
  • 重慶江津網(wǎng)站建設外包seo服務收費標準
  • 域名及網(wǎng)站建設實驗報告長尾關鍵詞快速排名軟件
  • 網(wǎng)站建設客戶需求表 文庫北京網(wǎng)站推廣營銷服務電話
  • 做網(wǎng)站什么都不懂 怎么做電工培訓機構
  • 短鏈接生成算法淄博seo網(wǎng)絡公司
  • 濟南旅游網(wǎng)站建設現(xiàn)狀sem和seo哪個工作好
  • 連云港網(wǎng)站 建設百度一下就知道
  • 手機網(wǎng)站開發(fā)者工具淄博seo網(wǎng)站推廣
  • 飼料公司網(wǎng)站建設方案如何制作一個宣傳網(wǎng)頁
  • 溫州外貿網(wǎng)站設計如何進行網(wǎng)站宣傳推廣