1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.wm; 18 19 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; 20 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; 21 import static android.view.WindowManagerPolicyConstants.APPLICATION_LAYER; 22 import static android.window.DisplayAreaOrganizer.FEATURE_IME_PLACEHOLDER; 23 24 import static com.android.server.wm.DisplayAreaPolicyBuilder.Feature; 25 26 import android.annotation.Nullable; 27 28 import com.android.server.policy.WindowManagerPolicy; 29 30 import java.util.ArrayList; 31 import java.util.Collections; 32 import java.util.List; 33 import java.util.Map; 34 35 /** 36 * Root of a {@link DisplayArea} hierarchy. It can be either the {@link DisplayContent} as the root 37 * of the whole logical display, or a {@link DisplayAreaGroup} as the root of a partition of the 38 * logical display. 39 */ 40 class RootDisplayArea extends DisplayArea.Dimmable { 41 42 /** {@link Feature} that are supported in this {@link DisplayArea} hierarchy. */ 43 List<DisplayAreaPolicyBuilder.Feature> mFeatures; 44 45 /** 46 * Mapping from policy supported {@link Feature} to list of {@link DisplayArea} created to cover 47 * all the window types that the {@link Feature} will be applied to. 48 */ 49 Map<Feature, List<DisplayArea<WindowContainer>>> mFeatureToDisplayAreas; 50 51 /** Mapping from window layer to {@link DisplayArea.Tokens} that holds windows on that layer. */ 52 private DisplayArea.Tokens[] mAreaForLayer; 53 54 /** Whether the hierarchy has been built. */ 55 private boolean mHasBuiltHierarchy; 56 RootDisplayArea(WindowManagerService wms, String name, int featureId)57 RootDisplayArea(WindowManagerService wms, String name, int featureId) { 58 super(wms, Type.ANY, name, featureId); 59 } 60 61 @Override getRootDisplayArea()62 RootDisplayArea getRootDisplayArea() { 63 return this; 64 } 65 66 @Override asRootDisplayArea()67 RootDisplayArea asRootDisplayArea() { 68 return this; 69 } 70 71 /** Whether the orientation (based on dimensions) of this root is different from the Display. */ isOrientationDifferentFromDisplay()72 boolean isOrientationDifferentFromDisplay() { 73 return false; 74 } 75 76 /** 77 * Places the IME container below this root, so that it's bounds and config will be updated to 78 * match the root. 79 */ placeImeContainer(DisplayArea.Tokens imeContainer)80 void placeImeContainer(DisplayArea.Tokens imeContainer) { 81 final RootDisplayArea previousRoot = imeContainer.getRootDisplayArea(); 82 83 List<Feature> features = mFeatures; 84 for (int i = 0; i < features.size(); i++) { 85 Feature feature = features.get(i); 86 if (feature.getId() == FEATURE_IME_PLACEHOLDER) { 87 List<DisplayArea<WindowContainer>> imeDisplayAreas = 88 mFeatureToDisplayAreas.get(feature); 89 if (imeDisplayAreas.size() != 1) { 90 throw new IllegalStateException("There must be exactly one DisplayArea for the " 91 + "FEATURE_IME_PLACEHOLDER"); 92 } 93 94 previousRoot.updateImeContainerForLayers(null /* imeContainer */); 95 imeContainer.reparent(imeDisplayAreas.get(0), POSITION_TOP); 96 updateImeContainerForLayers(imeContainer); 97 return; 98 } 99 } 100 throw new IllegalStateException( 101 "There is no FEATURE_IME_PLACEHOLDER in this root to place the IME container"); 102 } 103 104 /** 105 * Finds the {@link DisplayArea.Tokens} in {@code mAreaForLayer} that this type of window 106 * should be attached to. 107 * <p> 108 * Note that in most cases, users are expected to call 109 * {@link DisplayContent#findAreaForToken(WindowToken)} to find a {@link DisplayArea} in 110 * {@link DisplayContent} level instead of calling this inner method. 111 * </p> 112 */ 113 @Nullable findAreaForTokenInLayer(WindowToken token)114 DisplayArea.Tokens findAreaForTokenInLayer(WindowToken token) { 115 return findAreaForWindowTypeInLayer(token.windowType, token.mOwnerCanManageAppTokens, 116 token.mRoundedCornerOverlay); 117 } 118 119 /** @see #findAreaForTokenInLayer(WindowToken) */ 120 @Nullable findAreaForWindowTypeInLayer(int windowType, boolean ownerCanManageAppTokens, boolean roundedCornerOverlay)121 DisplayArea.Tokens findAreaForWindowTypeInLayer(int windowType, boolean ownerCanManageAppTokens, 122 boolean roundedCornerOverlay) { 123 int windowLayerFromType = mWmService.mPolicy.getWindowLayerFromTypeLw(windowType, 124 ownerCanManageAppTokens, roundedCornerOverlay); 125 if (windowLayerFromType == APPLICATION_LAYER) { 126 throw new IllegalArgumentException( 127 "There shouldn't be WindowToken on APPLICATION_LAYER"); 128 } 129 return mAreaForLayer[windowLayerFromType]; 130 } 131 132 /** Callback after {@link DisplayArea} hierarchy has been built. */ onHierarchyBuilt(ArrayList<Feature> features, DisplayArea.Tokens[] areaForLayer, Map<Feature, List<DisplayArea<WindowContainer>>> featureToDisplayAreas)133 void onHierarchyBuilt(ArrayList<Feature> features, DisplayArea.Tokens[] areaForLayer, 134 Map<Feature, List<DisplayArea<WindowContainer>>> featureToDisplayAreas) { 135 if (mHasBuiltHierarchy) { 136 throw new IllegalStateException("Root should only build the hierarchy once"); 137 } 138 mHasBuiltHierarchy = true; 139 mFeatures = Collections.unmodifiableList(features); 140 mAreaForLayer = areaForLayer; 141 mFeatureToDisplayAreas = featureToDisplayAreas; 142 } 143 updateImeContainerForLayers(@ullable DisplayArea.Tokens imeContainer)144 private void updateImeContainerForLayers(@Nullable DisplayArea.Tokens imeContainer) { 145 final WindowManagerPolicy policy = mWmService.mPolicy; 146 mAreaForLayer[policy.getWindowLayerFromTypeLw(TYPE_INPUT_METHOD)] = imeContainer; 147 mAreaForLayer[policy.getWindowLayerFromTypeLw(TYPE_INPUT_METHOD_DIALOG)] = imeContainer; 148 } 149 } 150