国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

android 13 WMS/AMS系統(tǒng)開發(fā)-窗口層級相關(guān)DisplayArea,WindowContainer第二節(jié)

這篇具有很好參考價(jià)值的文章主要介紹了android 13 WMS/AMS系統(tǒng)開發(fā)-窗口層級相關(guān)DisplayArea,WindowContainer第二節(jié)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

接著上一節(jié)課學(xué)習(xí),我們已經(jīng)清楚的知道了層級結(jié)構(gòu)應(yīng)該怎么看,根據(jù)dumpsys的輸出可以完美復(fù)原出層級結(jié)構(gòu)樹,也理解了結(jié)構(gòu)樹對于層級結(jié)構(gòu)的控制作用。但還沒有從源碼部分對這個(gè)結(jié)構(gòu)樹進(jìn)行一個(gè)分析,即分析生成這個(gè)結(jié)構(gòu)樹的源碼部分。

1、DisplayContent中啟動層級樹的構(gòu)建

    /**
     * Create new {@link DisplayContent} instance, add itself to the root window container and
     * initialize direct children.
     * @param display May not be null.
     * @param root {@link RootWindowContainer}
     */
    DisplayContent(Display display, RootWindowContainer root) {
        super(root.mWindowManager, "DisplayContent", FEATURE_ROOT);
        
    //ignore
    //實(shí)際調(diào)用這里surface相關(guān)圖層配置,因?yàn)轱@示東西都需要Surfaceflinger
        configureSurfaces(pendingTransaction);
    //ignore
    }
    private void configureSurfaces(Transaction transaction) {
     //ignore

        if (mDisplayAreaPolicy == null) {
            // Setup the policy and build the display area hierarchy.
            // Build the hierarchy only after creating the surface so it is reparented correctly
            //實(shí)際調(diào)用這里進(jìn)行DisplayArea構(gòu)建
            mDisplayAreaPolicy = mWmService.getDisplayAreaPolicyProvider().instantiate(
                    mWmService, this /* content */, this /* root */,
                    mImeWindowsContainer);
        }
//ignore
    }

結(jié)下來調(diào)用是實(shí)現(xiàn)類DefaultProvider的instantiate
frameworks/base/services/core/java/com/android/server/wm/DisplayAreaPolicy.java

 public DisplayAreaPolicy instantiate(WindowManagerService wmService,
                DisplayContent content, RootDisplayArea root,
                DisplayArea.Tokens imeContainer) {
                //創(chuàng)建特殊的TaskDisplayArea,這里我們前面講過它是專門來裝Activity相關(guān)的容器
            final TaskDisplayArea defaultTaskDisplayArea = new TaskDisplayArea(content, wmService,
                    "DefaultTaskDisplayArea", FEATURE_DEFAULT_TASK_CONTAINER);
            final List<TaskDisplayArea> tdaList = new ArrayList<>();
            tdaList.add(defaultTaskDisplayArea);

            // Define the features that will be supported under the root of the whole logical
            // display. The policy will build the DisplayArea hierarchy based on this.
            final HierarchyBuilder rootHierarchy = new HierarchyBuilder(root);
            // Set the essential containers (even if the display doesn't support IME).
 //這里同時(shí)setImeContainer進(jìn)行輸入法直接容器設(shè)置           
 rootHierarchy.setImeContainer(imeContainer).setTaskDisplayAreas(tdaList);
            if (content.isTrusted()) {//主屏幕肯定進(jìn)入,也是構(gòu)成層級關(guān)鍵
                // Only trusted display can have system decorations.
                configureTrustedHierarchyBuilder(rootHierarchy, wmService, content);
            }

             return new DisplayAreaPolicyBuilder().setRootHierarchy(rootHierarchy).build(wmService);
        }

上面可以看出主要有以下部分
1、構(gòu)建HierarchyBuilder對象
2、準(zhǔn)備TaskDisplayArea
3、準(zhǔn)備好imeContainer
4、識別屏幕情況,進(jìn)入configureTrustedHierarchyBuilder
5、配置完成進(jìn)入build
先看configureTrustedHierarchyBuilder

