blob: b97460ae9eb8355758e08d1ff523cfcd61397a3d [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;
Wale Ogunwalee4da0c12016-07-29 12:47:02 -070021import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
22import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
Wale Ogunwalee4da0c12016-07-29 12:47:02 -070023import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
24import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
25import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
26import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070027import static com.android.server.wm.WindowTokenProto.HASH_CODE;
28import static com.android.server.wm.WindowTokenProto.HIDDEN;
29import static com.android.server.wm.WindowTokenProto.PAUSED;
30import static com.android.server.wm.WindowTokenProto.WAITING_TO_SHOW;
31import static com.android.server.wm.WindowTokenProto.WINDOWS;
32import static com.android.server.wm.WindowTokenProto.WINDOW_CONTAINER;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080033
Vishnu Nair04ab4392018-01-10 11:00:06 -080034import android.annotation.CallSuper;
Jorim Jaggife762342016-10-13 14:33:27 +020035import android.os.Debug;
36import android.os.IBinder;
Jorim Jaggife762342016-10-13 14:33:27 +020037import android.util.Slog;
Vishnu Nair04ab4392018-01-10 11:00:06 -080038import android.util.proto.ProtoOutputStream;
Jorim Jaggife762342016-10-13 14:33:27 +020039
40import java.io.PrintWriter;
Vishnu Nair04ab4392018-01-10 11:00:06 -080041import java.util.Comparator;
Jorim Jaggife762342016-10-13 14:33:27 +020042
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080043/**
Wale Ogunwaled1c37912016-08-16 03:19:39 -070044 * Container of a set of related windows in the window manager. Often this is an AppWindowToken,
45 * which is the handle for an Activity that it uses to display windows. For nested windows, there is
46 * a WindowToken created for the parent window to manage its children.
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080047 */
Wale Ogunwaled90546a2016-09-09 23:28:03 -070048class WindowToken extends WindowContainer<WindowState> {
Wale Ogunwalee4da0c12016-07-29 12:47:02 -070049 private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowToken" : TAG_WM;
50
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080051 // The actual token.
52 final IBinder token;
53
54 // The type of window this token is for, as per WindowManager.LayoutParams.
55 final int windowType;
56
Adrian Roos4bef62e2018-03-21 19:52:09 +010057 /** {@code true} if this holds the rounded corner overlay */
58 final boolean mRoundedCornerOverlay;
59
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080060 // Set if this token was explicitly added by a client, so should
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -080061 // persist (not be removed) when all windows are removed.
62 boolean mPersistOnEmpty;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080063
64 // For printing.
65 String stringName;
66
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080067 // Is key dispatching paused for this token?
68 boolean paused = false;
69
70 // Should this token's windows be hidden?
Jorim Jaggif5f9e122017-10-24 18:21:09 +020071 private boolean mHidden;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080072
73 // Temporary for finding which tokens no longer have visible windows.
74 boolean hasVisible;
75
76 // Set to true when this token is in a pending transaction where it
77 // will be shown.
78 boolean waitingToShow;
79
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080080 // Set to true when this token is in a pending transaction where its
81 // windows will be put to the bottom of the list.
82 boolean sendingToBottom;
83
Wale Ogunwale02319a62016-09-26 15:21:22 -070084 // The display this token is on.
Jorim Jaggi879ff722016-11-04 18:08:17 -070085 protected DisplayContent mDisplayContent;
Wale Ogunwale02319a62016-09-26 15:21:22 -070086
Wale Ogunwale5cd907d2017-01-26 14:14:08 -080087 /** The owner has {@link android.Manifest.permission#MANAGE_APP_TOKENS} */
88 final boolean mOwnerCanManageAppTokens;
89
Wale Ogunwale07bcab72016-10-14 15:30:09 -070090 /**
91 * Compares two child window of this token and returns -1 if the first is lesser than the
92 * second in terms of z-order and 1 otherwise.
93 */
94 private final Comparator<WindowState> mWindowComparator =
95 (WindowState newWindow, WindowState existingWindow) -> {
96 final WindowToken token = WindowToken.this;
97 if (newWindow.mToken != token) {
98 throw new IllegalArgumentException("newWindow=" + newWindow
99 + " is not a child of token=" + token);
100 }
101
102 if (existingWindow.mToken != token) {
103 throw new IllegalArgumentException("existingWindow=" + existingWindow
104 + " is not a child of token=" + token);
105 }
106
107 return isFirstChildWindowGreaterThanSecond(newWindow, existingWindow) ? 1 : -1;
108 };
109
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800110 WindowToken(WindowManagerService service, IBinder _token, int type, boolean persistOnEmpty,
Wale Ogunwale5cd907d2017-01-26 14:14:08 -0800111 DisplayContent dc, boolean ownerCanManageAppTokens) {
Adrian Roos4bef62e2018-03-21 19:52:09 +0100112 this(service, _token, type, persistOnEmpty, dc, ownerCanManageAppTokens,
113 false /* roundedCornersOverlay */);
114 }
115
116 WindowToken(WindowManagerService service, IBinder _token, int type, boolean persistOnEmpty,
117 DisplayContent dc, boolean ownerCanManageAppTokens, boolean roundedCornerOverlay) {
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100118 super(service);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800119 token = _token;
120 windowType = type;
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800121 mPersistOnEmpty = persistOnEmpty;
Wale Ogunwale5cd907d2017-01-26 14:14:08 -0800122 mOwnerCanManageAppTokens = ownerCanManageAppTokens;
Adrian Roos4bef62e2018-03-21 19:52:09 +0100123 mRoundedCornerOverlay = roundedCornerOverlay;
Wale Ogunwale02319a62016-09-26 15:21:22 -0700124 onDisplayChanged(dc);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800125 }
126
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200127 void setHidden(boolean hidden) {
128 if (hidden != mHidden) {
129 mHidden = hidden;
130 }
131 }
132
133 boolean isHidden() {
134 return mHidden;
135 }
136
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800137 void removeAllWindowsIfPossible() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700138 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700139 final WindowState win = mChildren.get(i);
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800140 if (DEBUG_WINDOW_MOVEMENT) Slog.w(TAG_WM,
141 "removeAllWindowsIfPossible: removing win=" + win);
Wale Ogunwale92fc3722016-08-05 12:19:08 -0700142 win.removeIfPossible();
Svetoslav3a5c7212014-10-14 09:54:26 -0700143 }
144 }
145
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700146 void setExiting() {
chaviwaec55ff52017-12-04 18:39:34 -0800147 if (mChildren.size() == 0) {
148 super.removeImmediately();
149 return;
150 }
151
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800152 // This token is exiting, so allow it to be removed when it no longer contains any windows.
153 mPersistOnEmpty = false;
154
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200155 if (mHidden) {
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700156 return;
157 }
158
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700159 final int count = mChildren.size();
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700160 boolean changed = false;
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700161 boolean delayed = false;
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700162
163 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700164 final WindowState win = mChildren.get(i);
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700165 if (win.mWinAnimator.isAnimationSet()) {
166 delayed = true;
167 }
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700168 changed |= win.onSetAppExiting();
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700169 }
170
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200171 setHidden(true);
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700172
173 if (changed) {
Wale Ogunwale2049dbf2016-08-02 21:05:23 -0700174 mService.mWindowPlacerLocked.performSurfacePlacement();
175 mService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /*updateInputWindows*/);
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700176 }
177
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700178 if (delayed) {
179 mDisplayContent.mExitingTokens.add(this);
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700180 }
181 }
182
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700183 /**
Wale Ogunwale07bcab72016-10-14 15:30:09 -0700184 * Returns true if the new window is considered greater than the existing window in terms of
185 * z-order.
186 */
187 protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
188 WindowState existingWindow) {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700189 // New window is considered greater if it has a higher or equal base layer.
190 return newWindow.mBaseLayer >= existingWindow.mBaseLayer;
Wale Ogunwale07bcab72016-10-14 15:30:09 -0700191 }
192
Wale Ogunwale92fc3722016-08-05 12:19:08 -0700193 void addWindow(final WindowState win) {
Wale Ogunwale07bcab72016-10-14 15:30:09 -0700194 if (DEBUG_FOCUS) Slog.d(TAG_WM,
195 "addWindow: win=" + win + " Callers=" + Debug.getCallers(5));
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700196
Wale Ogunwale6213caa2016-12-02 16:47:15 +0000197 if (win.isChildWindow()) {
198 // Child windows are added to their parent windows.
Wale Ogunwaleb9a07c32016-10-12 14:55:56 -0700199 return;
200 }
Wale Ogunwaleb9a07c32016-10-12 14:55:56 -0700201 if (!mChildren.contains(win)) {
Wale Ogunwale6213caa2016-12-02 16:47:15 +0000202 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + this);
203 addChild(win, mWindowComparator);
204 mService.mWindowsChanged = true;
205 // TODO: Should we also be setting layout needed here and other places?
Wale Ogunwaleb9a07c32016-10-12 14:55:56 -0700206 }
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700207 }
208
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700209 /** Returns true if the token windows list is empty. */
210 boolean isEmpty() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700211 return mChildren.isEmpty();
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700212 }
213
214 WindowState getReplacingWindow() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700215 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700216 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700217 final WindowState replacing = win.getReplacingWindow();
218 if (replacing != null) {
219 return replacing;
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700220 }
221 }
222 return null;
223 }
224
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700225 /** Return true if this token has a window that wants the wallpaper displayed behind it. */
226 boolean windowsCanBeWallpaperTarget() {
227 for (int j = mChildren.size() - 1; j >= 0; j--) {
228 final WindowState w = mChildren.get(j);
229 if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
230 return true;
231 }
232 }
233
234 return false;
235 }
236
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700237 int getHighestAnimLayer() {
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700238 int highest = -1;
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700239 for (int j = 0; j < mChildren.size(); j++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700240 final WindowState w = mChildren.get(j);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700241 final int wLayer = w.getHighestAnimLayer();
242 if (wLayer > highest) {
243 highest = wLayer;
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700244 }
245 }
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700246 return highest;
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700247 }
248
Wale Ogunwale2049dbf2016-08-02 21:05:23 -0700249 AppWindowToken asAppWindowToken() {
250 // TODO: Not sure if this is the best way to handle this vs. using instanceof and casting.
251 // I am not an app window token!
252 return null;
253 }
254
Wale Ogunwale02319a62016-09-26 15:21:22 -0700255 DisplayContent getDisplayContent() {
256 return mDisplayContent;
257 }
258
259 @Override
260 void removeImmediately() {
Wale Ogunwale02319a62016-09-26 15:21:22 -0700261 if (mDisplayContent != null) {
262 mDisplayContent.removeWindowToken(token);
Wale Ogunwale02319a62016-09-26 15:21:22 -0700263 }
Wale Ogunwalecfca2582016-10-19 09:53:25 -0700264 // Needs to occur after the token is removed from the display above to avoid attempt at
265 // duplicate removal of this window container from it's parent.
266 super.removeImmediately();
Wale Ogunwale02319a62016-09-26 15:21:22 -0700267 }
268
269 void onDisplayChanged(DisplayContent dc) {
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800270 dc.reParentWindowToken(this);
Wale Ogunwale02319a62016-09-26 15:21:22 -0700271 mDisplayContent = dc;
Robert Carrda61ba92017-03-29 15:52:23 -0700272
Adrian Roos4bef62e2018-03-21 19:52:09 +0100273 // The rounded corner overlay should not be rotated. We ensure that by moving it outside
274 // the windowing layer.
275 if (mRoundedCornerOverlay) {
276 mDisplayContent.reparentToOverlay(mPendingTransaction, mSurfaceControl);
277 }
278
Robert Carrda61ba92017-03-29 15:52:23 -0700279 // TODO(b/36740756): One day this should perhaps be hooked
280 // up with goodToGo, so we don't move a window
281 // to another display before the window behind
282 // it is ready.
Robert Carrda61ba92017-03-29 15:52:23 -0700283
Wale Ogunwale02319a62016-09-26 15:21:22 -0700284 super.onDisplayChanged(dc);
285 }
286
Wale Ogunwale0d5609b2017-09-13 05:55:07 -0700287 @CallSuper
288 @Override
Adrian Roos4921ccf2017-09-28 16:54:06 +0200289 public void writeToProto(ProtoOutputStream proto, long fieldId, boolean trim) {
Steven Timotiusaf03df62017-07-18 16:56:43 -0700290 final long token = proto.start(fieldId);
Adrian Roos4921ccf2017-09-28 16:54:06 +0200291 super.writeToProto(proto, WINDOW_CONTAINER, trim);
Steven Timotiusaf03df62017-07-18 16:56:43 -0700292 proto.write(HASH_CODE, System.identityHashCode(this));
293 for (int i = 0; i < mChildren.size(); i++) {
294 final WindowState w = mChildren.get(i);
Adrian Roos4921ccf2017-09-28 16:54:06 +0200295 w.writeToProto(proto, WINDOWS, trim);
Steven Timotiusaf03df62017-07-18 16:56:43 -0700296 }
Vishnu Nair04ab4392018-01-10 11:00:06 -0800297 proto.write(HIDDEN, mHidden);
298 proto.write(WAITING_TO_SHOW, waitingToShow);
299 proto.write(PAUSED, paused);
Steven Timotiusaf03df62017-07-18 16:56:43 -0700300 proto.end(token);
301 }
302
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200303 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
304 super.dump(pw, prefix, dumpAll);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700305 pw.print(prefix); pw.print("windows="); pw.println(mChildren);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800306 pw.print(prefix); pw.print("windowType="); pw.print(windowType);
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200307 pw.print(" hidden="); pw.print(mHidden);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800308 pw.print(" hasVisible="); pw.println(hasVisible);
Wale Ogunwale10cb5e22015-05-24 12:36:21 -0700309 if (waitingToShow || sendingToBottom) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800310 pw.print(prefix); pw.print("waitingToShow="); pw.print(waitingToShow);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800311 pw.print(" sendingToBottom="); pw.print(sendingToBottom);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800312 }
313 }
314
315 @Override
316 public String toString() {
317 if (stringName == null) {
318 StringBuilder sb = new StringBuilder();
319 sb.append("WindowToken{");
320 sb.append(Integer.toHexString(System.identityHashCode(this)));
Dianne Hackbornef03a7f2012-10-29 18:46:52 -0700321 sb.append(" "); sb.append(token); sb.append('}');
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800322 stringName = sb.toString();
323 }
324 return stringName;
325 }
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700326
327 @Override
328 String getName() {
329 return toString();
330 }
David Stevens9440dc82017-03-16 19:00:20 -0700331
332 boolean okToDisplay() {
333 return mDisplayContent != null && mDisplayContent.okToDisplay();
334 }
335
336 boolean okToAnimate() {
337 return mDisplayContent != null && mDisplayContent.okToAnimate();
338 }
Robert Carr683e05d2018-04-18 15:11:04 -0700339
340 /**
341 * Return whether windows from this token can layer above the
342 * system bars, or in other words extend outside of the "Decor Frame"
343 */
344 boolean canLayerAboveSystemBars() {
345 int layer = mService.mPolicy.getWindowLayerFromTypeLw(windowType,
346 mOwnerCanManageAppTokens);
347 int navLayer = mService.mPolicy.getWindowLayerFromTypeLw(TYPE_NAVIGATION_BAR,
348 mOwnerCanManageAppTokens);
349 return mOwnerCanManageAppTokens && (layer > navLayer);
350 }
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800351}