blob: 287d7cd8a75887e682d41b97eb1a5c0da7780358 [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
Adrian Roosb125e0b2019-10-02 14:55:14 +020022import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
23import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS;
24import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_WINDOW_MOVEMENT;
lumark9bca6b42019-10-17 18:35:22 +080025import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
26import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
27import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
Wale Ogunwalee4da0c12016-07-29 12:47:02 -070028import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
29import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
30import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070031import static com.android.server.wm.WindowTokenProto.HASH_CODE;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070032import static com.android.server.wm.WindowTokenProto.PAUSED;
33import static com.android.server.wm.WindowTokenProto.WAITING_TO_SHOW;
34import static com.android.server.wm.WindowTokenProto.WINDOWS;
35import static com.android.server.wm.WindowTokenProto.WINDOW_CONTAINER;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080036
Vishnu Nair04ab4392018-01-10 11:00:06 -080037import android.annotation.CallSuper;
Jorim Jaggife762342016-10-13 14:33:27 +020038import android.os.Debug;
39import android.os.IBinder;
Vishnu Nair04ab4392018-01-10 11:00:06 -080040import android.util.proto.ProtoOutputStream;
Jorim Jaggife762342016-10-13 14:33:27 +020041
Adrian Roosb125e0b2019-10-02 14:55:14 +020042import com.android.server.protolog.common.ProtoLog;
43
Jorim Jaggife762342016-10-13 14:33:27 +020044import java.io.PrintWriter;
Vishnu Nair04ab4392018-01-10 11:00:06 -080045import java.util.Comparator;
Jorim Jaggife762342016-10-13 14:33:27 +020046
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080047/**
Wale Ogunwaled1c37912016-08-16 03:19:39 -070048 * Container of a set of related windows in the window manager. Often this is an AppWindowToken,
49 * which is the handle for an Activity that it uses to display windows. For nested windows, there is
50 * a WindowToken created for the parent window to manage its children.
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080051 */
Wale Ogunwaled90546a2016-09-09 23:28:03 -070052class WindowToken extends WindowContainer<WindowState> {
Wale Ogunwalee4da0c12016-07-29 12:47:02 -070053 private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowToken" : TAG_WM;
54
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080055 // The actual token.
56 final IBinder token;
57
58 // The type of window this token is for, as per WindowManager.LayoutParams.
59 final int windowType;
60
Adrian Roos4bef62e2018-03-21 19:52:09 +010061 /** {@code true} if this holds the rounded corner overlay */
62 final boolean mRoundedCornerOverlay;
63
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080064 // Set if this token was explicitly added by a client, so should
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -080065 // persist (not be removed) when all windows are removed.
66 boolean mPersistOnEmpty;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080067
68 // For printing.
69 String stringName;
70
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080071 // Is key dispatching paused for this token?
72 boolean paused = false;
73
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080074 // 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
Wale Ogunwale5cd907d2017-01-26 14:14:08 -080081 /** The owner has {@link android.Manifest.permission#MANAGE_APP_TOKENS} */
82 final boolean mOwnerCanManageAppTokens;
83
Wale Ogunwale07bcab72016-10-14 15:30:09 -070084 /**
85 * Compares two child window of this token and returns -1 if the first is lesser than the
86 * second in terms of z-order and 1 otherwise.
87 */
88 private final Comparator<WindowState> mWindowComparator =
89 (WindowState newWindow, WindowState existingWindow) -> {
90 final WindowToken token = WindowToken.this;
91 if (newWindow.mToken != token) {
92 throw new IllegalArgumentException("newWindow=" + newWindow
93 + " is not a child of token=" + token);
94 }
95
96 if (existingWindow.mToken != token) {
97 throw new IllegalArgumentException("existingWindow=" + existingWindow
98 + " is not a child of token=" + token);
99 }
100
101 return isFirstChildWindowGreaterThanSecond(newWindow, existingWindow) ? 1 : -1;
102 };
103
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800104 WindowToken(WindowManagerService service, IBinder _token, int type, boolean persistOnEmpty,
Wale Ogunwale5cd907d2017-01-26 14:14:08 -0800105 DisplayContent dc, boolean ownerCanManageAppTokens) {
Adrian Roos4bef62e2018-03-21 19:52:09 +0100106 this(service, _token, type, persistOnEmpty, dc, ownerCanManageAppTokens,
107 false /* roundedCornersOverlay */);
108 }
109
110 WindowToken(WindowManagerService service, IBinder _token, int type, boolean persistOnEmpty,
111 DisplayContent dc, boolean ownerCanManageAppTokens, boolean roundedCornerOverlay) {
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100112 super(service);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800113 token = _token;
114 windowType = type;
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800115 mPersistOnEmpty = persistOnEmpty;
Wale Ogunwale5cd907d2017-01-26 14:14:08 -0800116 mOwnerCanManageAppTokens = ownerCanManageAppTokens;
Adrian Roos4bef62e2018-03-21 19:52:09 +0100117 mRoundedCornerOverlay = roundedCornerOverlay;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800118 if (dc != null) {
119 onDisplayChanged(dc);
120 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800121 }
122
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800123 void removeAllWindowsIfPossible() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700124 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700125 final WindowState win = mChildren.get(i);
Adrian Roosb125e0b2019-10-02 14:55:14 +0200126 ProtoLog.w(WM_DEBUG_WINDOW_MOVEMENT,
127 "removeAllWindowsIfPossible: removing win=%s", win);
Wale Ogunwale92fc3722016-08-05 12:19:08 -0700128 win.removeIfPossible();
Svetoslav3a5c7212014-10-14 09:54:26 -0700129 }
130 }
131
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700132 void setExiting() {
chaviwaec55ff52017-12-04 18:39:34 -0800133 if (mChildren.size() == 0) {
134 super.removeImmediately();
135 return;
136 }
137
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800138 // This token is exiting, so allow it to be removed when it no longer contains any windows.
139 mPersistOnEmpty = false;
140
Issei Suzukif2f6c912019-11-08 11:24:18 +0100141 if (!isVisible()) {
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700142 return;
143 }
144
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700145 final int count = mChildren.size();
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700146 boolean changed = false;
lumark9bca6b42019-10-17 18:35:22 +0800147 final boolean delayed = isAnimating(TRANSITION | PARENTS | CHILDREN);
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700148
149 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700150 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700151 changed |= win.onSetAppExiting();
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700152 }
153
Issei Suzukif2f6c912019-11-08 11:24:18 +0100154 final ActivityRecord app = asActivityRecord();
155 if (app != null) {
156 app.setVisible(false);
157 }
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700158
159 if (changed) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800160 mWmService.mWindowPlacerLocked.performSurfacePlacement();
161 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /*updateInputWindows*/);
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700162 }
163
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700164 if (delayed) {
165 mDisplayContent.mExitingTokens.add(this);
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700166 }
167 }
168
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700169 /**
Riddle Hsub398da32019-01-21 21:48:16 +0800170 * @return The scale for applications running in compatibility mode. Multiply the size in the
171 * application by this scale will be the size in the screen.
172 */
173 float getSizeCompatScale() {
174 return mDisplayContent.mCompatibleScreenScale;
175 }
176
177 /**
Wale Ogunwale07bcab72016-10-14 15:30:09 -0700178 * Returns true if the new window is considered greater than the existing window in terms of
179 * z-order.
180 */
181 protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
182 WindowState existingWindow) {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700183 // New window is considered greater if it has a higher or equal base layer.
184 return newWindow.mBaseLayer >= existingWindow.mBaseLayer;
Wale Ogunwale07bcab72016-10-14 15:30:09 -0700185 }
186
Wale Ogunwale92fc3722016-08-05 12:19:08 -0700187 void addWindow(final WindowState win) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200188 ProtoLog.d(WM_DEBUG_FOCUS,
189 "addWindow: win=%s Callers=%s", win, Debug.getCallers(5));
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700190
Wale Ogunwale6213caa2016-12-02 16:47:15 +0000191 if (win.isChildWindow()) {
192 // Child windows are added to their parent windows.
Wale Ogunwaleb9a07c32016-10-12 14:55:56 -0700193 return;
194 }
Wale Ogunwaleb9a07c32016-10-12 14:55:56 -0700195 if (!mChildren.contains(win)) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200196 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "Adding %s to %s", win, this);
Wale Ogunwale6213caa2016-12-02 16:47:15 +0000197 addChild(win, mWindowComparator);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800198 mWmService.mWindowsChanged = true;
Wale Ogunwale6213caa2016-12-02 16:47:15 +0000199 // TODO: Should we also be setting layout needed here and other places?
Wale Ogunwaleb9a07c32016-10-12 14:55:56 -0700200 }
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700201 }
202
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700203 /** Returns true if the token windows list is empty. */
204 boolean isEmpty() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700205 return mChildren.isEmpty();
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700206 }
207
208 WindowState getReplacingWindow() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700209 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700210 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700211 final WindowState replacing = win.getReplacingWindow();
212 if (replacing != null) {
213 return replacing;
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700214 }
215 }
216 return null;
217 }
218
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700219 /** Return true if this token has a window that wants the wallpaper displayed behind it. */
220 boolean windowsCanBeWallpaperTarget() {
221 for (int j = mChildren.size() - 1; j >= 0; j--) {
222 final WindowState w = mChildren.get(j);
223 if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
224 return true;
225 }
226 }
227
228 return false;
229 }
230
Garfield Tane8d84ab2019-10-11 09:49:40 -0700231 ActivityRecord asActivityRecord() {
Wale Ogunwale2049dbf2016-08-02 21:05:23 -0700232 // TODO: Not sure if this is the best way to handle this vs. using instanceof and casting.
233 // I am not an app window token!
234 return null;
235 }
236
Wale Ogunwale02319a62016-09-26 15:21:22 -0700237 @Override
238 void removeImmediately() {
Wale Ogunwale02319a62016-09-26 15:21:22 -0700239 if (mDisplayContent != null) {
240 mDisplayContent.removeWindowToken(token);
Wale Ogunwale02319a62016-09-26 15:21:22 -0700241 }
Wale Ogunwalecfca2582016-10-19 09:53:25 -0700242 // Needs to occur after the token is removed from the display above to avoid attempt at
243 // duplicate removal of this window container from it's parent.
244 super.removeImmediately();
Wale Ogunwale02319a62016-09-26 15:21:22 -0700245 }
246
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800247 @Override
Wale Ogunwale02319a62016-09-26 15:21:22 -0700248 void onDisplayChanged(DisplayContent dc) {
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800249 dc.reParentWindowToken(this);
Robert Carrda61ba92017-03-29 15:52:23 -0700250
251 // TODO(b/36740756): One day this should perhaps be hooked
252 // up with goodToGo, so we don't move a window
253 // to another display before the window behind
254 // it is ready.
Robert Carrda61ba92017-03-29 15:52:23 -0700255
Wale Ogunwale02319a62016-09-26 15:21:22 -0700256 super.onDisplayChanged(dc);
257 }
258
Wale Ogunwale0d5609b2017-09-13 05:55:07 -0700259 @CallSuper
260 @Override
Nataniel Borges023ecb52019-01-16 14:15:43 -0800261 public void writeToProto(ProtoOutputStream proto, long fieldId,
262 @WindowTraceLogLevel int logLevel) {
263 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
264 return;
265 }
266
Steven Timotiusaf03df62017-07-18 16:56:43 -0700267 final long token = proto.start(fieldId);
Nataniel Borges023ecb52019-01-16 14:15:43 -0800268 super.writeToProto(proto, WINDOW_CONTAINER, logLevel);
Steven Timotiusaf03df62017-07-18 16:56:43 -0700269 proto.write(HASH_CODE, System.identityHashCode(this));
270 for (int i = 0; i < mChildren.size(); i++) {
271 final WindowState w = mChildren.get(i);
Nataniel Borges023ecb52019-01-16 14:15:43 -0800272 w.writeToProto(proto, WINDOWS, logLevel);
Steven Timotiusaf03df62017-07-18 16:56:43 -0700273 }
Vishnu Nair04ab4392018-01-10 11:00:06 -0800274 proto.write(WAITING_TO_SHOW, waitingToShow);
275 proto.write(PAUSED, paused);
Steven Timotiusaf03df62017-07-18 16:56:43 -0700276 proto.end(token);
277 }
278
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200279 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
280 super.dump(pw, prefix, dumpAll);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700281 pw.print(prefix); pw.print("windows="); pw.println(mChildren);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800282 pw.print(prefix); pw.print("windowType="); pw.print(windowType);
Issei Suzuki7b9e2572019-11-14 16:19:54 +0100283 pw.print(" hasVisible="); pw.println(hasVisible);
Wale Ogunwale7a8889a2019-11-16 08:23:42 -0800284 if (waitingToShow) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800285 pw.print(prefix); pw.print("waitingToShow="); pw.print(waitingToShow);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800286 }
287 }
288
289 @Override
290 public String toString() {
291 if (stringName == null) {
292 StringBuilder sb = new StringBuilder();
293 sb.append("WindowToken{");
294 sb.append(Integer.toHexString(System.identityHashCode(this)));
Dianne Hackbornef03a7f2012-10-29 18:46:52 -0700295 sb.append(" "); sb.append(token); sb.append('}');
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800296 stringName = sb.toString();
297 }
298 return stringName;
299 }
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700300
301 @Override
302 String getName() {
303 return toString();
304 }
David Stevens9440dc82017-03-16 19:00:20 -0700305
Robert Carr683e05d2018-04-18 15:11:04 -0700306 /**
307 * Return whether windows from this token can layer above the
308 * system bars, or in other words extend outside of the "Decor Frame"
309 */
310 boolean canLayerAboveSystemBars() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800311 int layer = mWmService.mPolicy.getWindowLayerFromTypeLw(windowType,
Robert Carr683e05d2018-04-18 15:11:04 -0700312 mOwnerCanManageAppTokens);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800313 int navLayer = mWmService.mPolicy.getWindowLayerFromTypeLw(TYPE_NAVIGATION_BAR,
Robert Carr683e05d2018-04-18 15:11:04 -0700314 mOwnerCanManageAppTokens);
315 return mOwnerCanManageAppTokens && (layer > navLayer);
316 }
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800317}