private void configureTrustedHierarchyBuilder(HierarchyBuilder rootHierarchy,
                WindowManagerService wmService, DisplayContent content) {
            // WindowedMagnification should be on the top so that there is only one surface
            // to be magnified.
            rootHierarchy.addFeature(new Feature.Builder(wmService.mPolicy, "WindowedMagnification",
                    FEATURE_WINDOWED_MAGNIFICATION)
                    .upTo(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY)
                    .except(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY)
                    // Make the DA dimmable so that the magnify window also mirrors the dim layer.
                    .setNewDisplayAreaSupplier(DisplayArea.Dimmable::new)
                    .build());
            if (content.isDefaultDisplay) {
                // Only default display can have cutout.
                // See LocalDisplayAdapter.LocalDisplayDevice#getDisplayDeviceInfoLocked.
                rootHierarchy.addFeature(new Feature.Builder(wmService.mPolicy, "HideDisplayCutout",
                        FEATURE_HIDE_DISPLAY_CUTOUT)
                        .all()
                        .except(TYPE_NAVIGATION_BAR, TYPE_NAVIGATION_BAR_PANEL, TYPE_STATUS_BAR,
                                TYPE_NOTIFICATION_SHADE)
                        .build())
                        .addFeature(new Feature.Builder(wmService.mPolicy, "OneHanded",
                                FEATURE_ONE_HANDED)
                                .all()
                                .except(TYPE_NAVIGATION_BAR, TYPE_NAVIGATION_BAR_PANEL,
                                        TYPE_SECURE_SYSTEM_OVERLAY)
                                .build());
            }
            rootHierarchy
                    .addFeature(new Feature.Builder(wmService.mPolicy, "FullscreenMagnification",
                            FEATURE_FULLSCREEN_MAGNIFICATION)
                            .all()
                            .except(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY, TYPE_INPUT_METHOD,
                                    TYPE_INPUT_METHOD_DIALOG, TYPE_MAGNIFICATION_OVERLAY,
                                    TYPE_NAVIGATION_BAR, TYPE_NAVIGATION_BAR_PANEL)
                            .build())
                    .addFeature(new Feature.Builder(wmService.mPolicy, "ImePlaceholder",
                            FEATURE_IME_PLACEHOLDER)
                            .and(TYPE_INPUT_METHOD, TYPE_INPUT_METHOD_DIALOG)
                            .build());
        }
    }

看到這個(gè)大家是否覺得這些名字和dumpsys的很熟悉,對的其實(shí)就是這里設(shè)置的這些Feature名字
先來看Feature類:

    /**
     * A feature that requires {@link DisplayArea DisplayArea(s)}.
     */
    static class Feature {
        private final String mName;
        private final int mId;
        private final boolean[] mWindowLayers;
        private final NewDisplayAreaSupplier mNewDisplayAreaSupplier;

        private Feature(String name, int id, boolean[] windowLayers,
                NewDisplayAreaSupplier newDisplayAreaSupplier) {
            mName = name;
            mId = id;
            mWindowLayers = windowLayers;
            mNewDisplayAreaSupplier = newDisplayAreaSupplier;
        }
           //注意這里排除36層
     Feature build() {
                if (mExcludeRoundedCorner) {
                    // Always put the rounded corner layer to the top most layer.
                    mLayers[mPolicy.getMaxWindowLayer()] = false;
                }
                return new Feature(mName, mId, mLayers.clone(), mNewDisplayAreaSupplier);
            }

首先Feature代表的是DisplayArea的一個(gè)特征,可以根據(jù)Feature來對不同的DisplayArea進(jìn)行劃分。
mName:這個(gè)Feature的名字,如上面的“WindowedMagnification”,“HideDisplayCutout”之類的,后續(xù)DisplayArea層級結(jié)構(gòu)建立起來后,每個(gè)DisplayArea的名字用的就是當(dāng)前DisplayArea對應(yīng)的那個(gè)Feature的名字。
mId:Feature的ID,如上面的FEATURE_WINDOWED_MAGNIFICATION和FEATURE_HIDE_DISPLAY_CUTOUT,雖說是Feature的ID,因?yàn)镕eature又是DisplayArea的特征
mWindowLayers:代表了這個(gè)DisplayArea可以包含哪些層級對應(yīng)的窗口,后續(xù)會分析到。
看看其中一個(gè)Feature:

   rootHierarchy.addFeature(new Feature.Builder(wmService.mPolicy, "WindowedMagnification",
                    FEATURE_WINDOWED_MAGNIFICATION)
                    .upTo(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY)
                    .except(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY)
                    // Make the DA dimmable so that the magnify window also mirrors the dim layer.
                    .setNewDisplayAreaSupplier(DisplayArea.Dimmable::new)
                    .build());
//typeInclusive代表一個(gè)windowType,一般可以通過windowType獲取對應(yīng)的windowLayer,獲取方法layerFromType,upTo代表邏輯就是把層級范圍到typeInclusive
  Builder upTo(int typeInclusive) {
                final int max = layerFromType(typeInclusive, false);
                for (int i = 0; i < max; i++) {
                    mLayers[i] = true;
                }
                set(typeInclusive, true);
                return this;
            }
  /**
             * Set that the feature does not apply to the given window types.
             */
             //簡單說就是把人家types排除
            Builder except(int... types) {
                for (int i = 0; i < types.length; i++) {
                    int type = types[i];
                    set(type, false);
                }
                return this;
            }
            //留下types
             Builder and(int... types) {
                for (int i = 0; i < types.length; i++) {
                    int type = types[i];
                    set(type, true);
                }
                return this;
            }
             private int layerFromType(int type, boolean internalWindows) {
                return mPolicy.getWindowLayerFromTypeLw(type, internalWindows);
            }

