blob: f0b9c62f2843069f2df010f41b9f99a8796817db [file] [log] [blame]
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08001/*
2 * Copyright (C) 2011 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 Ogunwale0c4a40ef2016-10-07 07:06:40 -070019import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
Robert Carr683e05d2018-04-18 15:11:04 -070020import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
Louis Chang7501e332018-08-20 13:08:39 +080021
Wale Ogunwalee4da0c12016-07-29 12:47:02 -070022import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
23import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
Wale Ogunwalee4da0c12016-07-29 12:47:02 -070024import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
25import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
26import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
27import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070028import static com.android.server.wm.WindowTokenProto.HASH_CODE;
29import static com.android.server.wm.WindowTokenProto.HIDDEN;
30import static com.android.server.wm.WindowTokenProto.PAUSED;
31import static com.android.server.wm.WindowTokenProto.WAITING_TO_SHOW;
32import static com.android.server.wm.WindowTokenProto.WINDOWS;
33import static com.android.server.wm.WindowTokenProto.WINDOW_CONTAINER;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080034
Vishnu Nair04ab4392018-01-10 11:00:06 -080035import android.annotation.CallSuper;
Jorim Jaggife762342016-10-13 14:33:27 +020036import android.os.Debug;
37import android.os.IBinder;
Jorim Jaggife762342016-10-13 14:33:27 +020038import android.util.Slog;
Vishnu Nair04ab4392018-01-10 11:00:06 -080039import android.util.proto.ProtoOutputStream;
Jorim Jaggife762342016-10-13 14:33:27 +020040
41import java.io.PrintWriter;
Vishnu Nair04ab4392018-01-10 11:00:06 -080042import java.util.Comparator;
Jorim Jaggife762342016-10-13 14:33:27 +020043
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080044/**
Wale Ogunwaled1c37912016-08-16 03:19:39 -070045 * Container of a set of related windows in the window manager. Often this is an AppWindowToken,
46 * which is the handle for an Activity that it uses to display windows. For nested windows, there is
47 * a WindowToken created for the parent window to manage its children.
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080048 */
Wale Ogunwaled90546a2016-09-09 23:28:03 -070049class WindowToken extends WindowContainer<WindowState> {
Wale Ogunwalee4da0c12016-07-29 12:47:02 -070050 private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowToken" : TAG_WM;
51
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080052 // The actual token.
53 final IBinder token;
54
55 // The type of window this token is for, as per WindowManager.LayoutParams.
56 final int windowType;
57
Adrian Roos4bef62e2018-03-21 19:52:09 +010058 /** {@code true} if this holds the rounded corner overlay */
59 final boolean mRoundedCornerOverlay;
60
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080061 // Set if this token was explicitly added by a client, so should
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -080062 // persist (not be removed) when all windows are removed.
63 boolean mPersistOnEmpty;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080064
65 // For printing.
66 String stringName;
67
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080068 // Is key dispatching paused for this token?
69 boolean paused = false;
70
71 // Should this token's windows be hidden?
Jorim Jaggif5f9e122017-10-24 18:21:09 +020072 private boolean mHidden;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080073
74 // Temporary for finding which tokens no longer have visible windows.
75 boolean hasVisible;
76
77 // Set to true when this token is in a pending transaction where it
78 // will be shown.
79 boolean waitingToShow;
80
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080081 // Set to true when this token is in a pending transaction where its
82 // windows will be put to the bottom of the list.
83 boolean sendingToBottom;
84
Wale Ogunwale02319a62016-09-26 15:21:22 -070085 // The display this token is on.
Jorim Jaggi879ff722016-11-04 18:08:17 -070086 protected DisplayContent mDisplayContent;
Wale Ogunwale02319a62016-09-26 15:21:22 -070087
Wale Ogunwale5cd907d2017-01-26 14:14:08 -080088 /** The owner has {@link android.Manifest.permission#MANAGE_APP_TOKENS} */
89 final boolean mOwnerCanManageAppTokens;
90
Wale Ogunwale07bcab72016-10-14 15:30:09 -070091 /**
92 * Compares two child window of this token and returns -1 if the first is lesser than the
93 * second in terms of z-order and 1 otherwise.
94 */
95 private final Comparator<WindowState> mWindowComparator =
96 (WindowState newWindow, WindowState existingWindow) -> {
97 final WindowToken token = WindowToken.this;
98 if (newWindow.mToken != token) {
99 throw new IllegalArgumentException("newWindow=" + newWindow
100 + " is not a child of token=" + token);
101 }
102
103 if (existingWindow.mToken != token) {
104 throw new IllegalArgumentException("existingWindow=" + existingWindow
105 + " is not a child of token=" + token);
106 }
107
108 return isFirstChildWindowGreaterThanSecond(newWindow, existingWindow) ? 1 : -1;
109 };
110
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800111 WindowToken(WindowManagerService service, IBinder _token, int type, boolean persistOnEmpty,
Wale Ogunwale5cd907d2017-01-26 14:14:08 -0800112 DisplayContent dc, boolean ownerCanManageAppTokens) {
Adrian Roos4bef62e2018-03-21 19:52:09 +0100113 this(service, _token, type, persistOnEmpty, dc, ownerCanManageAppTokens,
114 false /* roundedCornersOverlay */);
115 }
116
117 WindowToken(WindowManagerService service, IBinder _token, int type, boolean persistOnEmpty,
118 DisplayContent dc, boolean ownerCanManageAppTokens, boolean roundedCornerOverlay) {
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100119 super(service);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800120 token = _token;
121 windowType = type;
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800122 mPersistOnEmpty = persistOnEmpty;
Wale Ogunwale5cd907d2017-01-26 14:14:08 -0800123 mOwnerCanManageAppTokens = ownerCanManageAppTokens;
Adrian Roos4bef62e2018-03-21 19:52:09 +0100124 mRoundedCornerOverlay = roundedCornerOverlay;
Wale Ogunwale02319a62016-09-26 15:21:22 -0700125 onDisplayChanged(dc);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800126 }
127
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200128 void setHidden(boolean hidden) {
129 if (hidden != mHidden) {
130 mHidden = hidden;
131 }
132 }
133
134 boolean isHidden() {
135 return mHidden;
136 }
137
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800138 void removeAllWindowsIfPossible() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700139 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700140 final WindowState win = mChildren.get(i);
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800141 if (DEBUG_WINDOW_MOVEMENT) Slog.w(TAG_WM,
142 "removeAllWindowsIfPossible: removing win=" + win);
Wale Ogunwale92fc3722016-08-05 12:19:08 -0700143 win.removeIfPossible();
Svetoslav3a5c7212014-10-14 09:54:26 -0700144 }
145 }
146
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700147 void setExiting() {
chaviwaec55ff52017-12-04 18:39:34 -0800148 if (mChildren.size() == 0) {
149 super.removeImmediately();
150 return;
151 }
152
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800153 // This token is exiting, so allow it to be removed when it no longer contains any windows.
154 mPersistOnEmpty = false;
155
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200156 if (mHidden) {
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700157 return;
158 }
159
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700160 final int count = mChildren.size();
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700161 boolean changed = false;
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700162 boolean delayed = false;
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700163
164 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700165 final WindowState win = mChildren.get(i);
Jorim Jaggi5bdccba2018-08-13 16:40:49 +0200166 if (win.isAnimating()) {
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700167 delayed = true;
168 }
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700169 changed |= win.onSetAppExiting();
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700170 }
171
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200172 setHidden(true);
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700173
174 if (changed) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800175 mWmService.mWindowPlacerLocked.performSurfacePlacement();
176 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /*updateInputWindows*/);
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700177 }
178
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700179 if (delayed) {
180 mDisplayContent.mExitingTokens.add(this);
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700181 }
182 }
183
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700184 /**
Riddle Hsub398da32019-01-21 21:48:16 +0800185 * @return The scale for applications running in compatibility mode. Multiply the size in the
186 * application by this scale will be the size in the screen.
187 */
188 float getSizeCompatScale() {
189 return mDisplayContent.mCompatibleScreenScale;
190 }
191
192 /**
Wale Ogunwale07bcab72016-10-14 15:30:09 -0700193 * Returns true if the new window is considered greater than the existing window in terms of
194 * z-order.
195 */
196 protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
197 WindowState existingWindow) {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700198 // New window is considered greater if it has a higher or equal base layer.
199 return newWindow.mBaseLayer >= existingWindow.mBaseLayer;
Wale Ogunwale07bcab72016-10-14 15:30:09 -0700200 }
201
Wale Ogunwale92fc3722016-08-05 12:19:08 -0700202 void addWindow(final WindowState win) {
Wale Ogunwale07bcab72016-10-14 15:30:09 -0700203 if (DEBUG_FOCUS) Slog.d(TAG_WM,
204 "addWindow: win=" + win + " Callers=" + Debug.getCallers(5));
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700205
Wale Ogunwale6213caa2016-12-02 16:47:15 +0000206 if (win.isChildWindow()) {
207 // Child windows are added to their parent windows.
Wale Ogunwaleb9a07c32016-10-12 14:55:56 -0700208 return;
209 }
Wale Ogunwaleb9a07c32016-10-12 14:55:56 -0700210 if (!mChildren.contains(win)) {
Wale Ogunwale6213caa2016-12-02 16:47:15 +0000211 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + this);
212 addChild(win, mWindowComparator);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800213 mWmService.mWindowsChanged = true;
Wale Ogunwale6213caa2016-12-02 16:47:15 +0000214 // TODO: Should we also be setting layout needed here and other places?
Wale Ogunwaleb9a07c32016-10-12 14:55:56 -0700215 }
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700216 }
217
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700218 /** Returns true if the token windows list is empty. */
219 boolean isEmpty() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700220 return mChildren.isEmpty();
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700221 }
222
223 WindowState getReplacingWindow() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700224 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700225 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700226 final WindowState replacing = win.getReplacingWindow();
227 if (replacing != null) {
228 return replacing;
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700229 }
230 }
231 return null;
232 }
233
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700234 /** Return true if this token has a window that wants the wallpaper displayed behind it. */
235 boolean windowsCanBeWallpaperTarget() {
236 for (int j = mChildren.size() - 1; j >= 0; j--) {
237 final WindowState w = mChildren.get(j);
238 if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
239 return true;
240 }
241 }
242
243 return false;
244 }
245
Wale Ogunwale2049dbf2016-08-02 21:05:23 -0700246 AppWindowToken asAppWindowToken() {
247 // TODO: Not sure if this is the best way to handle this vs. using instanceof and casting.
248 // I am not an app window token!
249 return null;
250 }
251
Wale Ogunwale02319a62016-09-26 15:21:22 -0700252 DisplayContent getDisplayContent() {
253 return mDisplayContent;
254 }
255
256 @Override
257 void removeImmediately() {
Wale Ogunwale02319a62016-09-26 15:21:22 -0700258 if (mDisplayContent != null) {
259 mDisplayContent.removeWindowToken(token);
Wale Ogunwale02319a62016-09-26 15:21:22 -0700260 }
Wale Ogunwalecfca2582016-10-19 09:53:25 -0700261 // Needs to occur after the token is removed from the display above to avoid attempt at
262 // duplicate removal of this window container from it's parent.
263 super.removeImmediately();
Wale Ogunwale02319a62016-09-26 15:21:22 -0700264 }
265
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800266 @Override
Wale Ogunwale02319a62016-09-26 15:21:22 -0700267 void onDisplayChanged(DisplayContent dc) {
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800268 dc.reParentWindowToken(this);
Wale Ogunwale02319a62016-09-26 15:21:22 -0700269 mDisplayContent = dc;
Robert Carrda61ba92017-03-29 15:52:23 -0700270
271 // TODO(b/36740756): One day this should perhaps be hooked
272 // up with goodToGo, so we don't move a window
273 // to another display before the window behind
274 // it is ready.
Robert Carrda61ba92017-03-29 15:52:23 -0700275
Wale Ogunwale02319a62016-09-26 15:21:22 -0700276 super.onDisplayChanged(dc);
277 }
278
Wale Ogunwale0d5609b2017-09-13 05:55:07 -0700279 @CallSuper
280 @Override
Nataniel Borges023ecb52019-01-16 14:15:43 -0800281 public void writeToProto(ProtoOutputStream proto, long fieldId,
282 @WindowTraceLogLevel int logLevel) {
283 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
284 return;
285 }
286
Steven Timotiusaf03df62017-07-18 16:56:43 -0700287 final long token = proto.start(fieldId);
Nataniel Borges023ecb52019-01-16 14:15:43 -0800288 super.writeToProto(proto, WINDOW_CONTAINER, logLevel);
Steven Timotiusaf03df62017-07-18 16:56:43 -0700289 proto.write(HASH_CODE, System.identityHashCode(this));
290 for (int i = 0; i < mChildren.size(); i++) {
291 final WindowState w = mChildren.get(i);
Nataniel Borges023ecb52019-01-16 14:15:43 -0800292 w.writeToProto(proto, WINDOWS, logLevel);
Steven Timotiusaf03df62017-07-18 16:56:43 -0700293 }
Vishnu Nair04ab4392018-01-10 11:00:06 -0800294 proto.write(HIDDEN, mHidden);
295 proto.write(WAITING_TO_SHOW, waitingToShow);
296 proto.write(PAUSED, paused);
Steven Timotiusaf03df62017-07-18 16:56:43 -0700297 proto.end(token);
298 }
299
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200300 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
301 super.dump(pw, prefix, dumpAll);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700302 pw.print(prefix); pw.print("windows="); pw.println(mChildren);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800303 pw.print(prefix); pw.print("windowType="); pw.print(windowType);
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200304 pw.print(" hidden="); pw.print(mHidden);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800305 pw.print(" hasVisible="); pw.println(hasVisible);
Wale Ogunwale10cb5e22015-05-24 12:36:21 -0700306 if (waitingToShow || sendingToBottom) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800307 pw.print(prefix); pw.print("waitingToShow="); pw.print(waitingToShow);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800308 pw.print(" sendingToBottom="); pw.print(sendingToBottom);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800309 }
310 }
311
312 @Override
313 public String toString() {
314 if (stringName == null) {
315 StringBuilder sb = new StringBuilder();
316 sb.append("WindowToken{");
317 sb.append(Integer.toHexString(System.identityHashCode(this)));
Dianne Hackbornef03a7f2012-10-29 18:46:52 -0700318 sb.append(" "); sb.append(token); sb.append('}');
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800319 stringName = sb.toString();
320 }
321 return stringName;
322 }
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700323
324 @Override
325 String getName() {
326 return toString();
327 }
David Stevens9440dc82017-03-16 19:00:20 -0700328
329 boolean okToDisplay() {
330 return mDisplayContent != null && mDisplayContent.okToDisplay();
331 }
332
333 boolean okToAnimate() {
334 return mDisplayContent != null && mDisplayContent.okToAnimate();
335 }
Robert Carr683e05d2018-04-18 15:11:04 -0700336
337 /**
338 * Return whether windows from this token can layer above the
339 * system bars, or in other words extend outside of the "Decor Frame"
340 */
341 boolean canLayerAboveSystemBars() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800342 int layer = mWmService.mPolicy.getWindowLayerFromTypeLw(windowType,
Robert Carr683e05d2018-04-18 15:11:04 -0700343 mOwnerCanManageAppTokens);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800344 int navLayer = mWmService.mPolicy.getWindowLayerFromTypeLw(TYPE_NAVIGATION_BAR,
Robert Carr683e05d2018-04-18 15:11:04 -0700345 mOwnerCanManageAppTokens);
346 return mOwnerCanManageAppTokens && (layer > navLayer);
347 }
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800348}