<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                經過上一節的介紹,讀者應該對WMS的窗口管理有了一個感性的認識。從這一節開將深入WMS的內部去剖析其工作流程。 根據前述內容可知,SampleWindow添加窗口的函數是IWindowSession.add()。IWindowSession是WMS與客戶端交互的一個代理,add則直接調用到了WMS的addWindow()函數。我們將從這個函數開始WMS之旅。本小節只討論它的前半部分。 >[info] **注意**: 由于篇幅所限,本章不準備討論removeWindow的實現。 **WindowManagerService.java::WindowManagerService.addWindow()Part1** ``` public int addWindow(Session session, IWindowclient, int seq, WindowManager.LayoutParams attrs, int viewVisibility,int displayId Rect outContentInsets, InputChannel outInputChannel) { // 首先檢查權限,沒有權限的客戶端不能添加窗口 intres = mPolicy.checkAddPermission(attrs); ...... // 當為某個窗口添加子窗口時,attachedWindow將用來保存父窗口的實例 WindowState attachedWindow = null; //win就是即將被添加的窗口了 WindowState win = null; ...... finalint type = attrs.type; synchronized(mWindowMap){ ...... //①獲取窗口要添加到的DisplayContent /* 在添加窗口時,必須通過displayId參數指定添加到哪一個DisplayContent。 SampleWindow例子沒有指定displayId參數,Session會替SampleWindow選擇 DEFAULT_DISPLAY,也就是手機屏幕 */ finalDisplayContent displayContent = getDisplayContentLocked(displayId); if(displayContent == null) { return WindowManagerGlobal.ADD_INVALID_DISPLAY; } ...... // 如果要添加的窗口是另一個的子窗口,就要求父窗口必須已經存在 // 注意, attrs.type表示了窗口的類型,attrs.token則表示了窗口所隸屬的對象 // 對于子窗口來說,attrs.token表示了父窗口 if(type >= FIRST_SUB_WINDOW &&.type <= LAST_SUB_WINDOW) { attachedWindow = windowForClientLocked(null, attrs.token, false); if (attachedWindow == null) { return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN; } //在這里還可以看出WMS要求窗口的層級關系最多為兩層 if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW &&attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) { return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN; } } booleanaddToken = false; // **②WindowToken出場!**根據客戶端的attrs.token取出已注冊的WindowToken WindowToken token = mTokenMap.get(attrs.token); // 下面的if語句塊初步揭示了WindowToken和窗口之間的關系 if(token == null) { // 對于以下幾種類型的窗口,必須通過LayoutParams.token成員為其指定一個已經 // 添加至WMS的WindowToken if (type >= FIRST_APPLICATION_WINDOW && type<= LAST_APPLICATION_WINDOW) { return WindowManagerGlobal.ADD_BAD_APP_TOKEN; } if (type == TYPE_INPUT_METHOD) { return WindowManagerGlobal.ADD_BAD_APP_TOKEN; } if (type == TYPE_WALLPAPER) { return WindowManagerGlobal.ADD_BAD_APP_TOKEN; } if (type == TYPE_DREAM) { return WindowManagerGlobal.ADD_BAD_APP_TOKEN; } // 其他類型的窗口則不需要事先向WMS添加WindowToken因為WMS會在這里隱式地創 // 建一個。注意最后一個參數false,這表示此WindowToken由WMS隱式創建。 token = new WindowToken(this, attrs.token, -1, false); addToken = true; } else if (type >= FIRST_APPLICATION_WINDOW &&type <= LAST_APPLICATION_WINDOW) { // 對于APPLICATION類型的窗口,要求對應的WindowToken的類型也為APPLICATION // 并且是WindowToken的子類:AppWindowToken AppWindowToken atoken = token.appWindowToken; if (atoken == null) { return WindowManagerImpl.ADD_NOT_APP_TOKEN; } else if (atoken.removed) { returnWindowManagerImpl.ADD_APP_EXITING; } if (type==TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn){ return WindowManagerImpl.ADD_STARTING_NOT_NEEDED; } } else if (type == TYPE_INPUT_METHOD) { // 對于其他幾種類型的窗口也有類似的要求:窗口類型必須與WindowToken的類型一致 if (token.windowType != TYPE_INPUT_METHOD) { return WindowManagerGlobal.ADD_BAD_APP_TOKEN; } } else if (type == TYPE_WALLPAPER) { if (token.windowType != TYPE_WALLPAPER) { return WindowManagerGlobal.ADD_BAD_APP_TOKEN; } } else if (type == TYPE_DREAM) { if (token.windowType != TYPE_DREAM) { return WindowManagerGlobal.ADD_BAD_APP_TOKEN; } } // ③WMS為要添加的窗口創建了一個WindowState對象 // 這個對象維護了一個窗口的所有狀態信息 win= new WindowState(this, session, client, token, attachedWindow,seq, attrs, viewVisibility, displayContent); ...... // WindowManagerPolicy出場了。這個函數的調用會調整LayoutParams的一些成員的取值 mPolicy.adjustWindowParamsLw(win.mAttrs); res= mPolicy.prepareAddWindowLw(win, attrs); if(res != WindowManagerGlobal.ADD_OKAY) { return res; } // 接下來將剛剛隱式創建的WindowToken添加到mTokenMap中去。通過這行代碼應該 //讀者應該能想到,所有的WindowToken都被放入這個HashTable中 ...... if(addToken) { mTokenMap.put(attrs.token, token); } win.attach(); // 然后將WindowState對象加入到mWindowMap中 mWindowMap.put(client.asBinder(),win); // 剩下的代碼稍后再做分析 ...... } } ``` addWindow()函數的前段代碼展示了三個重要的概念,分別是WindowToken、WindowState以及DisplayContent。并且在函數開始處對窗口類型的檢查判斷也初步揭示了它們之間的關系:除子窗口外,添加任何一個窗口都必須指明其所屬的WindowToken;窗口在WMS中通過一個WindowState實例進行管理和保管。同時必須在窗口中指明其所屬的DisplayContent,以便確定窗口將被顯示到哪一個屏幕上。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看