接著上一節(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
(注意這里其實(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
因?yàn)?2-35層上一個(gè)Feature并沒有覆蓋
OneHanded 0-23 26-32 34-35
FullscreenMagnification 0-12 15-23 26-27 29-31 33-35
ImePlaceholder 13-14
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):文章來源:http://www.zghlxwxcb.cn/news/detail-618989.html
文章來源地址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)!