這里調(diào)用了getWindowLayerFromTypeLw來實(shí)現(xiàn)窗口類型到層級數(shù)的轉(zhuǎn)化:

 default int getWindowLayerFromTypeLw(int type, boolean canAddInternalSystemWindow,
            boolean roundedCornerOverlay) {
        // Always put the rounded corner layer to the top most.
        if (roundedCornerOverlay && canAddInternalSystemWindow) {
            return getMaxWindowLayer();
        }
        if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
            return APPLICATION_LAYER;
        }

        switch (type) {
            case TYPE_WALLPAPER:
                // wallpaper is at the bottom, though the window manager may move it.
                return  1;
            case TYPE_PRESENTATION:
            case TYPE_PRIVATE_PRESENTATION:
            case TYPE_DOCK_DIVIDER:
            case TYPE_QS_DIALOG:
            case TYPE_PHONE:
                return  3;
            case TYPE_SEARCH_BAR:
                return  4;
            case TYPE_INPUT_CONSUMER:
                return  5;
            case TYPE_SYSTEM_DIALOG:
                return  6;
            case TYPE_TOAST:
                // toasts and the plugged-in battery thing
                return  7;
            case TYPE_PRIORITY_PHONE:
                // SIM errors and unlock.  Not sure if this really should be in a high layer.
                return  8;
            case TYPE_SYSTEM_ALERT:
                // like the ANR / app crashed dialogs
                // Type is deprecated for non-system apps. For system apps, this type should be
                // in a higher layer than TYPE_APPLICATION_OVERLAY.
                return  canAddInternalSystemWindow ? 12 : 9;
            case TYPE_APPLICATION_OVERLAY:
                return  11;
            case TYPE_INPUT_METHOD:
                // on-screen keyboards and other such input method user interfaces go here.
                return  13;
            case TYPE_INPUT_METHOD_DIALOG:
                // on-screen keyboards and other such input method user interfaces go here.
                return  14;
            case TYPE_STATUS_BAR:
                return  15;
            case TYPE_STATUS_BAR_ADDITIONAL:
                return  16;
            case TYPE_NOTIFICATION_SHADE:
                return  17;
            case TYPE_STATUS_BAR_SUB_PANEL:
                return  18;
            case TYPE_KEYGUARD_DIALOG:
                return  19;
            case TYPE_VOICE_INTERACTION_STARTING:
                return  20;
            case TYPE_VOICE_INTERACTION:
                // voice interaction layer should show above the lock screen.
                return  21;
            case TYPE_VOLUME_OVERLAY:
                // the on-screen volume indicator and controller shown when the user
                // changes the device volume
                return  22;
            case TYPE_SYSTEM_OVERLAY:
                // the on-screen volume indicator and controller shown when the user
                // changes the device volume
                return  canAddInternalSystemWindow ? 23 : 10;
            case TYPE_NAVIGATION_BAR:
                // the navigation bar, if available, shows atop most things
                return  24;
            case TYPE_NAVIGATION_BAR_PANEL:
                // some panels (e.g. search) need to show on top of the navigation bar
                return  25;
            case TYPE_SCREENSHOT:
                // screenshot selection layer shouldn't go above system error, but it should cover
                // navigation bars at the very least.
                return  26;
            case TYPE_SYSTEM_ERROR:
                // system-level error dialogs
                return  canAddInternalSystemWindow ? 27 : 9;
            case TYPE_MAGNIFICATION_OVERLAY:
                // used to highlight the magnified portion of a display
                return  28;
            case TYPE_DISPLAY_OVERLAY:
                // used to simulate secondary display devices
                return  29;
            case TYPE_DRAG:
                // the drag layer: input for drag-and-drop is associated with this window,
                // which sits above all other focusable windows
                return  30;
            case TYPE_ACCESSIBILITY_OVERLAY:
                // overlay put by accessibility services to intercept user interaction
                return  31;
            case TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY:
                return 32;
            case TYPE_SECURE_SYSTEM_OVERLAY:
                return  33;
            case TYPE_BOOT_PROGRESS:
                return  34;
            case TYPE_POINTER:
                // the (mouse) pointer layer
                return  35;
            default:
                Slog.e("WindowManager", "Unknown window type: " + type);
                return 3;
        }
    }
 

看到上面是不是看到和我們熟悉的窗口類型,如TYPE_WALLPAPER,TYPE_NAVIGATION_BAR等,其實(shí)他們都是有固定的一個(gè)層級的。即windowType的值并不是真正層級數(shù)目,都是需要通過這個(gè)方法進(jìn)行轉(zhuǎn)化才是真正層級數(shù)

那么我們再回到addFeature部分,通過以上的層級獲取及相關(guān)upTo方法后我們可以得出各個(gè)Feature的一個(gè)層級情況

Feature名字 層級情況
WindowedMagnification 0-31
HideDisplayCutout 0-14 16 18-23 26-35
OneHanded 0-23 26-32 34-35
FullscreenMagnification 0-12 15-23 26-27 29-31 33-35
ImePlaceholder 13-14

也就是每個(gè)Feature對應(yīng)層級已經(jīng)清楚了
再接下來就要進(jìn)入正式的樹構(gòu)建了
frameworks/base/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java

Result build(WindowManagerService wmService) {
        validate();

        // Attach DA group roots to screen hierarchy before adding windows to group hierarchies.
        mRootHierarchyBuilder.build(mDisplayAreaGroupHierarchyBuilders);//關(guān)鍵的進(jìn)行build
       //ignore
        return new Result(wmService, mRootHierarchyBuilder.mRoot, displayAreaGroupRoots,
                mSelectRootForWindowFunc, mSelectTaskDisplayAreaFunc);
    }

