blob: 5dc79f8500c0aa993388fa1c8f2791692ec12790 [file] [log] [blame]
Jorim Jaggi50981592015-12-29 17:54:12 +01001/*
2 * Copyright (C) 2015 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 */
Filip Gruszczynski92e432c2015-12-15 19:17:09 -080016
Jorim Jaggi50981592015-12-29 17:54:12 +010017package com.android.server.wm;
Filip Gruszczynski92e432c2015-12-15 19:17:09 -080018
Filip Gruszczynski92e432c2015-12-15 19:17:09 -080019import android.util.Slog;
Filip Gruszczynski92e432c2015-12-15 19:17:09 -080020
Wale Ogunwale26b7b432016-02-03 14:12:08 -080021import java.util.ArrayDeque;
Wale Ogunwale1e129a42016-11-21 13:03:47 -080022import java.util.function.Consumer;
Filip Gruszczynski92e432c2015-12-15 19:17:09 -080023
Winson Chung1cebea62017-06-26 17:22:27 -070024import static android.app.ActivityManager.StackId;
Winson Chung83471632016-12-13 11:02:12 -080025import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID;
Wale Ogunwale26b7b432016-02-03 14:12:08 -080026import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
Winson Chung1cebea62017-06-26 17:22:27 -070027import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
Wale Ogunwale26b7b432016-02-03 14:12:08 -080028import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
Wale Ogunwale44fbdf52016-11-16 10:18:45 -080029import static android.view.Display.DEFAULT_DISPLAY;
Jorim Jaggi50981592015-12-29 17:54:12 +010030import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
31import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
32import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
33import static com.android.server.wm.WindowManagerService.WINDOW_LAYER_MULTIPLIER;
34
Filip Gruszczynski92e432c2015-12-15 19:17:09 -080035/**
36 * Controller for assigning layers to windows on the display.
37 *
38 * This class encapsulates general algorithm for assigning layers and special rules that we need to
39 * apply on top. The general algorithm goes through windows from bottom to the top and the higher
40 * the window is, the higher layer is assigned. The final layer is equal to base layer +
41 * adjustment from the order. This means that the window list is assumed to be ordered roughly by
42 * the base layer (there are exceptions, e.g. due to keyguard and wallpaper and they need to be
43 * handled with care, because they break the algorithm).
44 *
45 * On top of the general algorithm we add special rules, that govern such amazing things as:
46 * <li>IME (which has higher base layer, but will be positioned above application windows)</li>
47 * <li>docked/pinned windows (that need to be lifted above other application windows, including
48 * animations)
49 * <li>dock divider (which needs to live above applications, but below IME)</li>
50 * <li>replaced windows, which need to live above their normal level, because they anticipate
51 * an animation</li>.
52 */
Wale Ogunwalec69694a2016-10-18 13:51:15 -070053class WindowLayersController {
Filip Gruszczynski92e432c2015-12-15 19:17:09 -080054 private final WindowManagerService mService;
55
Wale Ogunwalec69694a2016-10-18 13:51:15 -070056 WindowLayersController(WindowManagerService service) {
Filip Gruszczynski92e432c2015-12-15 19:17:09 -080057 mService = service;
58 }
59
Wale Ogunwale26b7b432016-02-03 14:12:08 -080060 private ArrayDeque<WindowState> mPinnedWindows = new ArrayDeque<>();
61 private ArrayDeque<WindowState> mDockedWindows = new ArrayDeque<>();
Winson Chung83471632016-12-13 11:02:12 -080062 private ArrayDeque<WindowState> mAssistantWindows = new ArrayDeque<>();
Robert Carrb9768772016-04-19 22:31:09 -070063 private ArrayDeque<WindowState> mInputMethodWindows = new ArrayDeque<>();
Filip Gruszczynski92e432c2015-12-15 19:17:09 -080064 private WindowState mDockDivider = null;
Wale Ogunwale26b7b432016-02-03 14:12:08 -080065 private ArrayDeque<WindowState> mReplacingWindows = new ArrayDeque<>();
Wale Ogunwaled1880962016-11-08 10:31:59 -080066 private int mCurBaseLayer;
67 private int mCurLayer;
68 private boolean mAnyLayerChanged;
Winson Chung1cebea62017-06-26 17:22:27 -070069 private int mHighestApplicationLayer;
70 private int mHighestDockedAffectedLayer;
Wale Ogunwale44fbdf52016-11-16 10:18:45 -080071 private int mHighestLayerInImeTargetBaseLayer;
72 private WindowState mImeTarget;
Wale Ogunwaleca9e0612016-12-02 07:45:59 -080073 private boolean mAboveImeTarget;
74 private ArrayDeque<WindowState> mAboveImeTargetAppWindows = new ArrayDeque();
Filip Gruszczynski92e432c2015-12-15 19:17:09 -080075
Wale Ogunwale1e129a42016-11-21 13:03:47 -080076 private final Consumer<WindowState> mAssignWindowLayersConsumer = w -> {
77 boolean layerChanged = false;
78
79 int oldLayer = w.mLayer;
80 if (w.mBaseLayer == mCurBaseLayer) {
81 mCurLayer += WINDOW_LAYER_MULTIPLIER;
82 } else {
83 mCurBaseLayer = mCurLayer = w.mBaseLayer;
84 }
85 assignAnimLayer(w, mCurLayer);
86
87 // TODO: Preserved old behavior of code here but not sure comparing oldLayer to
88 // mAnimLayer and mLayer makes sense...though the worst case would be unintentional
89 // layer reassignment.
90 if (w.mLayer != oldLayer || w.mWinAnimator.mAnimLayer != oldLayer) {
91 layerChanged = true;
92 mAnyLayerChanged = true;
93 }
94
95 if (w.mAppToken != null) {
96 mHighestApplicationLayer = Math.max(mHighestApplicationLayer,
97 w.mWinAnimator.mAnimLayer);
98 }
99 if (mImeTarget != null && w.mBaseLayer == mImeTarget.mBaseLayer) {
100 mHighestLayerInImeTargetBaseLayer = Math.max(mHighestLayerInImeTargetBaseLayer,
101 w.mWinAnimator.mAnimLayer);
102 }
Winson Chung1cebea62017-06-26 17:22:27 -0700103 if (w.getAppToken() != null && StackId.isResizeableByDockedStack(w.getStackId())) {
104 mHighestDockedAffectedLayer = Math.max(mHighestDockedAffectedLayer,
105 w.mWinAnimator.mAnimLayer);
106 }
Wale Ogunwale1e129a42016-11-21 13:03:47 -0800107
108 collectSpecialWindows(w);
109
110 if (layerChanged) {
111 w.scheduleAnimationIfDimming();
112 }
113 };
114
Wale Ogunwaled1880962016-11-08 10:31:59 -0800115 final void assignWindowLayers(DisplayContent dc) {
116 if (DEBUG_LAYERS) Slog.v(TAG_WM, "Assigning layers based",
Filip Gruszczynski92e432c2015-12-15 19:17:09 -0800117 new RuntimeException("here").fillInStackTrace());
118
Wale Ogunwale44fbdf52016-11-16 10:18:45 -0800119 reset();
Wale Ogunwale1e129a42016-11-21 13:03:47 -0800120 dc.forAllWindows(mAssignWindowLayersConsumer, false /* traverseTopToBottom */);
Filip Gruszczynski92e432c2015-12-15 19:17:09 -0800121
122 adjustSpecialWindows();
123
124 //TODO (multidisplay): Magnification is supported only for the default display.
Wale Ogunwaled1880962016-11-08 10:31:59 -0800125 if (mService.mAccessibilityController != null && mAnyLayerChanged
Wale Ogunwale44fbdf52016-11-16 10:18:45 -0800126 && dc.getDisplayId() == DEFAULT_DISPLAY) {
Filip Gruszczynski92e432c2015-12-15 19:17:09 -0800127 mService.mAccessibilityController.onWindowLayersChangedLocked();
128 }
129
Wale Ogunwaled1880962016-11-08 10:31:59 -0800130 if (DEBUG_LAYERS) logDebugLayers(dc);
Filip Gruszczynski92e432c2015-12-15 19:17:09 -0800131 }
132
Wale Ogunwaled1880962016-11-08 10:31:59 -0800133 private void logDebugLayers(DisplayContent dc) {
134 dc.forAllWindows((w) -> {
Filip Gruszczynski92e432c2015-12-15 19:17:09 -0800135 final WindowStateAnimator winAnimator = w.mWinAnimator;
136 Slog.v(TAG_WM, "Assign layer " + w + ": " + "mBase=" + w.mBaseLayer
137 + " mLayer=" + w.mLayer + (w.mAppToken == null
Robert Carrdee1b3f2017-02-27 11:33:33 -0800138 ? "" : " mAppLayer=" + w.mAppToken.getAnimLayerAdjustment())
Filip Gruszczynski92e432c2015-12-15 19:17:09 -0800139 + " =mAnimLayer=" + winAnimator.mAnimLayer);
Wale Ogunwaled1880962016-11-08 10:31:59 -0800140 }, false /* traverseTopToBottom */);
Filip Gruszczynski92e432c2015-12-15 19:17:09 -0800141 }
142
Wale Ogunwale44fbdf52016-11-16 10:18:45 -0800143 private void reset() {
Wale Ogunwale26b7b432016-02-03 14:12:08 -0800144 mPinnedWindows.clear();
Robert Carrb9768772016-04-19 22:31:09 -0700145 mInputMethodWindows.clear();
Wale Ogunwale26b7b432016-02-03 14:12:08 -0800146 mDockedWindows.clear();
Winson Chung83471632016-12-13 11:02:12 -0800147 mAssistantWindows.clear();
Wale Ogunwale26b7b432016-02-03 14:12:08 -0800148 mReplacingWindows.clear();
Filip Gruszczynski92e432c2015-12-15 19:17:09 -0800149 mDockDivider = null;
Wale Ogunwaled1880962016-11-08 10:31:59 -0800150
151 mCurBaseLayer = 0;
152 mCurLayer = 0;
153 mAnyLayerChanged = false;
Wale Ogunwale44fbdf52016-11-16 10:18:45 -0800154
Winson Chung1cebea62017-06-26 17:22:27 -0700155 mHighestApplicationLayer = 0;
156 mHighestDockedAffectedLayer = 0;
Wale Ogunwale44fbdf52016-11-16 10:18:45 -0800157 mHighestLayerInImeTargetBaseLayer = (mImeTarget != null) ? mImeTarget.mBaseLayer : 0;
Winson Chung1cebea62017-06-26 17:22:27 -0700158 mImeTarget = mService.mInputMethodTarget;
Wale Ogunwaleca9e0612016-12-02 07:45:59 -0800159 mAboveImeTarget = false;
160 mAboveImeTargetAppWindows.clear();
Filip Gruszczynski92e432c2015-12-15 19:17:09 -0800161 }
162
163 private void collectSpecialWindows(WindowState w) {
Filip Gruszczynskibedb5662016-01-04 15:56:07 -0800164 if (w.mAttrs.type == TYPE_DOCK_DIVIDER) {
Filip Gruszczynski92e432c2015-12-15 19:17:09 -0800165 mDockDivider = w;
Wale Ogunwale26b7b432016-02-03 14:12:08 -0800166 return;
167 }
168 if (w.mWillReplaceWindow) {
169 mReplacingWindows.add(w);
170 }
Robert Carrb9768772016-04-19 22:31:09 -0700171 if (w.mIsImWindow) {
172 mInputMethodWindows.add(w);
173 return;
174 }
Wale Ogunwaleca9e0612016-12-02 07:45:59 -0800175 if (mImeTarget != null) {
176 if (w.getParentWindow() == mImeTarget && w.mSubLayer > 0) {
177 // Child windows of the ime target with a positive sub-layer should be placed above
178 // the IME.
179 mAboveImeTargetAppWindows.add(w);
180 } else if (mAboveImeTarget && w.mAppToken != null) {
181 // windows of apps above the IME target should be placed above the IME.
182 mAboveImeTargetAppWindows.add(w);
183 }
184 if (w == mImeTarget) {
185 mAboveImeTarget = true;
186 }
187 }
188
Winson Chung1cebea62017-06-26 17:22:27 -0700189 final int stackId = w.getAppToken() != null ? w.getStackId() : INVALID_STACK_ID;
190 if (stackId == PINNED_STACK_ID) {
Wale Ogunwale26b7b432016-02-03 14:12:08 -0800191 mPinnedWindows.add(w);
Winson Chung1cebea62017-06-26 17:22:27 -0700192 } else if (stackId == DOCKED_STACK_ID) {
Wale Ogunwale26b7b432016-02-03 14:12:08 -0800193 mDockedWindows.add(w);
Winson Chung1cebea62017-06-26 17:22:27 -0700194 } else if (stackId == ASSISTANT_STACK_ID) {
Winson Chung83471632016-12-13 11:02:12 -0800195 mAssistantWindows.add(w);
Filip Gruszczynski92e432c2015-12-15 19:17:09 -0800196 }
197 }
198
199 private void adjustSpecialWindows() {
Winson Chung1cebea62017-06-26 17:22:27 -0700200 // The following adjustments are beyond the highest docked-affected layer
201 int layer = mHighestDockedAffectedLayer + WINDOW_LAYER_MULTIPLIER;
202
203 // Adjust the docked stack windows and dock divider above only the windows that are affected
204 // by the docked stack. When this happens, also boost the assistant window layers, otherwise
205 // the docked stack windows & divider would be promoted above the assistant.
206 if (!mDockedWindows.isEmpty() && mHighestDockedAffectedLayer > 0) {
207 while (!mDockedWindows.isEmpty()) {
208 final WindowState window = mDockedWindows.remove();
209 layer = assignAndIncreaseLayerIfNeeded(window, layer);
210 }
211
212 layer = assignAndIncreaseLayerIfNeeded(mDockDivider, layer);
213
214 while (!mAssistantWindows.isEmpty()) {
215 final WindowState window = mAssistantWindows.remove();
216 if (window.mLayer > mHighestDockedAffectedLayer) {
217 layer = assignAndIncreaseLayerIfNeeded(window, layer);
218 }
219 }
Wale Ogunwale26b7b432016-02-03 14:12:08 -0800220 }
Jorim Jaggi50981592015-12-29 17:54:12 +0100221
Winson Chung1cebea62017-06-26 17:22:27 -0700222 // The following adjustments are beyond the highest app layer or boosted layer
223 layer = Math.max(layer, mHighestApplicationLayer + WINDOW_LAYER_MULTIPLIER);
Robert Carr9da141f2016-04-05 14:24:22 -0700224
Wale Ogunwale26b7b432016-02-03 14:12:08 -0800225 // We know that we will be animating a relaunching window in the near future, which will
226 // receive a z-order increase. We want the replaced window to immediately receive the same
227 // treatment, e.g. to be above the dock divider.
228 while (!mReplacingWindows.isEmpty()) {
229 layer = assignAndIncreaseLayerIfNeeded(mReplacingWindows.remove(), layer);
230 }
231
232 while (!mPinnedWindows.isEmpty()) {
233 layer = assignAndIncreaseLayerIfNeeded(mPinnedWindows.remove(), layer);
234 }
Wale Ogunwale44fbdf52016-11-16 10:18:45 -0800235
236 // Make sure IME is the highest window in the base layer of it's target.
237 if (mImeTarget != null) {
238 if (mImeTarget.mAppToken == null) {
239 // For non-app ime targets adjust the layer we start from to match what we found
240 // when assigning layers. Otherwise, just use the highest app layer we have some far.
241 layer = mHighestLayerInImeTargetBaseLayer + WINDOW_LAYER_MULTIPLIER;
242 }
243
244 while (!mInputMethodWindows.isEmpty()) {
245 layer = assignAndIncreaseLayerIfNeeded(mInputMethodWindows.remove(), layer);
246 }
Wale Ogunwaleca9e0612016-12-02 07:45:59 -0800247
248 // Adjust app windows the should be displayed above the IME since they are above the IME
249 // target.
250 while (!mAboveImeTargetAppWindows.isEmpty()) {
251 layer = assignAndIncreaseLayerIfNeeded(mAboveImeTargetAppWindows.remove(), layer);
252 }
Wale Ogunwale44fbdf52016-11-16 10:18:45 -0800253 }
254
Filip Gruszczynski92e432c2015-12-15 19:17:09 -0800255 }
256
257 private int assignAndIncreaseLayerIfNeeded(WindowState win, int layer) {
Robert Carr90da5e52016-04-15 10:58:37 -0700258 if (win != null) {
Robert Carr67eec032016-03-22 16:57:33 -0700259 assignAnimLayer(win, layer);
Wale Ogunwale44fbdf52016-11-16 10:18:45 -0800260 // Make sure we leave space in-between normal windows for dims and such.
Robert Carr6412d752016-03-31 17:23:35 -0700261 layer += WINDOW_LAYER_MULTIPLIER;
Filip Gruszczynski92e432c2015-12-15 19:17:09 -0800262 }
263 return layer;
264 }
Robert Carr6412d752016-03-31 17:23:35 -0700265
Robert Carr67eec032016-03-22 16:57:33 -0700266 private void assignAnimLayer(WindowState w, int layer) {
267 w.mLayer = layer;
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700268 w.mWinAnimator.mAnimLayer = w.getAnimLayerAdjustment()
269 + w.getSpecialWindowAnimLayerAdjustment();
Matthew Ng7c706472017-05-05 17:12:18 -0700270 if (w.mAppToken != null && w.mAppToken.mAppAnimator.thumbnailForceAboveLayer > 0) {
271 if (w.mWinAnimator.mAnimLayer > w.mAppToken.mAppAnimator.thumbnailForceAboveLayer) {
272 w.mAppToken.mAppAnimator.thumbnailForceAboveLayer = w.mWinAnimator.mAnimLayer;
273 }
274 // TODO(b/62029108): the entire contents of the if statement should call the refactored
275 // function to set the thumbnail layer for w.AppToken
276 int highestLayer = w.mAppToken.getHighestAnimLayer();
277 if (highestLayer > 0) {
278 if (w.mAppToken.mAppAnimator.thumbnail != null
279 && w.mAppToken.mAppAnimator.thumbnailForceAboveLayer != highestLayer) {
280 w.mAppToken.mAppAnimator.thumbnailForceAboveLayer = highestLayer;
281 w.mAppToken.mAppAnimator.thumbnail.setLayer(highestLayer + 1);
282 }
283 }
Jorim Jaggic69bd222016-03-15 14:38:37 +0100284 }
Robert Carr67eec032016-03-22 16:57:33 -0700285 }
Filip Gruszczynski92e432c2015-12-15 19:17:09 -0800286}