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_ACCESSIBILITY_MAGNIFICATION_OVERLAY; 20 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; 21 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; 22 import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY; 23 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; 24 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL; 25 import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE; 26 import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY; 27 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; 28 import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER; 29 import static android.window.DisplayAreaOrganizer.FEATURE_FULLSCREEN_MAGNIFICATION; 30 import static android.window.DisplayAreaOrganizer.FEATURE_HIDE_DISPLAY_CUTOUT; 31 import static android.window.DisplayAreaOrganizer.FEATURE_IME_PLACEHOLDER; 32 import static android.window.DisplayAreaOrganizer.FEATURE_ONE_HANDED; 33 import static android.window.DisplayAreaOrganizer.FEATURE_WINDOWED_MAGNIFICATION; 34 35 import static com.android.server.wm.DisplayAreaPolicyBuilder.Feature; 36 import static com.android.server.wm.DisplayAreaPolicyBuilder.HierarchyBuilder; 37 38 import android.annotation.Nullable; 39 import android.content.res.Resources; 40 import android.os.Bundle; 41 import android.text.TextUtils; 42 43 import java.util.ArrayList; 44 import java.util.List; 45 46 /** 47 * Policy that manages {@link DisplayArea}. 48 */ 49 public abstract class DisplayAreaPolicy { 50 protected final WindowManagerService mWmService; 51 52 /** 53 * The {@link RootDisplayArea} of the whole logical display. All {@link DisplayArea}s must be 54 * (direct or indirect) descendants of this area. 55 */ 56 protected final RootDisplayArea mRoot; 57 58 /** 59 * Constructs a new {@link DisplayAreaPolicy} 60 * 61 * @param wmService the window manager service instance 62 * @param root the root display area under which the policy operates 63 */ DisplayAreaPolicy(WindowManagerService wmService, RootDisplayArea root)64 protected DisplayAreaPolicy(WindowManagerService wmService, RootDisplayArea root) { 65 mWmService = wmService; 66 mRoot = root; 67 } 68 69 /** 70 * Called to ask the policy to attach the given {@link WindowToken} to the {@link DisplayArea} 71 * hierarchy. 72 * 73 * <p>This must attach the token to {@link #mRoot} (or one of its descendants). 74 */ addWindow(WindowToken token)75 public abstract void addWindow(WindowToken token); 76 77 /** Gets the {@link DisplayArea} with given window type and launched options */ findAreaForWindowType(int type, Bundle options, boolean ownerCanManageAppTokens, boolean roundedCornerOverlay)78 public abstract DisplayArea.Tokens findAreaForWindowType(int type, Bundle options, 79 boolean ownerCanManageAppTokens, boolean roundedCornerOverlay); 80 81 /** 82 * Gets the set of {@link DisplayArea} that are created for the given feature to apply to. 83 */ getDisplayAreas(int featureId)84 public abstract List<DisplayArea<? extends WindowContainer>> getDisplayAreas(int featureId); 85 86 /** 87 * @return the default/fallback {@link TaskDisplayArea} on the display. 88 */ getDefaultTaskDisplayArea()89 public abstract TaskDisplayArea getDefaultTaskDisplayArea(); 90 91 /** Returns the {@link TaskDisplayArea} specified by launch options. */ getTaskDisplayArea(@ullable Bundle options)92 public abstract TaskDisplayArea getTaskDisplayArea(@Nullable Bundle options); 93 94 /** Provider for platform-default display area policy. */ 95 static final class DefaultProvider implements DisplayAreaPolicy.Provider { 96 @Override instantiate(WindowManagerService wmService, DisplayContent content, RootDisplayArea root, DisplayArea.Tokens imeContainer)97 public DisplayAreaPolicy instantiate(WindowManagerService wmService, 98 DisplayContent content, RootDisplayArea root, 99 DisplayArea.Tokens imeContainer) { 100 final TaskDisplayArea defaultTaskDisplayArea = new TaskDisplayArea(content, wmService, 101 "DefaultTaskDisplayArea", FEATURE_DEFAULT_TASK_CONTAINER); 102 final List<TaskDisplayArea> tdaList = new ArrayList<>(); 103 tdaList.add(defaultTaskDisplayArea); 104 105 // Define the features that will be supported under the root of the whole logical 106 // display. The policy will build the DisplayArea hierarchy based on this. 107 final HierarchyBuilder rootHierarchy = new HierarchyBuilder(root); 108 // Set the essential containers (even if the display doesn't support IME). 109 rootHierarchy.setImeContainer(imeContainer).setTaskDisplayAreas(tdaList); 110 if (content.isTrusted()) { 111 // Only trusted display can have system decorations. 112 configureTrustedHierarchyBuilder(rootHierarchy, wmService, content); 113 } 114 115 // Instantiate the policy with the hierarchy defined above. This will create and attach 116 // all the necessary DisplayAreas to the root. 117 return new DisplayAreaPolicyBuilder().setRootHierarchy(rootHierarchy).build(wmService); 118 } 119 configureTrustedHierarchyBuilder(HierarchyBuilder rootHierarchy, WindowManagerService wmService, DisplayContent content)120 private void configureTrustedHierarchyBuilder(HierarchyBuilder rootHierarchy, 121 WindowManagerService wmService, DisplayContent content) { 122 // WindowedMagnification should be on the top so that there is only one surface 123 // to be magnified. 124 rootHierarchy.addFeature(new Feature.Builder(wmService.mPolicy, "WindowedMagnification", 125 FEATURE_WINDOWED_MAGNIFICATION) 126 .upTo(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY) 127 .except(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY) 128 // Make the DA dimmable so that the magnify window also mirrors the dim layer. 129 .setNewDisplayAreaSupplier(DisplayArea.Dimmable::new) 130 .build()); 131 if (content.isDefaultDisplay) { 132 // Only default display can have cutout. 133 // See LocalDisplayAdapter.LocalDisplayDevice#getDisplayDeviceInfoLocked. 134 rootHierarchy.addFeature(new Feature.Builder(wmService.mPolicy, "HideDisplayCutout", 135 FEATURE_HIDE_DISPLAY_CUTOUT) 136 .all() 137 .except(TYPE_NAVIGATION_BAR, TYPE_NAVIGATION_BAR_PANEL, TYPE_STATUS_BAR, 138 TYPE_NOTIFICATION_SHADE) 139 .build()) 140 .addFeature(new Feature.Builder(wmService.mPolicy, "OneHanded", 141 FEATURE_ONE_HANDED) 142 .all() 143 .except(TYPE_NAVIGATION_BAR, TYPE_NAVIGATION_BAR_PANEL, 144 TYPE_SECURE_SYSTEM_OVERLAY) 145 .build()); 146 } 147 rootHierarchy 148 .addFeature(new Feature.Builder(wmService.mPolicy, "FullscreenMagnification", 149 FEATURE_FULLSCREEN_MAGNIFICATION) 150 .all() 151 .except(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY, TYPE_INPUT_METHOD, 152 TYPE_INPUT_METHOD_DIALOG, TYPE_MAGNIFICATION_OVERLAY, 153 TYPE_NAVIGATION_BAR, TYPE_NAVIGATION_BAR_PANEL) 154 .build()) 155 .addFeature(new Feature.Builder(wmService.mPolicy, "ImePlaceholder", 156 FEATURE_IME_PLACEHOLDER) 157 .and(TYPE_INPUT_METHOD, TYPE_INPUT_METHOD_DIALOG) 158 .build()); 159 } 160 } 161 162 /** 163 * Provider for {@link DisplayAreaPolicy} instances. 164 * 165 * <p>By implementing this interface and overriding the 166 * {@code config_deviceSpecificDisplayAreaPolicyProvider}, a device-specific implementations 167 * of {@link DisplayAreaPolicy} can be supplied. 168 */ 169 public interface Provider { 170 /** 171 * Instantiates a new {@link DisplayAreaPolicy}. It should set up the {@link DisplayArea} 172 * hierarchy. 173 * 174 * @see DisplayAreaPolicy#DisplayAreaPolicy 175 */ instantiate(WindowManagerService wmService, DisplayContent content, RootDisplayArea root, DisplayArea.Tokens imeContainer)176 DisplayAreaPolicy instantiate(WindowManagerService wmService, DisplayContent content, 177 RootDisplayArea root, DisplayArea.Tokens imeContainer); 178 179 /** 180 * Instantiates the device-specific {@link Provider}. 181 */ fromResources(Resources res)182 static Provider fromResources(Resources res) { 183 String name = res.getString( 184 com.android.internal.R.string.config_deviceSpecificDisplayAreaPolicyProvider); 185 if (TextUtils.isEmpty(name)) { 186 return new DisplayAreaPolicy.DefaultProvider(); 187 } 188 try { 189 return (Provider) Class.forName(name).newInstance(); 190 } catch (ReflectiveOperationException | ClassCastException e) { 191 throw new IllegalStateException("Couldn't instantiate class " + name 192 + " for config_deviceSpecificDisplayAreaPolicyProvider:" 193 + " make sure it has a public zero-argument constructor" 194 + " and implements DisplayAreaPolicy.Provider", e); 195 } 196 } 197 } 198 } 199