來看看build方法:

 /**
         * Builds the {@link DisplayArea} hierarchy below root. And adds the roots of those
         * {@link HierarchyBuilder} as children.
         */
        private void build(@Nullable List<HierarchyBuilder> displayAreaGroupHierarchyBuilders) {
//ignore
            PendingArea[] areaForLayer = new PendingArea[maxWindowLayerCount];
            //搞默認(rèn)的PendingArea作為root部分
            final PendingArea root = new PendingArea(null, 0, null); 
            //給areaForLayer填滿都是默認(rèn)new PendingArea(null, 0, null); 
            Arrays.fill(areaForLayer, root);
		       //創(chuàng)建features相關(guān)的樹
            // Create DisplayAreas to cover all defined features.
            final int size = mFeatures.size();
            for (int i = 0; i < size; i++) {
                // Traverse the features with the order they are defined, so that the early defined
                // feature will be on the top in the hierarchy.
                final Feature feature = mFeatures.get(i);
                PendingArea featureArea = null;
                for (int layer = 0; layer < maxWindowLayerCount; layer++) {
                    if (feature.mWindowLayers[layer]) {
                        // This feature will be applied to this window layer.
                        //
                        // We need to find a DisplayArea for it:
                        // We can reuse the existing one if it was created for this feature for the
                        // previous layer AND the last feature that applied to the previous layer is
                        // the same as the feature that applied to the current layer (so they are ok
                        // to share the same parent DisplayArea).
                        if (featureArea == null || featureArea.mParent != areaForLayer[layer]) {
                            // No suitable DisplayArea:
                            // Create a new one under the previous area (as parent) for this layer.
                            featureArea = new PendingArea(feature, layer, areaForLayer[layer]);
                            areaForLayer[layer].mChildren.add(featureArea);
                        }
                        areaForLayer[layer] = featureArea;
                    } else {
                        // This feature won't be applied to this window layer. If it needs to be
                        // applied to the next layer, we will need to create a new DisplayArea for
                        // that.
                        featureArea = null;
                    }
                }
            }
					//創(chuàng)建葉子相關(guān)
            // Create Tokens as leaf for every layer.
            PendingArea leafArea = null;
            int leafType = LEAF_TYPE_TOKENS;
            for (int layer = 0; layer < maxWindowLayerCount; layer++) {
                int type = typeOfLayer(policy, layer);
                // Check whether we can reuse the same Tokens with the previous layer. This happens
                // if the previous layer is the same type as the current layer AND there is no
                // feature that applies to only one of them.
                if (leafArea == null || leafArea.mParent != areaForLayer[layer]
                        || type != leafType) {
                    // Create a new Tokens for this layer.
                    leafArea = new PendingArea(null /* feature */, layer, areaForLayer[layer]);
                    areaForLayer[layer].mChildren.add(leafArea);
                    leafType = type;
                    if (leafType == LEAF_TYPE_TASK_CONTAINERS) {
                        // We use the passed in TaskDisplayAreas for task container type of layer.
                        // Skip creating Tokens even if there is no TDA.
                        addTaskDisplayAreasToApplicationLayer(areaForLayer[layer]);
                        addDisplayAreaGroupsToApplicationLayer(areaForLayer[layer],
                                displayAreaGroupHierarchyBuilders);
                        leafArea.mSkipTokens = true;
                    } else if (leafType == LEAF_TYPE_IME_CONTAINERS) {
                        // We use the passed in ImeContainer for ime container type of layer.
                        // Skip creating Tokens even if there is no ime container.
                        leafArea.mExisting = mImeContainer;
                        leafArea.mSkipTokens = true;
                    }
                }
                leafArea.mMaxLayer = layer;
            }
            root.computeMaxLayer();//會計(jì)算出每個(gè)節(jié)點(diǎn)最大layer值

            // We built a tree of PendingAreas above with all the necessary info to represent the
            // hierarchy, now create and attach real DisplayAreas to the root.
            root.instantiateChildren(mRoot, displayAreaForLayer, 0, featureAreas);//這里會對把PendingArea生成DisplayArea

            // Notify the root that we have finished attaching all the DisplayAreas. Cache all the
            // feature related collections there for fast access.
            mRoot.onHierarchyBuilt(mFeatures, displayAreaForLayer, featureAreas);
        }

這里主要分兩個(gè)部分,邏輯稍微難理解:

