blob: e6f281da5e6637f4d6b49958e969ec5b0a50acb5 [file] [log] [blame]
Craig Mautner59c00972012-07-30 12:10:24 -07001/*
2 * Copyright (C) 2012 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
17package com.android.server.wm;
18
Wale Ogunwale3797c222015-10-27 14:21:58 -070019import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
Wale Ogunwale51362492016-09-08 17:49:17 -070020import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
Wale Ogunwale3797c222015-10-27 14:21:58 -070021import static android.app.ActivityManager.StackId.HOME_STACK_ID;
22import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
Wale Ogunwalea77e1462016-09-28 10:09:46 -070023import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
Wale Ogunwale51362492016-09-08 17:49:17 -070024import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
25import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Wale Ogunwale19e452e2016-10-12 12:36:29 -070026import static android.view.Display.DEFAULT_DISPLAY;
27import static android.view.Display.FLAG_PRIVATE;
Andrii Kulian4dfb9c42016-10-11 20:06:27 -070028import static android.view.Surface.ROTATION_0;
29import static android.view.Surface.ROTATION_180;
30import static android.view.Surface.ROTATION_270;
31import static android.view.Surface.ROTATION_90;
Wale Ogunwale10124582016-09-15 20:25:50 -070032import static android.view.WindowManager.DOCKED_BOTTOM;
33import static android.view.WindowManager.DOCKED_INVALID;
34import static android.view.WindowManager.DOCKED_TOP;
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -070035import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
Vladislav Kaznacheev5d6bdeb2016-02-12 17:07:20 -080036import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
37import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
38import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -070039import static android.view.WindowManager.LayoutParams.NEEDS_MENU_SET_TRUE;
40import static android.view.WindowManager.LayoutParams.NEEDS_MENU_UNSET;
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -070041import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
Wale Ogunwaleec731152016-09-08 20:18:57 -070042import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
43import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
Svetoslav Ganovaa076532016-08-01 19:16:43 -070044import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
Wale Ogunwaleec731152016-09-08 20:18:57 -070045import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
46import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
Wale Ogunwale10124582016-09-15 20:25:50 -070047import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -070048import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
49import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -070050import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD;
Wale Ogunwalec69694a2016-10-18 13:51:15 -070051import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
Wale Ogunwale2b06bfc2016-09-28 14:17:05 -070052import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
Wale Ogunwaleec731152016-09-08 20:18:57 -070053import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080054import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
Wale Ogunwale51362492016-09-08 17:49:17 -070055import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -070056import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080057import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -070058import static com.android.server.wm.WindowManagerService.H.WINDOW_HIDE_TIMEOUT;
Wale Ogunwale19e452e2016-10-12 12:36:29 -070059import static com.android.server.wm.WindowManagerService.dipToPixel;
60import static com.android.server.wm.WindowManagerService.localLOGV;
Wale Ogunwale231b06e2015-09-16 12:03:09 -070061import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -070062
Andrii Kulian3a507b52016-09-19 18:14:12 -070063import android.annotation.NonNull;
Wale Ogunwale3797c222015-10-27 14:21:58 -070064import android.app.ActivityManager.StackId;
Andrii Kulian441e4492016-09-29 15:25:00 -070065import android.content.res.Configuration;
Andrii Kulian4dfb9c42016-10-11 20:06:27 -070066import android.graphics.Matrix;
Craig Mautnerc00204b2013-03-05 15:02:14 -080067import android.graphics.Rect;
Andrii Kulian4dfb9c42016-10-11 20:06:27 -070068import android.graphics.RectF;
Craig Mautner6601b7b2013-04-29 10:29:11 -070069import android.graphics.Region;
Jorim Jaggid47e7e12016-03-01 09:57:38 +010070import android.graphics.Region.Op;
Wale Ogunwaleb699ce02016-07-18 12:05:30 -070071import android.hardware.display.DisplayManagerInternal;
Wale Ogunwale9adfe572016-09-08 20:43:58 -070072import android.os.Debug;
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -070073import android.os.Handler;
Wale Ogunwale02319a62016-09-26 15:21:22 -070074import android.os.IBinder;
Chong Zhang8e89b312015-09-09 15:09:30 -070075import android.util.DisplayMetrics;
Craig Mautnerde4ef022013-04-07 19:01:33 -070076import android.util.Slog;
Craig Mautnerb47bbc32012-08-22 17:41:48 -070077import android.view.Display;
Craig Mautner59c00972012-07-30 12:10:24 -070078import android.view.DisplayInfo;
Wale Ogunwaleec731152016-09-08 20:18:57 -070079import android.view.IWindow;
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -070080import android.view.WindowManager;
81import android.view.WindowManagerPolicy;
Wale Ogunwale19e452e2016-10-12 12:36:29 -070082
Wale Ogunwale9adfe572016-09-08 20:43:58 -070083import com.android.internal.util.FastPrintWriter;
Craig Mautner59c00972012-07-30 12:10:24 -070084
Robert Carr3b716242016-08-16 16:02:21 -070085import java.io.FileDescriptor;
Craig Mautner59c00972012-07-30 12:10:24 -070086import java.io.PrintWriter;
Wale Ogunwale9adfe572016-09-08 20:43:58 -070087import java.io.StringWriter;
Craig Mautner59c00972012-07-30 12:10:24 -070088import java.util.ArrayList;
Wale Ogunwale9adfe572016-09-08 20:43:58 -070089import java.util.Arrays;
Wale Ogunwale19e452e2016-10-12 12:36:29 -070090import java.util.Comparator;
Wale Ogunwale02319a62016-09-26 15:21:22 -070091import java.util.HashMap;
92import java.util.Iterator;
Andrii Kulian3a507b52016-09-19 18:14:12 -070093import java.util.List;
Craig Mautner59c00972012-07-30 12:10:24 -070094
Craig Mautner59c00972012-07-30 12:10:24 -070095/**
96 * Utility class for keeping track of the WindowStates and other pertinent contents of a
97 * particular Display.
98 *
99 * IMPORTANT: No method from this class should ever be used without holding
100 * WindowManagerService.mWindowMap.
101 */
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700102class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowContainer> {
Craig Mautner59c00972012-07-30 12:10:24 -0700103
104 /** Unique identifier of this stack. */
105 private final int mDisplayId;
106
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700107 // The display only has 2 child window containers. mTaskStackContainers which contains all
108 // window containers that are related to apps (Activities) and mNonAppWindowContainers which
109 // contains all window containers not related to apps (e.g. Status bar).
110 private final TaskStackContainers mTaskStackContainers = new TaskStackContainers();
111 private final NonAppWindowContainers mNonAppWindowContainers = new NonAppWindowContainers();
112
Craig Mautner59c00972012-07-30 12:10:24 -0700113 /** Z-ordered (bottom-most first) list of all Window objects. Assigned to an element
114 * from mDisplayWindows; */
Craig Mautnerdc548482014-02-05 13:35:24 -0800115 private final WindowList mWindows = new WindowList();
Craig Mautner59c00972012-07-30 12:10:24 -0700116
Wale Ogunwale02319a62016-09-26 15:21:22 -0700117 // Mapping from a token IBinder to a WindowToken object on this display.
118 private final HashMap<IBinder, WindowToken> mTokenMap = new HashMap();
119
Craig Mautner59c00972012-07-30 12:10:24 -0700120 int mInitialDisplayWidth = 0;
121 int mInitialDisplayHeight = 0;
Dianne Hackborndde331c2012-08-03 14:01:57 -0700122 int mInitialDisplayDensity = 0;
Craig Mautner59c00972012-07-30 12:10:24 -0700123 int mBaseDisplayWidth = 0;
124 int mBaseDisplayHeight = 0;
Dianne Hackborndde331c2012-08-03 14:01:57 -0700125 int mBaseDisplayDensity = 0;
Jeff Brownd46747a2015-04-15 19:02:36 -0700126 boolean mDisplayScalingDisabled;
Craig Mautner2d5618c2012-10-18 13:55:47 -0700127 private final DisplayInfo mDisplayInfo = new DisplayInfo();
128 private final Display mDisplay;
Wale Ogunwale231b06e2015-09-16 12:03:09 -0700129 private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
Craig Mautner59c00972012-07-30 12:10:24 -0700130
Craig Mautner6601b7b2013-04-29 10:29:11 -0700131 Rect mBaseDisplayRect = new Rect();
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700132 private Rect mContentRect = new Rect();
Craig Mautner6601b7b2013-04-29 10:29:11 -0700133
Craig Mautner39834192012-09-02 07:47:24 -0700134 // Accessed directly by all users.
Wale Ogunwale2b06bfc2016-09-28 14:17:05 -0700135 private boolean mLayoutNeeded;
Craig Mautner76a71652012-09-03 23:23:58 -0700136 int pendingLayoutChanges;
Craig Mautner69b08182012-09-05 13:07:13 -0700137 final boolean isDefaultDisplay;
Craig Mautner39834192012-09-02 07:47:24 -0700138
Craig Mautnerdc548482014-02-05 13:35:24 -0800139 /** Window tokens that are in the process of exiting, but still on screen for animations. */
Wale Ogunwale231b06e2015-09-16 12:03:09 -0700140 final ArrayList<WindowToken> mExitingTokens = new ArrayList<>();
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800141
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800142 /** A special TaskStack with id==HOME_STACK_ID that moves to the bottom whenever any TaskStack
143 * (except a future lockscreen TaskStack) moves to the top. */
Craig Mautnerde4ef022013-04-07 19:01:33 -0700144 private TaskStack mHomeStack = null;
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700145
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700146 /** Detect user tapping outside of current focused task bounds .*/
147 TaskTapPointerEventListener mTapDetector;
Craig Mautnercf910b02013-04-23 11:23:27 -0700148
Craig Mautner6601b7b2013-04-29 10:29:11 -0700149 /** Detect user tapping outside of current focused stack bounds .*/
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700150 private Region mTouchExcludeRegion = new Region();
Craig Mautner6601b7b2013-04-29 10:29:11 -0700151
Craig Mautner6601b7b2013-04-29 10:29:11 -0700152 /** Save allocating when calculating rects */
Filip Gruszczynski912d9192015-12-01 16:14:04 -0800153 private final Rect mTmpRect = new Rect();
154 private final Rect mTmpRect2 = new Rect();
Andrii Kulian4dfb9c42016-10-11 20:06:27 -0700155 private final RectF mTmpRectF = new RectF();
156 private final Matrix mTmpMatrix = new Matrix();
Filip Gruszczynski912d9192015-12-01 16:14:04 -0800157 private final Region mTmpRegion = new Region();
Craig Mautner6601b7b2013-04-29 10:29:11 -0700158
Craig Mautner9d808b12013-08-06 18:00:25 -0700159 final WindowManagerService mService;
160
Craig Mautner95da1082014-02-24 17:54:35 -0800161 /** Remove this display when animation on it has completed. */
Wale Ogunwaled4a00a02016-10-10 11:29:17 -0700162 private boolean mDeferredRemoval;
Craig Mautner1bf2b872014-02-05 15:37:40 -0800163
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700164 final DockedStackDividerController mDividerControllerLocked;
165
Chong Zhang112eb8c2015-11-02 11:17:00 -0800166 final DimLayerController mDimLayerController;
Filip Gruszczynski0689ae92015-10-01 12:30:31 -0700167
Filip Gruszczynskiecf67222015-12-11 15:16:36 -0800168 final ArrayList<WindowState> mTapExcludedWindows = new ArrayList<>();
169
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700170 /** Used when rebuilding window list to keep track of windows that have been removed. */
171 private WindowState[] mRebuildTmp = new WindowState[20];
172
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700173 private final TaskForResizePointSearchResult mTmpTaskForResizePointSearchResult =
174 new TaskForResizePointSearchResult();
175 private final GetWindowOnDisplaySearchResult mTmpGetWindowOnDisplaySearchResult =
176 new GetWindowOnDisplaySearchResult();
177
Wale Ogunwale601a3f02016-10-17 08:39:39 -0700178 // True if this display is in the process of being removed. Used to determine if the removal of
179 // the display's direct children should be allowed.
180 private boolean mRemovingDisplay = false;
181
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700182 private final WindowLayersController mLayersController;
183 int mInputMethodAnimLayerAdjustment;
184
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800185 /**
Craig Mautner2d5618c2012-10-18 13:55:47 -0700186 * @param display May not be null.
Craig Mautnerdf88d732014-01-27 09:21:32 -0800187 * @param service You know.
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700188 * @param layersController window layer controller used to assign layer to the windows on this
189 * display.
Craig Mautner2d5618c2012-10-18 13:55:47 -0700190 */
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700191 DisplayContent(Display display, WindowManagerService service,
192 WindowLayersController layersController) {
Craig Mautnerb47bbc32012-08-22 17:41:48 -0700193 mDisplay = display;
194 mDisplayId = display.getDisplayId();
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700195 mLayersController = layersController;
Craig Mautnerb47bbc32012-08-22 17:41:48 -0700196 display.getDisplayInfo(mDisplayInfo);
Wale Ogunwale231b06e2015-09-16 12:03:09 -0700197 display.getMetrics(mDisplayMetrics);
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700198 isDefaultDisplay = mDisplayId == DEFAULT_DISPLAY;
Craig Mautner9d808b12013-08-06 18:00:25 -0700199 mService = service;
Wale Ogunwalefd04d8c2015-09-30 10:09:39 -0700200 initializeDisplayBaseInfo();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800201 mDividerControllerLocked = new DockedStackDividerController(service, this);
Chong Zhang112eb8c2015-11-02 11:17:00 -0800202 mDimLayerController = new DimLayerController(this);
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700203
204 // These are the only direct children we should ever have and they are permanent.
205 super.addChild(mTaskStackContainers, null);
206 super.addChild(mNonAppWindowContainers, null);
Craig Mautner59c00972012-07-30 12:10:24 -0700207 }
208
209 int getDisplayId() {
210 return mDisplayId;
211 }
212
213 WindowList getWindowList() {
214 return mWindows;
215 }
216
Wale Ogunwale02319a62016-09-26 15:21:22 -0700217 WindowToken getWindowToken(IBinder binder) {
218 return mTokenMap.get(binder);
219 }
220
221 AppWindowToken getAppWindowToken(IBinder binder) {
222 final WindowToken token = getWindowToken(binder);
223 if (token == null) {
224 return null;
225 }
226 return token.asAppWindowToken();
227 }
228
229 void setWindowToken(IBinder binder, WindowToken token) {
230 final DisplayContent dc = mService.mRoot.getWindowTokenDisplay(token);
231 if (dc != null) {
232 // We currently don't support adding a window token to the display if the display
233 // already has the binder mapped to another token. If there is a use case for supporting
234 // this moving forward we will either need to merge the WindowTokens some how or have
235 // the binder map to a list of window tokens.
236 throw new IllegalArgumentException("Can't map token=" + token + " to display=" + this
237 + " already mapped to display=" + dc + " tokens=" + dc.mTokenMap);
238 }
239 mTokenMap.put(binder, token);
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700240
241 if (token.asAppWindowToken() == null) {
242 // Add non-app token to container hierarchy on the display. App tokens are added through
243 // the parent container managing them (e.g. Tasks).
244 mNonAppWindowContainers.addChild(token, null);
245 }
Wale Ogunwale02319a62016-09-26 15:21:22 -0700246 }
247
248 WindowToken removeWindowToken(IBinder binder) {
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700249 final WindowToken token = mTokenMap.remove(binder);
250 if (token != null && token.asAppWindowToken() == null) {
251 mNonAppWindowContainers.removeChild(token);
252 }
253 return token;
Wale Ogunwale02319a62016-09-26 15:21:22 -0700254 }
255
Craig Mautnerb47bbc32012-08-22 17:41:48 -0700256 Display getDisplay() {
257 return mDisplay;
258 }
259
Craig Mautner59c00972012-07-30 12:10:24 -0700260 DisplayInfo getDisplayInfo() {
261 return mDisplayInfo;
262 }
263
Wale Ogunwale231b06e2015-09-16 12:03:09 -0700264 DisplayMetrics getDisplayMetrics() {
265 return mDisplayMetrics;
266 }
267
Jorim Jaggi61f39a72015-10-29 16:54:18 +0100268 DockedStackDividerController getDockedDividerController() {
269 return mDividerControllerLocked;
270 }
271
Jeff Browna506a6e2013-06-04 00:02:38 -0700272 /**
273 * Returns true if the specified UID has access to this display.
274 */
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700275 boolean hasAccess(int uid) {
Jeff Browna506a6e2013-06-04 00:02:38 -0700276 return mDisplay.hasAccess(uid);
277 }
278
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700279 boolean isPrivate() {
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700280 return (mDisplay.getFlags() & FLAG_PRIVATE) != 0;
keunyounga446bf02013-06-21 19:07:57 -0700281 }
282
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700283 TaskStack getHomeStack() {
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700284 if (mHomeStack == null && mDisplayId == DEFAULT_DISPLAY) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800285 Slog.e(TAG_WM, "getHomeStack: Returning null from this=" + this);
Craig Mautnere0a38842013-12-16 16:14:02 -0800286 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700287 return mHomeStack;
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700288 }
289
Chong Zhangd9d35bd2016-08-04 17:55:21 -0700290 TaskStack getStackById(int stackId) {
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700291 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
292 final TaskStack stack = mTaskStackContainers.get(i);
Chong Zhangd9d35bd2016-08-04 17:55:21 -0700293 if (stack.mStackId == stackId) {
294 return stack;
295 }
296 }
297 return null;
298 }
299
Andrii Kulian441e4492016-09-29 15:25:00 -0700300 @Override
301 void onConfigurationChanged(Configuration newParentConfig) {
302 super.onConfigurationChanged(newParentConfig);
303
Andrii Kulian3a507b52016-09-19 18:14:12 -0700304 // The display size information is heavily dependent on the resources in the current
305 // configuration, so we need to reconfigure it every time the configuration changes.
306 // See {@link PhoneWindowManager#setInitialDisplaySize}...sigh...
307 mService.reconfigureDisplayLocked(this);
308
309 getDockedDividerController().onConfigurationChanged();
Andrii Kulian441e4492016-09-29 15:25:00 -0700310 }
Andrii Kulian3a507b52016-09-19 18:14:12 -0700311
Andrii Kulian441e4492016-09-29 15:25:00 -0700312 /**
313 * Callback used to trigger bounds update after configuration change and get ids of stacks whose
314 * bounds were updated.
315 */
316 void updateStackBoundsAfterConfigChange(@NonNull List<Integer> changedStackList) {
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700317 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
318 final TaskStack stack = mTaskStackContainers.get(i);
Andrii Kulian441e4492016-09-29 15:25:00 -0700319 if (stack.updateBoundsAfterConfigChange()) {
Andrii Kulian3a507b52016-09-19 18:14:12 -0700320 changedStackList.add(stack.mStackId);
321 }
322 }
323 }
324
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700325 @Override
326 boolean fillsParent() {
327 return true;
328 }
329
330 @Override
331 boolean isVisible() {
332 return true;
333 }
334
335 @Override
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700336 void onAppTransitionDone() {
Wale Ogunwale10124582016-09-15 20:25:50 -0700337 super.onAppTransitionDone();
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700338 rebuildAppWindowList();
339 }
340
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700341 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -0700342 int getOrientation() {
Wale Ogunwale51362492016-09-08 17:49:17 -0700343 if (mService.isStackVisibleLocked(DOCKED_STACK_ID)
344 || mService.isStackVisibleLocked(FREEFORM_WORKSPACE_STACK_ID)) {
345 // Apps and their containers are not allowed to specify an orientation while the docked
346 // or freeform stack is visible...except for the home stack/task if the docked stack is
347 // minimized and it actually set something.
Andrii Kulian8072d112016-09-16 11:11:01 -0700348 if (mHomeStack != null && mHomeStack.isVisible()
349 && mDividerControllerLocked.isMinimizedDock()) {
Wale Ogunwale51362492016-09-08 17:49:17 -0700350 final int orientation = mHomeStack.getOrientation();
351 if (orientation != SCREEN_ORIENTATION_UNSET) {
352 return orientation;
353 }
354 }
355 return SCREEN_ORIENTATION_UNSPECIFIED;
356 }
357
Wale Ogunwale10124582016-09-15 20:25:50 -0700358 final int orientation = super.getOrientation();
Wale Ogunwalea77e1462016-09-28 10:09:46 -0700359 if (orientation != SCREEN_ORIENTATION_UNSET && orientation != SCREEN_ORIENTATION_BEHIND) {
Wale Ogunwale10124582016-09-15 20:25:50 -0700360 if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
361 "App is requesting an orientation, return " + orientation);
362 return orientation;
Wale Ogunwale51362492016-09-08 17:49:17 -0700363 }
364
365 if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
366 "No app is requesting an orientation, return " + mService.mLastOrientation);
367 // The next app has not been requested to be visible, so we keep the current orientation
368 // to prevent freezing/unfreezing the display too early.
369 return mService.mLastOrientation;
370 }
371
Craig Mautner46ac6fa2013-08-01 10:06:34 -0700372 void updateDisplayInfo() {
Craig Mautner722285e2012-09-07 13:55:58 -0700373 mDisplay.getDisplayInfo(mDisplayInfo);
Wale Ogunwale231b06e2015-09-16 12:03:09 -0700374 mDisplay.getMetrics(mDisplayMetrics);
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700375 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
376 mTaskStackContainers.get(i).updateDisplayInfo(null);
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800377 }
Craig Mautner722285e2012-09-07 13:55:58 -0700378 }
379
Wale Ogunwalefd04d8c2015-09-30 10:09:39 -0700380 void initializeDisplayBaseInfo() {
Wale Ogunwaleb699ce02016-07-18 12:05:30 -0700381 final DisplayManagerInternal displayManagerInternal = mService.mDisplayManagerInternal;
382 if (displayManagerInternal != null) {
383 // Bootstrap the default logical display from the display manager.
384 final DisplayInfo newDisplayInfo = displayManagerInternal.getDisplayInfo(mDisplayId);
385 if (newDisplayInfo != null) {
386 mDisplayInfo.copyFrom(newDisplayInfo);
387 }
Wale Ogunwalefd04d8c2015-09-30 10:09:39 -0700388 }
Wale Ogunwaleb699ce02016-07-18 12:05:30 -0700389
Filip Gruszczynski608797e2015-11-12 19:08:20 -0800390 mBaseDisplayWidth = mInitialDisplayWidth = mDisplayInfo.logicalWidth;
391 mBaseDisplayHeight = mInitialDisplayHeight = mDisplayInfo.logicalHeight;
392 mBaseDisplayDensity = mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi;
393 mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight);
Wale Ogunwalefd04d8c2015-09-30 10:09:39 -0700394 }
395
Craig Mautner46ac6fa2013-08-01 10:06:34 -0700396 void getLogicalDisplayRect(Rect out) {
Craig Mautner46ac6fa2013-08-01 10:06:34 -0700397 // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked.
Craig Mautner4a1cb222013-12-04 16:14:06 -0800398 final int orientation = mDisplayInfo.rotation;
Andrii Kulian4dfb9c42016-10-11 20:06:27 -0700399 boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270);
Craig Mautner4a1cb222013-12-04 16:14:06 -0800400 final int physWidth = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
401 final int physHeight = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
Craig Mautner46ac6fa2013-08-01 10:06:34 -0700402 int width = mDisplayInfo.logicalWidth;
Craig Mautner4a1cb222013-12-04 16:14:06 -0800403 int left = (physWidth - width) / 2;
Craig Mautner46ac6fa2013-08-01 10:06:34 -0700404 int height = mDisplayInfo.logicalHeight;
Craig Mautner4a1cb222013-12-04 16:14:06 -0800405 int top = (physHeight - height) / 2;
Craig Mautner46ac6fa2013-08-01 10:06:34 -0700406 out.set(left, top, left + width, top + height);
407 }
408
Andrii Kulian4dfb9c42016-10-11 20:06:27 -0700409 private void getLogicalDisplayRect(Rect out, int orientation) {
410 getLogicalDisplayRect(out);
411
412 // Rotate the Rect if needed.
413 final int currentRotation = mDisplayInfo.rotation;
414 final int rotationDelta = deltaRotation(currentRotation, orientation);
415 if (rotationDelta == ROTATION_90 || rotationDelta == ROTATION_270) {
416 createRotationMatrix(rotationDelta, mBaseDisplayWidth, mBaseDisplayHeight, mTmpMatrix);
417 mTmpRectF.set(out);
418 mTmpMatrix.mapRect(mTmpRectF);
419 mTmpRectF.round(out);
420 }
421 }
422
Chong Zhangf66db432016-01-13 10:39:51 -0800423 void getContentRect(Rect out) {
424 out.set(mContentRect);
425 }
426
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700427 /** Refer to {@link WindowManagerService#attachStack(int, int, boolean)} */
428 void attachStack(TaskStack stack, boolean onTop) {
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700429 mTaskStackContainers.attachStack(stack, onTop);
Craig Mautnerc00204b2013-03-05 15:02:14 -0800430 }
431
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800432 void moveStack(TaskStack stack, boolean toTop) {
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700433 mTaskStackContainers.moveStack(stack, toTop);
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700434 }
Wale Ogunwale1e60e0c2015-10-28 13:36:10 -0700435
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700436 @Override
437 protected void addChild(DisplayChildWindowContainer child,
438 Comparator<DisplayChildWindowContainer> comparator) {
439 throw new UnsupportedOperationException("See DisplayChildWindowContainer");
440 }
Wale Ogunwale1e60e0c2015-10-28 13:36:10 -0700441
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700442 @Override
443 protected void addChild(DisplayChildWindowContainer child, int index) {
444 throw new UnsupportedOperationException("See DisplayChildWindowContainer");
445 }
446
447 @Override
448 protected void removeChild(DisplayChildWindowContainer child) {
Wale Ogunwale601a3f02016-10-17 08:39:39 -0700449 // Only allow removal of direct children from this display if the display is in the process
450 // of been removed.
451 if (mRemovingDisplay) {
452 super.removeChild(child);
453 return;
454 }
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700455 throw new UnsupportedOperationException("See DisplayChildWindowContainer");
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800456 }
457
458 /**
459 * Propagate the new bounds to all child stacks.
460 * @param contentRect The bounds to apply at the top level.
461 */
462 void resize(Rect contentRect) {
463 mContentRect.set(contentRect);
464 }
465
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700466 int taskIdFromPoint(int x, int y) {
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700467 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
468 final TaskStack stack = mTaskStackContainers.get(stackNdx);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700469 final int taskId = stack.taskIdFromPoint(x, y);
470 if (taskId != -1) {
471 return taskId;
Craig Mautner967212c2013-04-13 21:10:58 -0700472 }
473 }
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800474 return -1;
Craig Mautnercf910b02013-04-23 11:23:27 -0700475 }
476
Chong Zhang8e89b312015-09-09 15:09:30 -0700477 /**
Chong Zhangd8ceb852015-11-11 14:53:41 -0800478 * Find the task whose outside touch area (for resizing) (x, y) falls within.
Chong Zhang9184ec62015-09-24 12:32:21 -0700479 * Returns null if the touch doesn't fall into a resizing area.
Chong Zhang8e89b312015-09-09 15:09:30 -0700480 */
Wale Ogunwale15ead902016-09-02 14:30:11 -0700481 Task findTaskForResizePoint(int x, int y) {
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700482 final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700483 mTmpTaskForResizePointSearchResult.reset();
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700484 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
485 final TaskStack stack = mTaskStackContainers.get(stackNdx);
Wale Ogunwale3797c222015-10-27 14:21:58 -0700486 if (!StackId.isTaskResizeAllowed(stack.mStackId)) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700487 return null;
Chong Zhang8e89b312015-09-09 15:09:30 -0700488 }
Chong Zhang9184ec62015-09-24 12:32:21 -0700489
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700490 stack.findTaskForResizePoint(x, y, delta, mTmpTaskForResizePointSearchResult);
491 if (mTmpTaskForResizePointSearchResult.searchDone) {
492 return mTmpTaskForResizePointSearchResult.taskForResize;
Chong Zhang8e89b312015-09-09 15:09:30 -0700493 }
494 }
Chong Zhang9184ec62015-09-24 12:32:21 -0700495 return null;
Chong Zhang8e89b312015-09-09 15:09:30 -0700496 }
497
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700498 void setTouchExcludeRegion(Task focusedTask) {
Craig Mautner6601b7b2013-04-29 10:29:11 -0700499 mTouchExcludeRegion.set(mBaseDisplayRect);
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700500 final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700501 mTmpRect2.setEmpty();
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700502 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
503 final TaskStack stack = mTaskStackContainers.get(stackNdx);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700504 stack.setTouchExcludeRegion(
505 focusedTask, delta, mTouchExcludeRegion, mContentRect, mTmpRect2);
Craig Mautner6601b7b2013-04-29 10:29:11 -0700506 }
Chong Zhangd8ceb852015-11-11 14:53:41 -0800507 // If we removed the focused task above, add it back and only leave its
508 // outside touch area in the exclusion. TapDectector is not interested in
509 // any touch inside the focused task itself.
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700510 if (!mTmpRect2.isEmpty()) {
Chong Zhangd8ceb852015-11-11 14:53:41 -0800511 mTouchExcludeRegion.op(mTmpRect2, Region.Op.UNION);
512 }
Filip Gruszczynski912d9192015-12-01 16:14:04 -0800513 final WindowState inputMethod = mService.mInputMethodWindow;
514 if (inputMethod != null && inputMethod.isVisibleLw()) {
515 // If the input method is visible and the user is typing, we don't want these touch
516 // events to be intercepted and used to change focus. This would likely cause a
517 // disappearance of the input method.
518 inputMethod.getTouchableRegion(mTmpRegion);
519 mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION);
520 }
Filip Gruszczynskiecf67222015-12-11 15:16:36 -0800521 for (int i = mTapExcludedWindows.size() - 1; i >= 0; i--) {
522 WindowState win = mTapExcludedWindows.get(i);
523 win.getTouchableRegion(mTmpRegion);
524 mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION);
525 }
Jorim Jaggid47e7e12016-03-01 09:57:38 +0100526 if (getDockedStackVisibleForUserLocked() != null) {
527 mDividerControllerLocked.getTouchRegion(mTmpRect);
Jorim Jaggi7f19cb82016-03-25 19:37:44 -0700528 mTmpRegion.set(mTmpRect);
Jorim Jaggid47e7e12016-03-01 09:57:38 +0100529 mTouchExcludeRegion.op(mTmpRegion, Op.UNION);
530 }
Craig Mautner1bef3892015-02-17 15:09:47 -0800531 if (mTapDetector != null) {
Chong Zhang2e2c81a2016-07-15 11:28:17 -0700532 mTapDetector.setTouchExcludeRegion(mTouchExcludeRegion);
Craig Mautner1bef3892015-02-17 15:09:47 -0800533 }
Craig Mautner6601b7b2013-04-29 10:29:11 -0700534 }
535
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700536 void switchUser() {
Craig Mautner858d8a62013-04-23 17:08:34 -0700537 final WindowList windows = getWindowList();
538 for (int i = 0; i < windows.size(); i++) {
539 final WindowState win = windows.get(i);
540 if (win.isHiddenFromUserLocked()) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800541 if (DEBUG_VISIBILITY) Slog.w(TAG_WM, "user changing, hiding " + win
Wale Ogunwale498e8c92015-02-13 09:42:46 -0800542 + ", attrs=" + win.mAttrs.type + ", belonging to " + win.mOwnerUid);
Craig Mautner858d8a62013-04-23 17:08:34 -0700543 win.hideLw(false);
544 }
545 }
Craig Mautnerac6f8432013-07-17 13:24:59 -0700546
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700547 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
548 mTaskStackContainers.get(stackNdx).switchUser();
Craig Mautner858d8a62013-04-23 17:08:34 -0700549 }
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700550
551 rebuildAppWindowList();
Craig Mautner858d8a62013-04-23 17:08:34 -0700552 }
553
Craig Mautner05d29032013-05-03 13:40:13 -0700554 void resetAnimationBackgroundAnimator() {
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700555 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
556 mTaskStackContainers.get(stackNdx).resetAnimationBackgroundAnimator();
Craig Mautner05d29032013-05-03 13:40:13 -0700557 }
558 }
559
560 boolean animateDimLayers() {
Chong Zhang112eb8c2015-11-02 11:17:00 -0800561 return mDimLayerController.animateDimLayers();
Craig Mautner05d29032013-05-03 13:40:13 -0700562 }
563
564 void resetDimming() {
Chong Zhang112eb8c2015-11-02 11:17:00 -0800565 mDimLayerController.resetDimming();
Craig Mautner05d29032013-05-03 13:40:13 -0700566 }
567
568 boolean isDimming() {
Chong Zhang112eb8c2015-11-02 11:17:00 -0800569 return mDimLayerController.isDimming();
Craig Mautner05d29032013-05-03 13:40:13 -0700570 }
571
572 void stopDimmingIfNeeded() {
Chong Zhang112eb8c2015-11-02 11:17:00 -0800573 mDimLayerController.stopDimmingIfNeeded();
Craig Mautner05d29032013-05-03 13:40:13 -0700574 }
575
Wale Ogunwale10124582016-09-15 20:25:50 -0700576 @Override
577 void removeIfPossible() {
578 if (isAnimating()) {
579 mDeferredRemoval = true;
580 return;
Craig Mautner2eb15342013-08-07 13:13:35 -0700581 }
Wale Ogunwale10124582016-09-15 20:25:50 -0700582 removeImmediately();
Craig Mautner2eb15342013-08-07 13:13:35 -0700583 }
584
Wale Ogunwale10124582016-09-15 20:25:50 -0700585 @Override
586 void removeImmediately() {
Wale Ogunwale601a3f02016-10-17 08:39:39 -0700587 mRemovingDisplay = true;
588 try {
589 super.removeImmediately();
590 if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this);
591 mDimLayerController.close();
592 if (mDisplayId == DEFAULT_DISPLAY) {
593 mService.unregisterPointerEventListener(mTapDetector);
594 mService.unregisterPointerEventListener(mService.mMousePositionTracker);
595 }
596 } finally {
597 mRemovingDisplay = false;
Craig Mautner95da1082014-02-24 17:54:35 -0800598 }
Craig Mautner95da1082014-02-24 17:54:35 -0800599 }
600
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700601 /** Returns true if a removal action is still being deferred. */
Wale Ogunwale10124582016-09-15 20:25:50 -0700602 @Override
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700603 boolean checkCompleteDeferredRemoval() {
Wale Ogunwale10124582016-09-15 20:25:50 -0700604 final boolean stillDeferringRemoval = super.checkCompleteDeferredRemoval();
605
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700606 if (!stillDeferringRemoval && mDeferredRemoval) {
Wale Ogunwale10124582016-09-15 20:25:50 -0700607 removeImmediately();
Craig Mautner95da1082014-02-24 17:54:35 -0800608 mService.onDisplayRemoved(mDisplayId);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700609 return false;
Craig Mautner95da1082014-02-24 17:54:35 -0800610 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700611 return true;
Craig Mautner95da1082014-02-24 17:54:35 -0800612 }
613
Wale Ogunwale10124582016-09-15 20:25:50 -0700614 boolean animateForIme(float interpolatedValue, float animationTarget,
615 float dividerAnimationTarget) {
616 boolean updated = false;
617
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700618 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
619 final TaskStack stack = mTaskStackContainers.get(i);
Wale Ogunwale10124582016-09-15 20:25:50 -0700620 if (stack == null || !stack.isAdjustedForIme()) {
621 continue;
622 }
623
624 if (interpolatedValue >= 1f && animationTarget == 0f && dividerAnimationTarget == 0f) {
625 stack.resetAdjustedForIme(true /* adjustBoundsNow */);
626 updated = true;
627 } else {
628 mDividerControllerLocked.mLastAnimationProgress =
629 mDividerControllerLocked.getInterpolatedAnimationValue(interpolatedValue);
630 mDividerControllerLocked.mLastDividerProgress =
631 mDividerControllerLocked.getInterpolatedDividerValue(interpolatedValue);
632 updated |= stack.updateAdjustForIme(
633 mDividerControllerLocked.mLastAnimationProgress,
634 mDividerControllerLocked.mLastDividerProgress,
635 false /* force */);
636 }
637 if (interpolatedValue >= 1f) {
638 stack.endImeAdjustAnimation();
639 }
640 }
641
642 return updated;
643 }
644
645 boolean clearImeAdjustAnimation() {
646 boolean changed = false;
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700647 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
648 final TaskStack stack = mTaskStackContainers.get(i);
Wale Ogunwale10124582016-09-15 20:25:50 -0700649 if (stack != null && stack.isAdjustedForIme()) {
650 stack.resetAdjustedForIme(true /* adjustBoundsNow */);
651 changed = true;
652 }
653 }
654 return changed;
655 }
656
657 void beginImeAdjustAnimation() {
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700658 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
659 final TaskStack stack = mTaskStackContainers.get(i);
Wale Ogunwale10124582016-09-15 20:25:50 -0700660 if (stack.isVisible() && stack.isAdjustedForIme()) {
661 stack.beginImeAdjustAnimation();
662 }
663 }
664 }
665
666 void adjustForImeIfNeeded() {
667 final WindowState imeWin = mService.mInputMethodWindow;
668 final boolean imeVisible = imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw()
669 && !mDividerControllerLocked.isImeHideRequested();
670 final boolean dockVisible = mService.isStackVisibleLocked(DOCKED_STACK_ID);
671 final TaskStack imeTargetStack = mService.getImeFocusStackLocked();
672 final int imeDockSide = (dockVisible && imeTargetStack != null) ?
673 imeTargetStack.getDockSide() : DOCKED_INVALID;
674 final boolean imeOnTop = (imeDockSide == DOCKED_TOP);
675 final boolean imeOnBottom = (imeDockSide == DOCKED_BOTTOM);
676 final boolean dockMinimized = mDividerControllerLocked.isMinimizedDock();
677 final int imeHeight = mService.mPolicy.getInputMethodWindowVisibleHeightLw();
678 final boolean imeHeightChanged = imeVisible &&
679 imeHeight != mDividerControllerLocked.getImeHeightAdjustedFor();
680
681 // The divider could be adjusted for IME position, or be thinner than usual,
682 // or both. There are three possible cases:
683 // - If IME is visible, and focus is on top, divider is not moved for IME but thinner.
684 // - If IME is visible, and focus is on bottom, divider is moved for IME and thinner.
685 // - If IME is not visible, divider is not moved and is normal width.
686
687 if (imeVisible && dockVisible && (imeOnTop || imeOnBottom) && !dockMinimized) {
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700688 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
689 final TaskStack stack = mTaskStackContainers.get(i);
Wale Ogunwale10124582016-09-15 20:25:50 -0700690 final boolean isDockedOnBottom = stack.getDockSide() == DOCKED_BOTTOM;
691 if (stack.isVisible() && (imeOnBottom || isDockedOnBottom)) {
692 stack.setAdjustedForIme(imeWin, imeOnBottom && imeHeightChanged);
693 } else {
694 stack.resetAdjustedForIme(false);
695 }
696 }
697 mDividerControllerLocked.setAdjustedForIme(
698 imeOnBottom /*ime*/, true /*divider*/, true /*animate*/, imeWin, imeHeight);
699 } else {
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700700 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
701 final TaskStack stack = mTaskStackContainers.get(i);
Wale Ogunwale10124582016-09-15 20:25:50 -0700702 stack.resetAdjustedForIme(!dockVisible);
703 }
704 mDividerControllerLocked.setAdjustedForIme(
705 false /*ime*/, false /*divider*/, dockVisible /*animate*/, imeWin, imeHeight);
706 }
707 }
708
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700709 void setInputMethodAnimLayerAdjustment(int adj) {
710 if (DEBUG_LAYERS) Slog.v(TAG_WM, "Setting im layer adj to " + adj);
711 mInputMethodAnimLayerAdjustment = adj;
712 final WindowState imw = mService.mInputMethodWindow;
713 if (imw != null) {
714 imw.adjustAnimLayer(adj);
715 }
716 for (int i = mService.mInputMethodDialogs.size() - 1; i >= 0; i--) {
717 final WindowState dialog = mService.mInputMethodDialogs.get(i);
718 // TODO: This and other places setting mAnimLayer can probably use WS.adjustAnimLayer,
719 // but need to make sure we are not setting things twice for child windows that are
720 // already in the list.
721 dialog.mWinAnimator.mAnimLayer = dialog.mLayer + adj;
722 if (DEBUG_LAYERS) Slog.v(TAG_WM, "IM win " + imw
723 + " anim layer: " + dialog.mWinAnimator.mAnimLayer);
724 }
725 }
726
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -0700727 /**
728 * If a window that has an animation specifying a colored background and the current wallpaper
729 * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to
730 * suddenly disappear.
731 */
732 int getLayerForAnimationBackground(WindowStateAnimator winAnimator) {
733 for (int i = mWindows.size() - 1; i >= 0; --i) {
734 final WindowState win = mWindows.get(i);
735 if (win.mIsWallpaper && win.isVisibleNow()) {
736 return win.mWinAnimator.mAnimLayer;
737 }
738 }
739 return winAnimator.mAnimLayer;
740 }
741
Wale Ogunwale10124582016-09-15 20:25:50 -0700742 void prepareFreezingTaskBounds() {
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700743 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
744 final TaskStack stack = mTaskStackContainers.get(stackNdx);
Wale Ogunwale10124582016-09-15 20:25:50 -0700745 stack.prepareFreezingTaskBounds();
746 }
747 }
748
Wale Ogunwale94744212015-09-21 19:01:47 -0700749 void rotateBounds(int oldRotation, int newRotation, Rect bounds) {
Andrii Kulian4dfb9c42016-10-11 20:06:27 -0700750 getLogicalDisplayRect(mTmpRect, newRotation);
751
752 // Compute a transform matrix to undo the coordinate space transformation,
753 // and present the window at the same physical position it previously occupied.
754 final int deltaRotation = deltaRotation(newRotation, oldRotation);
755 createRotationMatrix(deltaRotation, mTmpRect.width(), mTmpRect.height(), mTmpMatrix);
756
757 mTmpRectF.set(bounds);
758 mTmpMatrix.mapRect(mTmpRectF);
759 mTmpRectF.round(bounds);
Wale Ogunwale94744212015-09-21 19:01:47 -0700760 }
761
Wale Ogunwale4a02d812015-02-12 23:01:38 -0800762 static int deltaRotation(int oldRotation, int newRotation) {
763 int delta = newRotation - oldRotation;
764 if (delta < 0) delta += 4;
765 return delta;
766 }
767
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700768 private static void createRotationMatrix(int rotation, float displayWidth, float displayHeight,
Andrii Kulian4dfb9c42016-10-11 20:06:27 -0700769 Matrix outMatrix) {
770 // For rotations without Z-ordering we don't need the target rectangle's position.
771 createRotationMatrix(rotation, 0 /* rectLeft */, 0 /* rectTop */, displayWidth,
772 displayHeight, outMatrix);
773 }
774
775 static void createRotationMatrix(int rotation, float rectLeft, float rectTop,
776 float displayWidth, float displayHeight, Matrix outMatrix) {
777 switch (rotation) {
778 case ROTATION_0:
779 outMatrix.reset();
780 break;
781 case ROTATION_270:
782 outMatrix.setRotate(270, 0, 0);
783 outMatrix.postTranslate(0, displayHeight);
784 outMatrix.postTranslate(rectTop, 0);
785 break;
786 case ROTATION_180:
787 outMatrix.reset();
788 break;
789 case ROTATION_90:
790 outMatrix.setRotate(90, 0, 0);
791 outMatrix.postTranslate(displayWidth, 0);
792 outMatrix.postTranslate(-rectTop, rectLeft);
793 break;
794 }
795 }
796
Craig Mautnera91f9e22012-09-14 16:22:08 -0700797 public void dump(String prefix, PrintWriter pw) {
798 pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId);
799 final String subPrefix = " " + prefix;
800 pw.print(subPrefix); pw.print("init="); pw.print(mInitialDisplayWidth); pw.print("x");
801 pw.print(mInitialDisplayHeight); pw.print(" "); pw.print(mInitialDisplayDensity);
802 pw.print("dpi");
803 if (mInitialDisplayWidth != mBaseDisplayWidth
804 || mInitialDisplayHeight != mBaseDisplayHeight
805 || mInitialDisplayDensity != mBaseDisplayDensity) {
806 pw.print(" base=");
807 pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight);
808 pw.print(" "); pw.print(mBaseDisplayDensity); pw.print("dpi");
809 }
Jeff Brownd46747a2015-04-15 19:02:36 -0700810 if (mDisplayScalingDisabled) {
811 pw.println(" noscale");
812 }
Craig Mautnera91f9e22012-09-14 16:22:08 -0700813 pw.print(" cur=");
814 pw.print(mDisplayInfo.logicalWidth);
815 pw.print("x"); pw.print(mDisplayInfo.logicalHeight);
816 pw.print(" app=");
817 pw.print(mDisplayInfo.appWidth);
818 pw.print("x"); pw.print(mDisplayInfo.appHeight);
819 pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth);
820 pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight);
821 pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth);
822 pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight);
Wale Ogunwale2b06bfc2016-09-28 14:17:05 -0700823 pw.println(subPrefix + "deferred=" + mDeferredRemoval
824 + " mLayoutNeeded=" + mLayoutNeeded);
Wale Ogunwaleb429e682016-01-06 12:36:34 -0800825
Craig Mautnerdc548482014-02-05 13:35:24 -0800826 pw.println();
Craig Mautnere8b85fd2014-10-22 09:23:25 -0700827 pw.println(" Application tokens in top down Z order:");
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700828 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
829 final TaskStack stack = mTaskStackContainers.get(stackNdx);
Wale Ogunwaleb429e682016-01-06 12:36:34 -0800830 stack.dump(prefix + " ", pw);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700831 }
Wale Ogunwaleb429e682016-01-06 12:36:34 -0800832
Craig Mautnerdc548482014-02-05 13:35:24 -0800833 pw.println();
834 if (!mExitingTokens.isEmpty()) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700835 pw.println();
836 pw.println(" Exiting tokens:");
Wale Ogunwaleb429e682016-01-06 12:36:34 -0800837 for (int i = mExitingTokens.size() - 1; i >= 0; i--) {
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700838 final WindowToken token = mExitingTokens.get(i);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700839 pw.print(" Exiting #"); pw.print(i);
840 pw.print(' '); pw.print(token);
841 pw.println(':');
842 token.dump(pw, " ");
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800843 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700844 }
Craig Mautner59c00972012-07-30 12:10:24 -0700845 pw.println();
Chong Zhang112eb8c2015-11-02 11:17:00 -0800846 mDimLayerController.dump(prefix + " ", pw);
Jorim Jaggi31f71702016-05-04 16:43:04 -0700847 pw.println();
848 mDividerControllerLocked.dump(prefix + " ", pw);
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700849
850 if (mInputMethodAnimLayerAdjustment != 0) {
851 pw.println(subPrefix
852 + "mInputMethodAnimLayerAdjustment=" + mInputMethodAnimLayerAdjustment);
853 }
Craig Mautner59c00972012-07-30 12:10:24 -0700854 }
Craig Mautnere0a38842013-12-16 16:14:02 -0800855
856 @Override
857 public String toString() {
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700858 return "Display " + mDisplayId + " info=" + mDisplayInfo + " stacks=" + mChildren;
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700859 }
860
861 String getName() {
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700862 return "Display " + mDisplayId + " name=\"" + mDisplayInfo.name + "\"";
Craig Mautnere0a38842013-12-16 16:14:02 -0800863 }
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700864
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800865 /**
866 * @return The docked stack, but only if it is visible, and {@code null} otherwise.
867 */
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -0700868 TaskStack getDockedStackLocked() {
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700869 final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700870 return (stack != null && stack.isVisible()) ? stack : null;
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700871 }
Vladislav Kaznacheev5d6bdeb2016-02-12 17:07:20 -0800872
873 /**
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800874 * Like {@link #getDockedStackLocked}, but also returns the docked stack if it's currently not
875 * visible, as long as it's not hidden because the current user doesn't have any tasks there.
876 */
877 TaskStack getDockedStackVisibleForUserLocked() {
878 final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700879 return (stack != null && stack.isVisible(true /* ignoreKeyguard */)) ? stack : null;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800880 }
881
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700882 /** Find the visible, touch-deliverable window under the given point */
Vladislav Kaznacheev5d6bdeb2016-02-12 17:07:20 -0800883 WindowState getTouchableWinAtPointLocked(float xf, float yf) {
884 WindowState touchedWin = null;
885 final int x = (int) xf;
886 final int y = (int) yf;
887
888 for (int i = mWindows.size() - 1; i >= 0; i--) {
889 WindowState window = mWindows.get(i);
890 final int flags = window.mAttrs.flags;
891 if (!window.isVisibleLw()) {
892 continue;
893 }
894 if ((flags & FLAG_NOT_TOUCHABLE) != 0) {
895 continue;
896 }
897
898 window.getVisibleBounds(mTmpRect);
899 if (!mTmpRect.contains(x, y)) {
900 continue;
901 }
902
903 window.getTouchableRegion(mTmpRegion);
904
905 final int touchFlags = flags & (FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL);
906 if (mTmpRegion.contains(x, y) || touchFlags == 0) {
907 touchedWin = window;
908 break;
909 }
910 }
911
912 return touchedWin;
913 }
Jorim Jaggi6626f542016-08-22 13:08:44 -0700914
Svetoslav Ganovaa076532016-08-01 19:16:43 -0700915 boolean canAddToastWindowForUid(int uid) {
916 // We allow one toast window per UID being shown at a time.
917 WindowList windows = getWindowList();
918 final int windowCount = windows.size();
919 for (int i = 0; i < windowCount; i++) {
920 WindowState window = windows.get(i);
921 if (window.mAttrs.type == TYPE_TOAST && window.mOwnerUid == uid
Svet Ganov62a40f82016-09-29 00:43:51 -0700922 && !window.mPermanentlyHidden && !window.mAnimatingExit
923 && !window.mRemoveOnExit) {
Svetoslav Ganovaa076532016-08-01 19:16:43 -0700924 return false;
925 }
926 }
927 return true;
928 }
929
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700930 void scheduleToastWindowsTimeoutIfNeededLocked(WindowState oldFocus, WindowState newFocus) {
Svetoslav Ganovaa076532016-08-01 19:16:43 -0700931 if (oldFocus == null || (newFocus != null && newFocus.mOwnerUid == oldFocus.mOwnerUid)) {
932 return;
933 }
934 final int lostFocusUid = oldFocus.mOwnerUid;
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700935 final WindowList windows = getWindowList();
Svetoslav Ganovaa076532016-08-01 19:16:43 -0700936 final int windowCount = windows.size();
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700937 final Handler handler = mService.mH;
Svetoslav Ganovaa076532016-08-01 19:16:43 -0700938 for (int i = 0; i < windowCount; i++) {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700939 final WindowState window = windows.get(i);
Svetoslav Ganovaa076532016-08-01 19:16:43 -0700940 if (window.mAttrs.type == TYPE_TOAST && window.mOwnerUid == lostFocusUid) {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700941 if (!handler.hasMessages(WINDOW_HIDE_TIMEOUT, window)) {
942 handler.sendMessageDelayed(handler.obtainMessage(WINDOW_HIDE_TIMEOUT, window),
Svetoslav Ganovaa076532016-08-01 19:16:43 -0700943 window.mAttrs.hideTimeoutMilliseconds);
944 }
945 }
946 }
947 }
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700948
949 WindowState findFocusedWindow() {
950 final AppWindowToken focusedApp = mService.mFocusedApp;
951
952 for (int i = mWindows.size() - 1; i >= 0; i--) {
953 final WindowState win = mWindows.get(i);
954
955 if (DEBUG_FOCUS) Slog.v(TAG_WM, "Looking for focus: " + i + " = " + win
956 + ", flags=" + win.mAttrs.flags + ", canReceive=" + win.canReceiveKeys());
957
958 if (!win.canReceiveKeys()) {
959 continue;
960 }
961
962 final AppWindowToken wtoken = win.mAppToken;
963
964 // If this window's application has been removed, just skip it.
965 if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) {
966 if (DEBUG_FOCUS) Slog.v(TAG_WM, "Skipping " + wtoken + " because "
967 + (wtoken.removed ? "removed" : "sendingToBottom"));
968 continue;
969 }
970
971 if (focusedApp == null) {
972 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp=null"
973 + " using new focus @ " + i + " = " + win);
974 return win;
975 }
976
977 if (!focusedApp.windowsAreFocusable()) {
978 // Current focused app windows aren't focusable...
979 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp windows not"
980 + " focusable using new focus @ " + i + " = " + win);
981 return win;
982 }
983
984 // Descend through all of the app tokens and find the first that either matches
985 // win.mAppToken (return win) or mFocusedApp (return null).
986 if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING) {
Wale Ogunwale10124582016-09-15 20:25:50 -0700987 if (focusedApp.compareTo(wtoken) > 0) {
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700988 // App stack below focused app stack. No focus for you!!!
989 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM,
990 "findFocusedWindow: Reached focused app=" + focusedApp);
991 return null;
992 }
993 }
994
995 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: Found new focus @ "
996 + i + " = " + win);
997 return win;
998 }
999
1000 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: No focusable windows.");
1001 return null;
1002 }
Wale Ogunwaleec731152016-09-08 20:18:57 -07001003
1004 int addAppWindowToWindowList(final WindowState win) {
1005 final IWindow client = win.mClient;
1006
1007 WindowList tokenWindowList = getTokenWindowsOnDisplay(win.mToken);
1008 if (!tokenWindowList.isEmpty()) {
1009 return addAppWindowExisting(win, tokenWindowList);
1010 }
1011
1012 // No windows from this token on this display
Wale Ogunwale19e452e2016-10-12 12:36:29 -07001013 if (localLOGV) Slog.v(TAG_WM, "Figuring out where to add app window "
Wale Ogunwaleec731152016-09-08 20:18:57 -07001014 + client.asBinder() + " (token=" + this + ")");
1015
1016 final WindowToken wToken = win.mToken;
1017
1018 // Figure out where the window should go, based on the order of applications.
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001019 mTmpGetWindowOnDisplaySearchResult.reset();
Wale Ogunwale19e452e2016-10-12 12:36:29 -07001020 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
1021 final TaskStack stack = mTaskStackContainers.get(i);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001022 stack.getWindowOnDisplayBeforeToken(this, wToken, mTmpGetWindowOnDisplaySearchResult);
1023 if (mTmpGetWindowOnDisplaySearchResult.reachedToken) {
Wale Ogunwaleec731152016-09-08 20:18:57 -07001024 // We have reach the token we are interested in. End search.
1025 break;
1026 }
1027 }
1028
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001029 WindowState pos = mTmpGetWindowOnDisplaySearchResult.foundWindow;
Wale Ogunwaleec731152016-09-08 20:18:57 -07001030
1031 // We now know the index into the apps. If we found an app window above, that gives us the
1032 // position; else we need to look some more.
1033 if (pos != null) {
1034 // Move behind any windows attached to this one.
Wale Ogunwale02319a62016-09-26 15:21:22 -07001035 final WindowToken atoken = getWindowToken(pos.mClient.asBinder());
Wale Ogunwaleec731152016-09-08 20:18:57 -07001036 if (atoken != null) {
1037 tokenWindowList = getTokenWindowsOnDisplay(atoken);
1038 final int NC = tokenWindowList.size();
1039 if (NC > 0) {
1040 WindowState bottom = tokenWindowList.get(0);
1041 if (bottom.mSubLayer < 0) {
1042 pos = bottom;
1043 }
1044 }
1045 }
1046 addWindowToListBefore(win, pos);
1047 return 0;
1048 }
1049
1050 // Continue looking down until we find the first token that has windows on this display.
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001051 mTmpGetWindowOnDisplaySearchResult.reset();
Wale Ogunwale19e452e2016-10-12 12:36:29 -07001052 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
1053 final TaskStack stack = mTaskStackContainers.get(i);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001054 stack.getWindowOnDisplayAfterToken(this, wToken, mTmpGetWindowOnDisplaySearchResult);
1055 if (mTmpGetWindowOnDisplaySearchResult.foundWindow != null) {
Wale Ogunwaleec731152016-09-08 20:18:57 -07001056 // We have found a window after the token. End search.
1057 break;
1058 }
1059 }
1060
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001061 pos = mTmpGetWindowOnDisplaySearchResult.foundWindow;
Wale Ogunwaleec731152016-09-08 20:18:57 -07001062
1063 if (pos != null) {
1064 // Move in front of any windows attached to this one.
Wale Ogunwale02319a62016-09-26 15:21:22 -07001065 final WindowToken atoken = getWindowToken(pos.mClient.asBinder());
Wale Ogunwaleec731152016-09-08 20:18:57 -07001066 if (atoken != null) {
1067 final WindowState top = atoken.getTopWindow();
1068 if (top != null && top.mSubLayer >= 0) {
1069 pos = top;
1070 }
1071 }
1072 addWindowToListAfter(win, pos);
1073 return 0;
1074 }
1075
1076 // Just search for the start of this layer.
1077 final int myLayer = win.mBaseLayer;
1078 int i;
1079 for (i = mWindows.size() - 1; i >= 0; --i) {
1080 final WindowState w = mWindows.get(i);
1081 // Dock divider shares the base layer with application windows, but we want to always
1082 // keep it above the application windows. The sharing of the base layer is intended
1083 // for window animations, which need to be above the dock divider for the duration
1084 // of the animation.
1085 if (w.mBaseLayer <= myLayer && w.mAttrs.type != TYPE_DOCK_DIVIDER) {
1086 break;
1087 }
1088 }
1089 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
1090 "Based on layer: Adding window " + win + " at " + (i + 1) + " of "
1091 + mWindows.size());
1092 mWindows.add(i + 1, win);
1093 mService.mWindowsChanged = true;
1094 return 0;
1095 }
1096
1097 /** Adds this non-app window to the window list. */
1098 void addNonAppWindowToWindowList(WindowState win) {
1099 // Figure out where window should go, based on layer.
1100 int i;
1101 for (i = mWindows.size() - 1; i >= 0; i--) {
1102 final WindowState otherWin = mWindows.get(i);
1103 if (otherWin.getBaseType() != TYPE_WALLPAPER && otherWin.mBaseLayer <= win.mBaseLayer) {
1104 // Wallpaper wanders through the window list, for example to position itself
1105 // directly behind keyguard. Because of this it will break the ordering based on
1106 // WindowState.mBaseLayer. There might windows with higher mBaseLayer behind it and
1107 // we don't want the new window to appear above them. An example of this is adding
1108 // of the docked stack divider. Consider a scenario with the following ordering (top
1109 // to bottom): keyguard, wallpaper, assist preview, apps. We want the dock divider
1110 // to land below the assist preview, so the dock divider must ignore the wallpaper,
1111 // with which it shares the base layer.
1112 break;
1113 }
1114 }
1115
1116 i++;
1117 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
1118 "Free window: Adding window " + this + " at " + i + " of " + mWindows.size());
1119 mWindows.add(i, win);
1120 mService.mWindowsChanged = true;
1121 }
1122
Wale Ogunwaleb9a07c32016-10-12 14:55:56 -07001123 void addToWindowList(WindowState win, int index) {
1124 mWindows.add(index, win);
1125 }
1126
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -07001127 boolean removeFromWindowList(WindowState win) {
1128 return mWindows.remove(win);
1129 }
1130
1131 private int removeWindowAndChildrenFromWindowList(WindowState win, int interestingPos) {
1132 final WindowList windows = getWindowList();
1133 int wpos = windows.indexOf(win);
1134 if (wpos < 0) {
1135 return interestingPos;
1136 }
1137
1138 if (wpos < interestingPos) interestingPos--;
1139 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Temp removing at " + wpos + ": " + this);
1140 windows.remove(wpos);
1141 mService.mWindowsChanged = true;
1142 int childWinCount = win.mChildren.size();
1143 while (childWinCount > 0) {
1144 childWinCount--;
1145 final WindowState cw = win.mChildren.get(childWinCount);
1146 int cpos = windows.indexOf(cw);
1147 if (cpos >= 0) {
1148 if (cpos < interestingPos) interestingPos--;
1149 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM,
1150 "Temp removing child at " + cpos + ": " + cw);
1151 windows.remove(cpos);
1152 }
1153 }
1154 return interestingPos;
1155 }
1156
Wale Ogunwaleec731152016-09-08 20:18:57 -07001157 void addChildWindowToWindowList(WindowState win) {
1158 final WindowState parentWindow = win.getParentWindow();
1159
1160 WindowList windowsOnSameDisplay = getTokenWindowsOnDisplay(win.mToken);
1161
1162 // Figure out this window's ordering relative to the parent window.
1163 final int wCount = windowsOnSameDisplay.size();
1164 final int sublayer = win.mSubLayer;
1165 int largestSublayer = Integer.MIN_VALUE;
1166 WindowState windowWithLargestSublayer = null;
1167 int i;
1168 for (i = 0; i < wCount; i++) {
1169 WindowState w = windowsOnSameDisplay.get(i);
1170 final int wSublayer = w.mSubLayer;
1171 if (wSublayer >= largestSublayer) {
1172 largestSublayer = wSublayer;
1173 windowWithLargestSublayer = w;
1174 }
1175 if (sublayer < 0) {
1176 // For negative sublayers, we go below all windows in the same sublayer.
1177 if (wSublayer >= sublayer) {
1178 addWindowToListBefore(win, wSublayer >= 0 ? parentWindow : w);
1179 break;
1180 }
1181 } else {
1182 // For positive sublayers, we go above all windows in the same sublayer.
1183 if (wSublayer > sublayer) {
1184 addWindowToListBefore(win, w);
1185 break;
1186 }
1187 }
1188 }
1189 if (i >= wCount) {
1190 if (sublayer < 0) {
1191 addWindowToListBefore(win, parentWindow);
1192 } else {
1193 addWindowToListAfter(win,
1194 largestSublayer >= 0 ? windowWithLargestSublayer : parentWindow);
1195 }
1196 }
1197 }
1198
Wale Ogunwalec69694a2016-10-18 13:51:15 -07001199 /** Updates the layer assignment of windows on this display. */
1200 void assignWindowLayers(boolean setLayoutNeeded) {
1201 mLayersController.assignWindowLayers(mWindows);
1202 if (setLayoutNeeded) {
1203 setLayoutNeeded();
1204 }
1205 }
1206
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001207 /**
1208 * Z-orders the display window list so that:
1209 * <ul>
1210 * <li>Any windows that are currently below the wallpaper window stay below the wallpaper
1211 * window.
1212 * <li>Exiting application windows are at the bottom, but above the wallpaper window.
1213 * <li>All other application windows are above the exiting application windows and ordered based
1214 * on the ordering of their stacks and tasks on the display.
1215 * <li>Non-application windows are at the very top.
1216 * </ul>
1217 * <p>
1218 * NOTE: This isn't a complete picture of what the user see. Further manipulation of the window
1219 * surface layering is done in {@link WindowLayersController}.
1220 */
1221 void rebuildAppWindowList() {
1222 int count = mWindows.size();
1223 int i;
1224 int lastBelow = -1;
1225 int numRemoved = 0;
1226
1227 if (mRebuildTmp.length < count) {
1228 mRebuildTmp = new WindowState[count + 10];
1229 }
1230
1231 // First remove all existing app windows.
1232 i = 0;
1233 while (i < count) {
1234 final WindowState w = mWindows.get(i);
1235 if (w.mAppToken != null) {
1236 final WindowState win = mWindows.remove(i);
1237 win.mRebuilding = true;
1238 mRebuildTmp[numRemoved] = win;
1239 mService.mWindowsChanged = true;
1240 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Rebuild removing window: " + win);
1241 count--;
1242 numRemoved++;
1243 continue;
1244 } else if (lastBelow == i-1) {
1245 if (w.mAttrs.type == TYPE_WALLPAPER) {
1246 lastBelow = i;
1247 }
1248 }
1249 i++;
1250 }
1251
1252 // Keep whatever windows were below the app windows still below, by skipping them.
1253 lastBelow++;
1254 i = lastBelow;
1255
1256 // First add all of the exiting app tokens... these are no longer in the main app list,
1257 // but still have windows shown. We put them in the back because now that the animation is
1258 // over we no longer will care about them.
Wale Ogunwale19e452e2016-10-12 12:36:29 -07001259 final int numStacks = mTaskStackContainers.size();
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001260 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
Wale Ogunwale19e452e2016-10-12 12:36:29 -07001261 AppTokenList exitingAppTokens = mTaskStackContainers.get(stackNdx).mExitingAppTokens;
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001262 int NT = exitingAppTokens.size();
1263 for (int j = 0; j < NT; j++) {
Wale Ogunwale360a8bc2016-10-10 13:25:26 -07001264 i = exitingAppTokens.get(j).rebuildWindowListUnchecked(i);
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001265 }
1266 }
1267
1268 // And add in the still active app tokens in Z order.
1269 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
Wale Ogunwale19e452e2016-10-12 12:36:29 -07001270 i = mTaskStackContainers.get(stackNdx).rebuildWindowList(i);
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001271 }
1272
1273 i -= lastBelow;
1274 if (i != numRemoved) {
Wale Ogunwale2b06bfc2016-09-28 14:17:05 -07001275 setLayoutNeeded();
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001276 Slog.w(TAG_WM, "On display=" + mDisplayId + " Rebuild removed " + numRemoved
1277 + " windows but added " + i + " rebuildAppWindowListLocked() "
1278 + " callers=" + Debug.getCallers(10));
1279 for (i = 0; i < numRemoved; i++) {
1280 WindowState ws = mRebuildTmp[i];
1281 if (ws.mRebuilding) {
1282 StringWriter sw = new StringWriter();
1283 PrintWriter pw = new FastPrintWriter(sw, false, 1024);
1284 ws.dump(pw, "", true);
1285 pw.flush();
1286 Slog.w(TAG_WM, "This window was lost: " + ws);
1287 Slog.w(TAG_WM, sw.toString());
1288 ws.mWinAnimator.destroySurfaceLocked();
1289 }
1290 }
Wale Ogunwaleba51ca22016-09-23 06:06:54 -07001291 Slog.w(TAG_WM, "Current window hierarchy:");
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001292 dumpChildrenNames();
1293 Slog.w(TAG_WM, "Final window list:");
1294 dumpWindows();
1295 }
1296 Arrays.fill(mRebuildTmp, null);
1297 }
1298
Wale Ogunwaleec731152016-09-08 20:18:57 -07001299 /** Return the list of Windows on this display associated with the input token. */
1300 WindowList getTokenWindowsOnDisplay(WindowToken token) {
1301 final WindowList windowList = new WindowList();
1302 final int count = mWindows.size();
1303 for (int i = 0; i < count; i++) {
1304 final WindowState win = mWindows.get(i);
1305 if (win.mToken == token) {
1306 windowList.add(win);
1307 }
1308 }
1309 return windowList;
1310 }
1311
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -07001312 private void reAddToWindowList(WindowState win) {
1313 win.mToken.addWindow(win);
1314 // This is a hack to get all of the child windows added as well at the right position. Child
1315 // windows should be rare and this case should be rare, so it shouldn't be that big a deal.
1316 int wpos = mWindows.indexOf(win);
1317 if (wpos >= 0) {
1318 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "ReAdd removing from " + wpos + ": " + win);
1319 mWindows.remove(wpos);
1320 mService.mWindowsChanged = true;
1321 win.reAddWindow(wpos);
1322 }
1323 }
1324
1325 void moveInputMethodDialogs(int pos) {
1326 ArrayList<WindowState> dialogs = mService.mInputMethodDialogs;
1327
1328 final int N = dialogs.size();
1329 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Removing " + N + " dialogs w/pos=" + pos);
1330 for (int i = 0; i < N; i++) {
1331 pos = removeWindowAndChildrenFromWindowList(dialogs.get(i), pos);
1332 }
1333 if (DEBUG_INPUT_METHOD) {
1334 Slog.v(TAG_WM, "Window list w/pos=" + pos);
1335 logWindowList(mWindows, " ");
1336 }
1337
1338 WindowState ime = mService.mInputMethodWindow;
1339 if (pos >= 0) {
1340 // Skip windows owned by the input method.
1341 if (ime != null) {
1342 while (pos < mWindows.size()) {
1343 WindowState wp = mWindows.get(pos);
1344 if (wp == ime || wp.getParentWindow() == ime) {
1345 pos++;
1346 continue;
1347 }
1348 break;
1349 }
1350 }
1351 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Adding " + N + " dialogs at pos=" + pos);
1352 for (int i=0; i<N; i++) {
1353 WindowState win = dialogs.get(i);
1354 pos = win.reAddWindow(pos);
1355 }
1356 if (DEBUG_INPUT_METHOD) {
1357 Slog.v(TAG_WM, "Final window list:");
1358 logWindowList(mWindows, " ");
1359 }
1360 return;
1361 }
1362 for (int i=0; i<N; i++) {
1363 WindowState win = dialogs.get(i);
1364 reAddToWindowList(win);
1365 if (DEBUG_INPUT_METHOD) {
1366 Slog.v(TAG_WM, "No IM target, final list:");
1367 logWindowList(mWindows, " ");
1368 }
1369 }
1370 }
1371
1372 boolean moveInputMethodWindowsIfNeeded(boolean needAssignLayers) {
1373 final WindowState imWin = mService.mInputMethodWindow;
1374 final int DN = mService.mInputMethodDialogs.size();
1375 if (imWin == null && DN == 0) {
1376 return false;
1377 }
1378
1379 // TODO(multidisplay): IMEs are only supported on the default display.
1380 WindowList windows = mWindows;
1381
1382 int imPos = findDesiredInputMethodWindowIndex(true);
1383 if (imPos >= 0) {
1384 // In this case, the input method windows are to be placed
1385 // immediately above the window they are targeting.
1386
1387 // First check to see if the input method windows are already
1388 // located here, and contiguous.
1389 final int N = windows.size();
1390 final WindowState firstImWin = imPos < N ? windows.get(imPos) : null;
1391
1392 // Figure out the actual input method window that should be
1393 // at the bottom of their stack.
1394 WindowState baseImWin = imWin != null ? imWin : mService.mInputMethodDialogs.get(0);
1395 final WindowState cw = baseImWin.getBottomChild();
1396 if (cw != null && cw.mSubLayer < 0) {
1397 baseImWin = cw;
1398 }
1399
1400 if (firstImWin == baseImWin) {
1401 // The windows haven't moved... but are they still contiguous?
1402 // First find the top IM window.
1403 int pos = imPos+1;
1404 while (pos < N) {
1405 if (!(windows.get(pos)).mIsImWindow) {
1406 break;
1407 }
1408 pos++;
1409 }
1410 pos++;
1411 // Now there should be no more input method windows above.
1412 while (pos < N) {
1413 if ((windows.get(pos)).mIsImWindow) {
1414 break;
1415 }
1416 pos++;
1417 }
1418 if (pos >= N) {
1419 return false;
1420 }
1421 }
1422
1423 if (imWin != null) {
1424 if (DEBUG_INPUT_METHOD) {
1425 Slog.v(TAG_WM, "Moving IM from " + imPos);
1426 logWindowList(windows, " ");
1427 }
1428 imPos = removeWindowAndChildrenFromWindowList(imWin, imPos);
1429 if (DEBUG_INPUT_METHOD) {
1430 Slog.v(TAG_WM, "List after removing with new pos " + imPos + ":");
1431 logWindowList(windows, " ");
1432 }
1433 imWin.reAddWindow(imPos);
1434 if (DEBUG_INPUT_METHOD) {
1435 Slog.v(TAG_WM, "List after moving IM to " + imPos + ":");
1436 logWindowList(windows, " ");
1437 }
1438 if (DN > 0) moveInputMethodDialogs(imPos+1);
1439 } else {
1440 moveInputMethodDialogs(imPos);
1441 }
1442
1443 } else {
1444 // In this case, the input method windows go in a fixed layer,
1445 // because they aren't currently associated with a focus window.
1446
1447 if (imWin != null) {
1448 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Moving IM from " + imPos);
1449 removeWindowAndChildrenFromWindowList(imWin, 0);
1450 reAddToWindowList(imWin);
1451 if (DEBUG_INPUT_METHOD) {
1452 Slog.v(TAG_WM, "List with no IM target:");
1453 logWindowList(windows, " ");
1454 }
1455 if (DN > 0) moveInputMethodDialogs(-1);
1456 } else {
1457 moveInputMethodDialogs(-1);
1458 }
1459
1460 }
1461
1462 if (needAssignLayers) {
1463 assignWindowLayers(false /* setLayoutNeeded */);
1464 }
1465
1466 return true;
1467 }
1468
1469 /**
1470 * Dig through the WindowStates and find the one that the Input Method will target.
1471 * @param willMove
1472 * @return The index+1 in mWindows of the discovered target.
1473 */
1474 int findDesiredInputMethodWindowIndex(boolean willMove) {
1475 // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the
1476 // same display. Or even when the current IME/target are not on the same screen as the next
1477 // IME/target. For now only look for input windows on the main screen.
1478 final WindowList windows = getWindowList();
1479 WindowState w = null;
1480 int i;
1481 for (i = windows.size() - 1; i >= 0; --i) {
1482 WindowState win = windows.get(i);
1483
1484 if (DEBUG_INPUT_METHOD && willMove) Slog.i(TAG_WM, "Checking window @" + i
1485 + " " + win + " fl=0x" + Integer.toHexString(win.mAttrs.flags));
1486 if (canBeImeTarget(win)) {
1487 w = win;
1488 //Slog.i(TAG_WM, "Putting input method here!");
1489
1490 // Yet more tricksyness! If this window is a "starting" window, we do actually want
1491 // to be on top of it, but it is not -really- where input will go. So if the caller
1492 // is not actually looking to move the IME, look down below for a real window to
1493 // target...
1494 if (!willMove && w.mAttrs.type == TYPE_APPLICATION_STARTING && i > 0) {
1495 WindowState wb = windows.get(i-1);
1496 if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) {
1497 i--;
1498 w = wb;
1499 }
1500 }
1501 break;
1502 }
1503 }
1504
1505 // Now w is either mWindows[0] or an IME (or null if mWindows is empty).
1506
1507 if (DEBUG_INPUT_METHOD && willMove) Slog.v(TAG_WM, "Proposed new IME target: " + w);
1508
1509 // Now, a special case -- if the last target's window is in the process of exiting, and is
1510 // above the new target, keep on the last target to avoid flicker. Consider for example a
1511 // Dialog with the IME shown: when the Dialog is dismissed, we want to keep the IME above it
1512 // until it is completely gone so it doesn't drop behind the dialog or its full-screen
1513 // scrim.
1514 final WindowState curTarget = mService.mInputMethodTarget;
1515 if (curTarget != null
1516 && curTarget.isDisplayedLw()
1517 && curTarget.isClosing()
1518 && (w == null || curTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer)) {
1519 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Current target higher, not changing");
1520 return windows.indexOf(curTarget) + 1;
1521 }
1522
1523 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Desired input method target="
1524 + w + " willMove=" + willMove);
1525
1526 if (willMove && w != null) {
1527 AppWindowToken token = curTarget == null ? null : curTarget.mAppToken;
1528 if (token != null) {
1529
1530 // Now some fun for dealing with window animations that modify the Z order. We need
1531 // to look at all windows below the current target that are in this app, finding the
1532 // highest visible one in layering.
1533 WindowState highestTarget = null;
1534 int highestPos = 0;
1535 if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) {
1536 WindowList curWindows = token.getDisplayContent().getWindowList();
1537 int pos = curWindows.indexOf(curTarget);
1538 while (pos >= 0) {
1539 WindowState win = curWindows.get(pos);
1540 if (win.mAppToken != token) {
1541 break;
1542 }
1543 if (!win.mRemoved) {
1544 if (highestTarget == null || win.mWinAnimator.mAnimLayer >
1545 highestTarget.mWinAnimator.mAnimLayer) {
1546 highestTarget = win;
1547 highestPos = pos;
1548 }
1549 }
1550 pos--;
1551 }
1552 }
1553
1554 if (highestTarget != null) {
1555 final AppTransition appTransition = mService.mAppTransition;
1556 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, appTransition + " " + highestTarget
1557 + " animating=" + highestTarget.mWinAnimator.isAnimationSet()
1558 + " layer=" + highestTarget.mWinAnimator.mAnimLayer
1559 + " new layer=" + w.mWinAnimator.mAnimLayer);
1560
1561 if (appTransition.isTransitionSet()) {
1562 // If we are currently setting up for an animation, hold everything until we
1563 // can find out what will happen.
1564 mService.mInputMethodTargetWaitingAnim = true;
1565 mService.mInputMethodTarget = highestTarget;
1566 return highestPos + 1;
1567 } else if (highestTarget.mWinAnimator.isAnimationSet() &&
1568 highestTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) {
1569 // If the window we are currently targeting is involved with an animation,
1570 // and it is on top of the next target we will be over, then hold off on
1571 // moving until that is done.
1572 mService.mInputMethodTargetWaitingAnim = true;
1573 mService.mInputMethodTarget = highestTarget;
1574 return highestPos + 1;
1575 }
1576 }
1577 }
1578 }
1579
1580 //Slog.i(TAG_WM, "Placing input method @" + (i+1));
1581 if (w != null) {
1582 if (willMove) {
1583 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to "
1584 + w + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : ""));
1585 mService.mInputMethodTarget = w;
1586 mService.mInputMethodTargetWaitingAnim = false;
1587 if (w.mAppToken != null) {
1588 setInputMethodAnimLayerAdjustment(
1589 w.mAppToken.mAppAnimator.animLayerAdjustment);
1590 } else {
1591 setInputMethodAnimLayerAdjustment(0);
1592 }
1593 }
1594
1595 // If the docked divider is visible, we still need to go through this whole excercise to
1596 // find the appropriate input method target (used for animations and dialog
1597 // adjustments), but for purposes of Z ordering we simply wish to place it above the
1598 // docked divider. Unless it is already above the divider.
1599 final WindowState dockedDivider = mDividerControllerLocked.getWindow();
1600 if (dockedDivider != null && dockedDivider.isVisibleLw()) {
1601 int dividerIndex = windows.indexOf(dockedDivider);
1602 if (dividerIndex > 0 && dividerIndex > i) {
1603 return dividerIndex + 1;
1604 }
1605 }
1606 return i+1;
1607 }
1608 if (willMove) {
1609 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget
1610 + " to null." + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : ""));
1611 mService.mInputMethodTarget = null;
1612 setInputMethodAnimLayerAdjustment(0);
1613 }
1614 return -1;
1615 }
1616
1617 private static boolean canBeImeTarget(WindowState w) {
1618 final int fl = w.mAttrs.flags & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM);
1619 final int type = w.mAttrs.type;
1620
1621 if (fl != 0 && fl != (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM)
1622 && type != TYPE_APPLICATION_STARTING) {
1623 return false;
1624 }
1625
1626 if (DEBUG_INPUT_METHOD) {
1627 Slog.i(TAG_WM, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding());
1628 if (!w.isVisibleOrAdding()) {
1629 Slog.i(TAG_WM, " mSurfaceController=" + w.mWinAnimator.mSurfaceController
1630 + " relayoutCalled=" + w.mRelayoutCalled
1631 + " viewVis=" + w.mViewVisibility
1632 + " policyVis=" + w.mPolicyVisibility
1633 + " policyVisAfterAnim=" + w.mPolicyVisibilityAfterAnim
1634 + " parentHidden=" + w.isParentWindowHidden()
1635 + " exiting=" + w.mAnimatingExit + " destroying=" + w.mDestroying);
1636 if (w.mAppToken != null) {
1637 Slog.i(TAG_WM, " mAppToken.hiddenRequested=" + w.mAppToken.hiddenRequested);
1638 }
1639 }
1640 }
1641 return w.isVisibleOrAdding();
1642 }
1643
1644 private void logWindowList(final WindowList windows, String prefix) {
1645 int N = windows.size();
1646 while (N > 0) {
1647 N--;
1648 Slog.v(TAG_WM, prefix + "#" + N + ": " + windows.get(N));
1649 }
1650 }
1651
1652 boolean getNeedsMenu(WindowState win, WindowManagerPolicy.WindowState bottom) {
1653 int index = -1;
1654 WindowList windows = getWindowList();
1655 while (true) {
1656 if (win.mAttrs.needsMenuKey != NEEDS_MENU_UNSET) {
1657 return win.mAttrs.needsMenuKey == NEEDS_MENU_SET_TRUE;
1658 }
1659 // If we reached the bottom of the range of windows we are considering,
1660 // assume no menu is needed.
1661 if (win == bottom) {
1662 return false;
1663 }
1664 // The current window hasn't specified whether menu key is needed; look behind it.
1665 // First, we may need to determine the starting position.
1666 if (index < 0) {
1667 index = windows.indexOf(win);
1668 }
1669 index--;
1670 if (index < 0) {
1671 return false;
1672 }
1673 win = windows.get(index);
1674 }
1675 }
1676
Wale Ogunwale2b06bfc2016-09-28 14:17:05 -07001677 void setLayoutNeeded() {
1678 if (DEBUG_LAYOUT) Slog.w(TAG_WM, "setLayoutNeeded: callers=" + Debug.getCallers(3));
1679 mLayoutNeeded = true;
1680 }
1681
1682 void clearLayoutNeeded() {
1683 if (DEBUG_LAYOUT) Slog.w(TAG_WM, "clearLayoutNeeded: callers=" + Debug.getCallers(3));
1684 mLayoutNeeded = false;
1685 }
1686
1687 boolean isLayoutNeeded() {
1688 return mLayoutNeeded;
1689 }
1690
Wale Ogunwaleec731152016-09-08 20:18:57 -07001691 private int addAppWindowExisting(WindowState win, WindowList tokenWindowList) {
1692
1693 int tokenWindowsPos;
1694 // If this application has existing windows, we simply place the new window on top of
1695 // them... but keep the starting window on top.
1696 if (win.mAttrs.type == TYPE_BASE_APPLICATION) {
1697 // Base windows go behind everything else.
1698 final WindowState lowestWindow = tokenWindowList.get(0);
1699 addWindowToListBefore(win, lowestWindow);
1700 tokenWindowsPos = win.mToken.getWindowIndex(lowestWindow);
1701 } else {
1702 final AppWindowToken atoken = win.mAppToken;
1703 final int windowListPos = tokenWindowList.size();
1704 final WindowState lastWindow = tokenWindowList.get(windowListPos - 1);
1705 if (atoken != null && lastWindow == atoken.startingWindow) {
1706 addWindowToListBefore(win, lastWindow);
1707 tokenWindowsPos = win.mToken.getWindowIndex(lastWindow);
1708 } else {
1709 int newIdx = findIdxBasedOnAppTokens(win);
1710 // There is a window above this one associated with the same apptoken note that the
1711 // window could be a floating window that was created later or a window at the top
1712 // of the list of windows associated with this token.
1713 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
1714 "not Base app: Adding window " + win + " at " + (newIdx + 1) + " of "
1715 + mWindows.size());
1716 mWindows.add(newIdx + 1, win);
1717 if (newIdx < 0) {
1718 // No window from token found on win's display.
1719 tokenWindowsPos = 0;
1720 } else {
1721 tokenWindowsPos = win.mToken.getWindowIndex(mWindows.get(newIdx)) + 1;
1722 }
1723 mService.mWindowsChanged = true;
1724 }
1725 }
1726 return tokenWindowsPos;
1727 }
1728
1729 /** Places the first input window after the second input window in the window list. */
1730 private void addWindowToListAfter(WindowState first, WindowState second) {
1731 final int i = mWindows.indexOf(second);
1732 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
1733 "Adding window " + this + " at " + (i + 1) + " of " + mWindows.size()
1734 + " (after " + second + ")");
1735 mWindows.add(i + 1, first);
1736 mService.mWindowsChanged = true;
1737 }
1738
1739 /** Places the first input window before the second input window in the window list. */
1740 private void addWindowToListBefore(WindowState first, WindowState second) {
1741 int i = mWindows.indexOf(second);
1742 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
1743 "Adding window " + this + " at " + i + " of " + mWindows.size()
1744 + " (before " + second + ")");
1745 if (i < 0) {
1746 Slog.w(TAG_WM, "addWindowToListBefore: Unable to find " + second + " in " + mWindows);
1747 i = 0;
1748 }
1749 mWindows.add(i, first);
1750 mService.mWindowsChanged = true;
1751 }
1752
1753 /**
1754 * This method finds out the index of a window that has the same app token as win. used for z
1755 * ordering the windows in mWindows
1756 */
1757 private int findIdxBasedOnAppTokens(WindowState win) {
1758 for(int j = mWindows.size() - 1; j >= 0; j--) {
1759 final WindowState wentry = mWindows.get(j);
1760 if(wentry.mAppToken == win.mAppToken) {
1761 return j;
1762 }
1763 }
1764 return -1;
1765 }
1766
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001767 private void dumpChildrenNames() {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -07001768 StringBuilder output = new StringBuilder();
1769 dumpChildrenNames(output, " ");
1770 Slog.v(TAG_WM, output.toString());
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001771 }
1772
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001773 private void dumpWindows() {
Wale Ogunwale10124582016-09-15 20:25:50 -07001774 Slog.v(TAG_WM, " Display #" + mDisplayId);
1775 final WindowList windows = getWindowList();
1776 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
1777 Slog.v(TAG_WM, " #" + winNdx + ": " + windows.get(winNdx));
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001778 }
1779 }
1780
Wale Ogunwale02319a62016-09-26 15:21:22 -07001781 void dumpTokens(PrintWriter pw, boolean dumpAll) {
1782 if (mTokenMap.isEmpty()) {
1783 return;
1784 }
1785 pw.println(" Display #" + mDisplayId);
1786 final Iterator<WindowToken> it = mTokenMap.values().iterator();
1787 while (it.hasNext()) {
1788 final WindowToken token = it.next();
1789 pw.print(" ");
1790 pw.print(token);
1791 if (dumpAll) {
1792 pw.println(':');
1793 token.dump(pw, " ");
1794 } else {
1795 pw.println();
1796 }
1797 }
1798 }
1799
Wale Ogunwale19e452e2016-10-12 12:36:29 -07001800 void enableSurfaceTrace(FileDescriptor fd) {
1801 for (int i = mWindows.size() - 1; i >= 0; i--) {
1802 final WindowState win = mWindows.get(i);
1803 win.mWinAnimator.enableSurfaceTrace(fd);
1804 }
1805 }
1806
1807 void disableSurfaceTrace() {
1808 for (int i = mWindows.size() - 1; i >= 0; i--) {
1809 final WindowState win = mWindows.get(i);
1810 win.mWinAnimator.disableSurfaceTrace();
1811 }
1812 }
1813
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001814 static final class GetWindowOnDisplaySearchResult {
Wale Ogunwaleec731152016-09-08 20:18:57 -07001815 boolean reachedToken;
1816 WindowState foundWindow;
1817
1818 void reset() {
1819 reachedToken = false;
1820 foundWindow = null;
1821 }
1822 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001823
1824 static final class TaskForResizePointSearchResult {
1825 boolean searchDone;
1826 Task taskForResize;
1827
1828 void reset() {
1829 searchDone = false;
1830 taskForResize = null;
1831 }
1832 }
Robert Carr3b716242016-08-16 16:02:21 -07001833
Wale Ogunwale19e452e2016-10-12 12:36:29 -07001834 /**
1835 * Base class for any direct child window container of {@link #DisplayContent} need to inherit
1836 * from. This is mainly a pass through class that allows {@link #DisplayContent} to have
1837 * homogeneous children type which is currently required by sub-classes of
1838 * {@link WindowContainer} class.
1839 */
1840 static class DisplayChildWindowContainer<E extends WindowContainer> extends WindowContainer<E> {
1841
1842 int size() {
1843 return mChildren.size();
1844 }
1845
1846 E get(int index) {
1847 return mChildren.get(index);
1848 }
1849
1850 @Override
1851 boolean fillsParent() {
1852 return true;
1853 }
1854
1855 @Override
1856 boolean isVisible() {
1857 return true;
Robert Carr3b716242016-08-16 16:02:21 -07001858 }
1859 }
1860
Wale Ogunwale19e452e2016-10-12 12:36:29 -07001861 /**
1862 * Window container class that contains all containers on this display relating to Apps.
1863 * I.e Activities.
1864 */
1865 private class TaskStackContainers extends DisplayChildWindowContainer<TaskStack> {
1866
1867 void attachStack(TaskStack stack, boolean onTop) {
1868 if (stack.mStackId == HOME_STACK_ID) {
1869 if (mHomeStack != null) {
1870 throw new IllegalArgumentException("attachStack: HOME_STACK_ID (0) not first.");
1871 }
1872 mHomeStack = stack;
1873 }
1874 addChild(stack, onTop);
1875 stack.onDisplayChanged(DisplayContent.this);
Robert Carr3b716242016-08-16 16:02:21 -07001876 }
Wale Ogunwale19e452e2016-10-12 12:36:29 -07001877
1878 void moveStack(TaskStack stack, boolean toTop) {
1879 if (StackId.isAlwaysOnTop(stack.mStackId) && !toTop) {
1880 // This stack is always-on-top silly...
1881 Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + stack + " to bottom");
1882 return;
1883 }
1884
1885 if (!mChildren.contains(stack)) {
1886 Slog.wtf(TAG_WM, "moving stack that was not added: " + stack, new Throwable());
1887 }
1888 removeChild(stack);
1889 addChild(stack, toTop);
1890 }
1891
1892 private void addChild(TaskStack stack, boolean toTop) {
1893 int addIndex = toTop ? mChildren.size() : 0;
1894
1895 if (toTop
1896 && mService.isStackVisibleLocked(PINNED_STACK_ID)
1897 && stack.mStackId != PINNED_STACK_ID) {
1898 // The pinned stack is always the top most stack (always-on-top) when it is visible.
1899 // So, stack is moved just below the pinned stack.
1900 addIndex--;
1901 TaskStack topStack = mChildren.get(addIndex);
1902 if (topStack.mStackId != PINNED_STACK_ID) {
1903 throw new IllegalStateException("Pinned stack isn't top stack??? " + mChildren);
1904 }
1905 }
1906 addChild(stack, addIndex);
1907 setLayoutNeeded();
1908 }
1909
1910 }
1911
1912 /**
1913 * Window container class that contains all containers on this display that are not related to
1914 * Apps. E.g. status bar.
1915 */
1916 private static class NonAppWindowContainers extends DisplayChildWindowContainer<WindowToken> {
1917
Robert Carr3b716242016-08-16 16:02:21 -07001918 }
Craig Mautner59c00972012-07-30 12:10:24 -07001919}