1、根據(jù)上面的幾個(gè)Feature的配置來構(gòu)造

 // Create DisplayAreas to cover all defined features.
            final int size = mFeatures.size();
            for (int i = 0; i < size; i++) {//針對5個(gè)Feature進(jìn)行遍歷,按照add先后順序,意味最先add在最頂層
                // Traverse the features with the order they are defined, so that the early defined
                // feature will be on the top in the hierarchy.
                final Feature feature = mFeatures.get(i);
                PendingArea featureArea = null;
                for (int layer = 0; layer < maxWindowLayerCount; layer++) {
                    if (feature.mWindowLayers[layer]) {
                        // This feature will be applied to this window layer.
                        //
                        // We need to find a DisplayArea for it:
                        // We can reuse the existing one if it was created for this feature for the
                        // previous layer AND the last feature that applied to the previous layer is
                        // the same as the feature that applied to the current layer (so they are ok
                        // to share the same parent DisplayArea).
                        //條件1:如果featureArea為空,一般每個(gè)Feature第一次進(jìn)入都為null
                        //條件2:如果featureArea不為空,featureArea的父節(jié)點(diǎn)不一樣,即如果兄弟層級featureArea的父節(jié)點(diǎn)是同一個(gè)那就不需要新創(chuàng)建
                        if (featureArea == null || featureArea.mParent != areaForLayer[layer]) {
                            // No suitable DisplayArea:
                            // Create a new one under the previous area (as parent) for this layer.
                            featureArea = new PendingArea(feature, layer, areaForLayer[layer]);//以areaForLayer[layer]為父節(jié)點(diǎn)創(chuàng)建一個(gè)新的節(jié)點(diǎn)
                            areaForLayer[layer].mChildren.add(featureArea);//老容器節(jié)點(diǎn)添加新節(jié)點(diǎn)
                        }
                        areaForLayer[layer] = featureArea;//更新當(dāng)前l(fā)ayer的容器節(jié)點(diǎn)變成新的PendingArea
                    } else {
                        // This feature won't be applied to this window layer. If it needs to be
                        // applied to the next layer, we will need to create a new DisplayArea for
                        // that.
                        //如果這一層不支持顯示,那么就把featureArea設(shè)置為null
                        featureArea = null;
                    }
                }
            }

那么我們來一個(gè)個(gè)Feature進(jìn)行分析進(jìn)行樹圖繪制:

Feature名字 層級情況
WindowedMagnification 0-31
第一個(gè)Feature從0層就需要創(chuàng)建PeadingArea,父節(jié)點(diǎn)是Root:0:0,一直到31都是共用一個(gè)Parent
android 13 WMS/AMS系統(tǒng)開發(fā)-窗口層級相關(guān)DisplayArea,WindowContainer第二節(jié),wms,framework教程,系統(tǒng)源碼,android,android studio,java

(注意這里其實(shí)還沒有最大層級,因?yàn)檫€沒有對最大層級進(jìn)行計(jì)算,這個(gè)要到最后才會結(jié)算,這里為了方便寫的)
HideDisplayCutout 0-14 16 18-23 26-35
到達(dá)第二個(gè)Feature開始從0時(shí)候肯定新建一個(gè)PendingArea,他的0-31層,父節(jié)點(diǎn)就會變成WindowedMagnification:0:31
android 13 WMS/AMS系統(tǒng)開發(fā)-窗口層級相關(guān)DisplayArea,WindowContainer第二節(jié),wms,framework教程,系統(tǒng)源碼,android,android studio,java
因?yàn)?2-35層上一個(gè)Feature并沒有覆蓋
OneHanded 0-23 26-32 34-35
android 13 WMS/AMS系統(tǒng)開發(fā)-窗口層級相關(guān)DisplayArea,WindowContainer第二節(jié),wms,framework教程,系統(tǒng)源碼,android,android studio,java

FullscreenMagnification 0-12 15-23 26-27 29-31 33-35
android 13 WMS/AMS系統(tǒng)開發(fā)-窗口層級相關(guān)DisplayArea,WindowContainer第二節(jié),wms,framework教程,系統(tǒng)源碼,android,android studio,java

ImePlaceholder 13-14
android 13 WMS/AMS系統(tǒng)開發(fā)-窗口層級相關(guān)DisplayArea,WindowContainer第二節(jié),wms,framework教程,系統(tǒng)源碼,android,android studio,java

2、Feature構(gòu)造完成也要對應(yīng)的一些特殊的進(jìn)行配置,除了TaskDisplayArea和ImeContainer特殊外,其他的給每個(gè)后面都給個(gè)Tokens

這個(gè)部分較為簡單一些,基于上面已經(jīng)根據(jù)Feature構(gòu)建的樹統(tǒng)一需要加上一個(gè)Tokens節(jié)點(diǎn),但是要除去TaskDisplayArea和ImeContainer的兩個(gè)部分

 // Create Tokens as leaf for every layer.
            PendingArea leafArea = null;
            int leafType = LEAF_TYPE_TOKENS;//統(tǒng)一初始中為LEAF_TYPE_TOKENS
            for (int layer = 0; layer < maxWindowLayerCount; layer++) {//遍歷36層
                int type = typeOfLayer(policy, layer);//獲取每層的type是什么
                // Check whether we can reuse the same Tokens with the previous layer. This happens
                // if the previous layer is the same type as the current layer AND there is no
                // feature that applies to only one of them.
                //條件1針對leafArea空,或者leafArea本身不和這個(gè)layer共用一個(gè)父節(jié)點(diǎn)
                //條件2針對屬于TYPE_INPUT_METHOD  APPLICATION_LAYER特殊處理
                if (leafArea == null || leafArea.mParent != areaForLayer[layer]
                        || type != leafType) {
                    // Create a new Tokens for this layer.
                    //以下代碼相應(yīng)想給每一層都掛載一個(gè)PendingArea
                    leafArea = new PendingArea(null /* feature */, layer, areaForLayer[layer]);//創(chuàng)建新的PendingArea,并掛載到areaForLayer[layer]下面
                    areaForLayer[layer].mChildren.add(leafArea);
                    leafType = type;
                    if (leafType == LEAF_TYPE_TASK_CONTAINERS) {
                    //APPLICATION_LAYER單獨(dú)處理,就是前面設(shè)置過的TaskDisplayArea
                        // We use the passed in TaskDisplayAreas for task container type of layer.
                        // Skip creating Tokens even if there is no TDA.
                        addTaskDisplayAreasToApplicationLayer(areaForLayer[layer]);//設(shè)置本身已經(jīng)設(shè)置過的TaskDisplayArea單獨(dú)處理
                        addDisplayAreaGroupsToApplicationLayer(areaForLayer[layer],
                                displayAreaGroupHierarchyBuilders);
                        leafArea.mSkipTokens = true;//設(shè)置跳過
                    } else if (leafType == LEAF_TYPE_IME_CONTAINERS) {
                        // We use the passed in ImeContainer for ime container type of layer.
                        // Skip creating Tokens even if there is no ime container.
                        leafArea.mExisting = mImeContainer;//設(shè)置本身已經(jīng)設(shè)置過的mImeContainer
                        leafArea.mSkipTokens = true;//設(shè)置跳過
                    }
                }
                leafArea.mMaxLayer = layer;
            }
            //根據(jù)層級獲取type,這里只對特殊的APPLICATION_LAYER和TYPE_INPUT_METHOD有特殊,其他都是LEAF_TYPE_TOKENS
            private static int typeOfLayer(WindowManagerPolicy policy, int layer) {
              if (layer == APPLICATION_LAYER) {
                  return LEAF_TYPE_TASK_CONTAINERS;
              } else if (layer == policy.getWindowLayerFromTypeLw(TYPE_INPUT_METHOD)
                      || layer == policy.getWindowLayerFromTypeLw(TYPE_INPUT_METHOD_DIALOG)) {
                  return LEAF_TYPE_IME_CONTAINERS;
              } else {
                  return LEAF_TYPE_TOKENS;
              }
          }
           /** Adds all {@link TaskDisplayArea} to the application layer. */
          private void addTaskDisplayAreasToApplicationLayer(PendingArea parentPendingArea) {
              final int count = mTaskDisplayAreas.size();//這里一般等于1
              for (int i = 0; i < count; i++) {
                  PendingArea leafArea =
                          new PendingArea(null /* feature */, APPLICATION_LAYER, parentPendingArea);//創(chuàng)建新的APPLICATION_LAYER的PendingArea,并掛載到parentPendingArea下面
                  leafArea.mExisting = mTaskDisplayAreas.get(i);//和前面IME一樣把容器設(shè)置進(jìn)去
                  leafArea.mMaxLayer = APPLICATION_LAYER;//設(shè)置最大Layer
                  parentPendingArea.mChildren.add(leafArea);//添加為父節(jié)點(diǎn)的孩子
              }
          }
      }
  

上面代碼執(zhí)行完成后基本Pending樹就構(gòu)造完成,但這個(gè)時(shí)候還是PendingArea還不是真正DisplayArea,而且當(dāng)前根節(jié)點(diǎn)只是個(gè)Root:0:0,根本不是我們DisplayContent,繼續(xù)看build還剩下以下幾步

 root.computeMaxLayer();//會計(jì)算出每個(gè)節(jié)點(diǎn)最大layer值

 // We built a tree of PendingAreas above with all the necessary info to represent the
 // hierarchy, now create and attach real DisplayAreas to the root.
 root.instantiateChildren(mRoot, displayAreaForLayer, 0, featureAreas);//這里會對把PendingArea生成DisplayArea,這里的參數(shù)mRoot就是我們的DisplayContent,root是Root:0:0這個(gè)PendingArea

這里重點(diǎn)看看 root.instantiateChildren(mRoot, displayAreaForLayer, 0, featureAreas);

  void instantiateChildren(DisplayArea<DisplayArea> parent, DisplayArea.Tokens[] areaForLayer,
912                  int level, Map<Feature, List<DisplayArea<WindowContainer>>> areas) {
913              mChildren.sort(Comparator.comparingInt(pendingArea -> pendingArea.mMinLayer));
914              for (int i = 0; i < mChildren.size(); i++) {
915                  final PendingArea child = mChildren.get(i);
916                  final DisplayArea area = child.createArea(parent, areaForLayer);
                     //這里可能create出來為null情況,比如前面說的ImeContainer,和DefaultTaskDisplayArea
917                  if (area == null) {
918                      // TaskDisplayArea and ImeContainer can be set at different hierarchy, so it can
919                      // be null.
920                      continue;
921                  }
922                  parent.addChild(area, WindowContainer.POSITION_TOP);//把返回的area設(shè)置為Child
923                  if (child.mFeature != null) {
924                      areas.get(child.mFeature).add(area);//同時(shí)也放入一下Feature集合
925                  }
926                  child.instantiateChildren(area, areaForLayer, level + 1, areas);//迭代子節(jié)點(diǎn)
927              }
928          }
929  
930          @Nullable
931          private DisplayArea createArea(DisplayArea<DisplayArea> parent,
932                  DisplayArea.Tokens[] areaForLayer) {
933              if (mExisting != null) {//Ime和DefaultTaskDisplayArea可以進(jìn)入,針對已經(jīng)存在mExisting直接使用它返回
934                  if (mExisting.asTokens() != null) {//判斷是否屬于Tokens類型,其實(shí)就是ImeContainer
935                      // Store the WindowToken container for layers
936                      fillAreaForLayers(mExisting.asTokens(), areaForLayer);//給對應(yīng)覆蓋的層級都需要賦值為mExisting
937                  }
938                  return mExisting;//返回之前設(shè)置的
939              }
940              if (mSkipTokens) {//如果被設(shè)置了跳過的直接返回null
941                  return null;
942              }
943              DisplayArea.Type type;
944              if (mMinLayer > APPLICATION_LAYER) {
945                  type = DisplayArea.Type.ABOVE_TASKS;
946              } else if (mMaxLayer < APPLICATION_LAYER) {
947                  type = DisplayArea.Type.BELOW_TASKS;
948              } else {
949                  type = DisplayArea.Type.ANY;
950              }
951              if (mFeature == null) {
952                  final DisplayArea.Tokens leaf = new DisplayArea.Tokens(parent.mWmService, type,
953                          "Leaf:" + mMinLayer + ":" + mMaxLayer);//構(gòu)造對應(yīng)Tokens
954                  fillAreaForLayers(leaf, areaForLayer);//給對應(yīng)覆蓋的層級都需要賦值為leaf
955                  return leaf;
956              } else {
957                  return mFeature.mNewDisplayAreaSupplier.create(parent.mWmService, type,
958                          mFeature.mName + ":" + mMinLayer + ":" + mMaxLayer, mFeature.mId);//這里一般是構(gòu)造對應(yīng)DisplayArea
959              }
960          }

對于代碼都給予了詳細(xì)注釋,這里就只做個(gè)總結(jié):
1、根據(jù)窗口層級37層,每一層進(jìn)行遍歷,掛載一個(gè)新的葉子TOKENS節(jié)點(diǎn),規(guī)則和前面Feature一樣,如果同一個(gè)父親則不需要新生成
2、針對TYPE_INPUT_METHOD APPLICATION_LAYER需要進(jìn)行特殊處理

那么綜上其實(shí)可以得出以下圖(紅色的Leaf就是新添加的,還有ImeContainer和DefaultTaskDisplayArea):

android 13 WMS/AMS系統(tǒng)開發(fā)-窗口層級相關(guān)DisplayArea,WindowContainer第二節(jié),wms,framework教程,系統(tǒng)源碼,android,android studio,java文章來源地址http://www.zghlxwxcb.cn/news/detail-618989.html

到了這里,關(guān)于android 13 WMS/AMS系統(tǒng)開發(fā)-窗口層級相關(guān)DisplayArea,WindowContainer第二節(jié)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Android Framework最難模塊WMS實(shí)戰(zhàn)作業(yè)-手機(jī)車機(jī)系統(tǒng)開發(fā)必備

    Android Framework最難模塊WMS實(shí)戰(zhàn)作業(yè)-手機(jī)車機(jī)系統(tǒng)開發(fā)必備

    0-整體介紹 1-window-container.mp4 窗口層級樹實(shí)戰(zhàn)啟動篇 2-displayarea-feature.mp4 窗口層級樹源碼分析相關(guān) 3-displayarea-draw-feature.mp4 窗口層級樹繪制實(shí)戰(zhàn)1 4-displayarea-draw-leaf.mp4 窗口層級樹繪制實(shí)戰(zhàn)2 5-displayarea-draw-leaf-2.mp4 窗口層級樹繪制實(shí)戰(zhàn)3 6-displayarea-surfacelayer.mp4 窗口層級樹相關(guān)sur

    2024年02月12日
    瀏覽(18)
  • Android窗口層級(Window Type)分析

    Android窗口層級(Window Type)分析

    Android的窗口Window分為三種類型: 應(yīng)用Window,比如 Activity 、 Dialog ;子Window,比如 PopupWindow ;系統(tǒng)Window,比如 Toast 、系統(tǒng)狀態(tài)欄、導(dǎo)航欄等等。 應(yīng)用Window的Z-Ordered最低,就是在系統(tǒng)中的顯示層級最低,然后到子Window,層級最高的是系統(tǒng)Window。層級高的Window會覆蓋層級低的W

    2024年02月09日
    瀏覽(20)
  • android framework實(shí)戰(zhàn)開發(fā)之WINDOWING_MODE_FREEFORM自由窗口相關(guān)

    android framework實(shí)戰(zhàn)開發(fā)之WINDOWING_MODE_FREEFORM自由窗口相關(guān)

    hi,粉絲朋友們! 今天開始就進(jìn)入正式的自由窗口的相關(guān)的內(nèi)容講解,blog只是一些知識點(diǎn)的記錄,更多的干貨,還請看馬哥的視頻,及視頻配套資料。 b站免費(fèi)視頻教程講解: https://www.bilibili.com/video/BV1wj411o7A9/ aosp默認(rèn)并沒有公開自由窗口模式,如果需要體驗(yàn)自由窗口模式必須

    2024年02月06日
    瀏覽(22)
  • 盤點(diǎn)3個(gè).Net開發(fā)的WMS倉庫管理系統(tǒng)

    盤點(diǎn)3個(gè).Net開發(fā)的WMS倉庫管理系統(tǒng)

    更多開源項(xiàng)目請查看:一個(gè)專注推薦.Net開源項(xiàng)目的榜單 倉庫管理系統(tǒng)在企業(yè)中,重要性越來越高,不僅可以提高效率,還能降低企業(yè)的壓力,企業(yè)通過協(xié)調(diào)和優(yōu)化資源使用和物料流動,能極大程度地提升了管理效率,節(jié)約了成本。 特別是最近這兩年,WMS倉庫管理系統(tǒng)特別受

    2024年02月01日
    瀏覽(18)
  • android多屏觸摸相關(guān)的詳解方案-安卓framework開發(fā)手機(jī)車載車機(jī)系統(tǒng)開發(fā)課程

    android多屏觸摸相關(guān)的詳解方案-安卓framework開發(fā)手機(jī)車載車機(jī)系統(tǒng)開發(fā)課程

    直播免費(fèi)視頻課程地址:https://www.bilibili.com/video/BV1hN4y1R7t2/ 在做雙屏相關(guān)需求開發(fā)過程中,經(jīng)常會有對兩個(gè)屏幕都要求可以正確觸摸的場景。但是目前我們模擬器默認(rèn)創(chuàng)建的雙屏其實(shí)是沒有辦法進(jìn)行觸摸的 靜態(tài)修改方案 使用命令查看display2即副屏的信息情況 adb shell dumpsys d

    2024年02月11日
    瀏覽(24)
  • 基于 ThinkPHP 5.1(穩(wěn)定版本) 開發(fā)wms 進(jìn)銷存系統(tǒng)源碼

    基于 ThinkPHP 5.1(穩(wěn)定版本) 開發(fā)wms 進(jìn)銷存系統(tǒng)源碼

    基于ThinkPHP 5.1(LTS版本)開發(fā)的WMS進(jìn)銷存系統(tǒng)源碼 管理員賬號密碼:admin 一、項(xiàng)目簡介 這個(gè)系統(tǒng)是一個(gè)基于ThinkPHP框架的WMS進(jìn)銷存系統(tǒng)。 二、實(shí)現(xiàn)功能 控制臺 – 權(quán)限管理(用戶管理、角色管理、節(jié)點(diǎn)管理) – 訂單管理(采購訂單、銷售訂單) – 倉庫管理(采購入庫、銷

    2024年02月14日
    瀏覽(25)
  • android相機(jī)、相冊相關(guān)(android13 適配)13又又又又又又搞事,讓第三方難以生存,踩坑

    前幾天公司開發(fā)的新項(xiàng)目要上線,結(jié)果...... 由于項(xiàng)目中有用戶更換頭像功能,應(yīng)用市場經(jīng)過檢測android13無法更換頭像,也沒有崩潰也沒有反應(yīng),所以App就被無情退回,相當(dāng)無奈,那就查問題,手頭有沒有android13測試機(jī),怎么辦,怎么辦,怎么辦...那就想辦法,還好vivo有云測

    2024年02月06日
    瀏覽(41)
  • Android 13 網(wǎng)絡(luò) Adb相關(guān)流程深入分析研究

    通過代碼分析發(fā)現(xiàn)Android13 上對 網(wǎng)絡(luò)adb 進(jìn)行了限制! Android13原生代碼要求:必現(xiàn)連接上某個(gè)wifi,才能進(jìn)行adb ,并且切換wifi或者關(guān)閉wifi都是會停止adb。 并且Android13 上 wifi adb 端口號每次是變化的,這個(gè)也是很不方便的! 如果要做成Android11 或者之前一樣,設(shè)備連接WiFi/有線網(wǎng)

    2024年02月09日
    瀏覽(23)
  • Android 13(T) - binder閱讀(3)- binder相關(guān)的類

    Android 13(T) - binder閱讀(3)- binder相關(guān)的類

    原先準(zhǔn)備在binder閱讀(3)中記錄ServiceManager的使用,但是寫著寫著發(fā)現(xiàn),如果不了解和binder相關(guān)的類,那么閱讀起來將會由很多困惑,所以就先來記錄binder相關(guān)的類了。記錄完發(fā)現(xiàn)特別凌亂…先就這樣吧。 從 binder閱讀(1)一開始的圖中可以看到, getService 獲得的是一個(gè)han

    2024年02月11日
    瀏覽(26)
  • 概念A(yù)ndroid AMS

    Android的Activity Manager Service(AMS)是負(fù)責(zé)管理整個(gè)系統(tǒng)中Activity生命周期、任務(wù)棧、應(yīng)用啟動等核心功能的系統(tǒng)服務(wù)。它通過系統(tǒng)級別的進(jìn)程間通信(IPC)機(jī)制與應(yīng)用程序組件交互,確保應(yīng)用程序的行為符合Android的多任務(wù)處理邏輯和用戶的預(yù)期。AMS是Android系統(tǒng)架構(gòu)中的一個(gè)關(guān)

    2024年04月25日
    瀏覽(22)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包