blob: 768f89eff774cefd19929f4bb28487c913b97677 [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
Charles Chen4bff5be2020-03-11 10:17:19 +080019import static android.os.Process.INVALID_UID;
Andrii Kulian02c0e4d2020-01-27 22:17:31 -080020import static android.view.Display.INVALID_DISPLAY;
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -070021import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
Riddle Hsud490c572020-04-17 01:39:27 +080022import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
Adrian Roosefa40702020-01-08 17:58:45 +010023import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
Robert Carr683e05d2018-04-18 15:11:04 -070024import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
Louis Chang7501e332018-08-20 13:08:39 +080025
Adrian Roosb125e0b2019-10-02 14:55:14 +020026import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
27import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS;
28import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_WINDOW_MOVEMENT;
Andrii Kulian02c0e4d2020-01-27 22:17:31 -080029import static com.android.server.wm.ProtoLogGroup.WM_ERROR;
lumark9bca6b42019-10-17 18:35:22 +080030import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
31import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
32import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
Vishnu Nairdddc9f52020-03-09 09:37:27 -070033import static com.android.server.wm.WindowContainerChildProto.WINDOW_TOKEN;
Wale Ogunwalee4da0c12016-07-29 12:47:02 -070034import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
35import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
36import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070037import static com.android.server.wm.WindowTokenProto.HASH_CODE;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070038import static com.android.server.wm.WindowTokenProto.PAUSED;
39import static com.android.server.wm.WindowTokenProto.WAITING_TO_SHOW;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070040import static com.android.server.wm.WindowTokenProto.WINDOW_CONTAINER;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080041
Vishnu Nair04ab4392018-01-10 11:00:06 -080042import android.annotation.CallSuper;
Andrii Kulian02c0e4d2020-01-27 22:17:31 -080043import android.app.IWindowToken;
Riddle Hsud490c572020-04-17 01:39:27 +080044import android.app.servertransaction.FixedRotationAdjustmentsItem;
Riddle Hsu6f548e92020-01-13 13:34:09 +080045import android.content.res.Configuration;
46import android.graphics.Rect;
Jorim Jaggife762342016-10-13 14:33:27 +020047import android.os.Debug;
48import android.os.IBinder;
Andrii Kulian02c0e4d2020-01-27 22:17:31 -080049import android.os.RemoteException;
Charles Chen4bff5be2020-03-11 10:17:19 +080050import android.util.Slog;
Vishnu Nair04ab4392018-01-10 11:00:06 -080051import android.util.proto.ProtoOutputStream;
Riddle Hsud490c572020-04-17 01:39:27 +080052import android.view.DisplayAdjustments.FixedRotationAdjustments;
Riddle Hsu6f548e92020-01-13 13:34:09 +080053import android.view.DisplayInfo;
54import android.view.InsetsState;
Adrian Roosefa40702020-01-08 17:58:45 +010055import android.view.SurfaceControl;
Vadim Caenb46f9232020-02-14 17:54:39 +010056import android.view.WindowManager;
Jorim Jaggife762342016-10-13 14:33:27 +020057
Charles Chen525e1e72020-03-02 15:40:25 +080058import com.android.internal.annotations.VisibleForTesting;
Adrian Roosefa40702020-01-08 17:58:45 +010059import com.android.server.policy.WindowManagerPolicy;
Adrian Roosb125e0b2019-10-02 14:55:14 +020060import com.android.server.protolog.common.ProtoLog;
61
Jorim Jaggife762342016-10-13 14:33:27 +020062import java.io.PrintWriter;
Riddle Hsu6f548e92020-01-13 13:34:09 +080063import java.util.ArrayList;
Vishnu Nair04ab4392018-01-10 11:00:06 -080064import java.util.Comparator;
Jorim Jaggife762342016-10-13 14:33:27 +020065
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080066/**
Wale Ogunwaled1c37912016-08-16 03:19:39 -070067 * Container of a set of related windows in the window manager. Often this is an AppWindowToken,
68 * which is the handle for an Activity that it uses to display windows. For nested windows, there is
69 * a WindowToken created for the parent window to manage its children.
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080070 */
Wale Ogunwaled90546a2016-09-09 23:28:03 -070071class WindowToken extends WindowContainer<WindowState> {
Wale Ogunwalee4da0c12016-07-29 12:47:02 -070072 private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowToken" : TAG_WM;
73
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080074 // The actual token.
75 final IBinder token;
76
77 // The type of window this token is for, as per WindowManager.LayoutParams.
78 final int windowType;
79
Adrian Roos4bef62e2018-03-21 19:52:09 +010080 /** {@code true} if this holds the rounded corner overlay */
81 final boolean mRoundedCornerOverlay;
82
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080083 // Set if this token was explicitly added by a client, so should
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -080084 // persist (not be removed) when all windows are removed.
85 boolean mPersistOnEmpty;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080086
87 // For printing.
88 String stringName;
89
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080090 // Is key dispatching paused for this token?
91 boolean paused = false;
92
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080093 // Temporary for finding which tokens no longer have visible windows.
94 boolean hasVisible;
95
96 // Set to true when this token is in a pending transaction where it
97 // will be shown.
98 boolean waitingToShow;
99
Wale Ogunwale5cd907d2017-01-26 14:14:08 -0800100 /** The owner has {@link android.Manifest.permission#MANAGE_APP_TOKENS} */
101 final boolean mOwnerCanManageAppTokens;
102
Riddle Hsu6f548e92020-01-13 13:34:09 +0800103 private FixedRotationTransformState mFixedRotationTransformState;
104
Andrii Kulian02c0e4d2020-01-27 22:17:31 -0800105 private Configuration mLastReportedConfig;
106 private int mLastReportedDisplay = INVALID_DISPLAY;
107
wilsonshih07cb2722020-03-16 23:19:24 +0800108 /**
109 * When set to {@code true}, this window token is created from {@link android.app.WindowContext}
110 */
Charles Chen525e1e72020-03-02 15:40:25 +0800111 @VisibleForTesting
112 final boolean mFromClientToken;
Andrii Kulian02c0e4d2020-01-27 22:17:31 -0800113
Charles Chen4bff5be2020-03-11 10:17:19 +0800114 private DeathRecipient mDeathRecipient;
115 private boolean mBinderDied = false;
116
117 private final int mOwnerUid;
118
Riddle Hsu6f548e92020-01-13 13:34:09 +0800119 /**
120 * Used to fix the transform of the token to be rotated to a rotation different than it's
121 * display. The window frames and surfaces corresponding to this token will be layouted and
122 * rotated by the given rotated display info, frames and insets.
123 */
124 private static class FixedRotationTransformState {
125 final DisplayInfo mDisplayInfo;
126 final DisplayFrames mDisplayFrames;
127 final InsetsState mInsetsState;
128 final Configuration mRotatedOverrideConfiguration;
129 final SeamlessRotator mRotator;
Riddle Hsu6393ad12020-03-02 23:56:32 +0800130 /**
131 * The tokens that share the same transform. Their end time of transform are the same as
132 * {@link #mOwner}.
133 */
134 final ArrayList<WindowToken> mAssociatedTokens = new ArrayList<>(1);
135 final ArrayList<WindowContainer<?>> mRotatedContainers = new ArrayList<>(3);
Riddle Hsu6f548e92020-01-13 13:34:09 +0800136 boolean mIsTransforming = true;
137
Riddle Hsud4957432020-04-24 22:06:29 +0800138 FixedRotationTransformState(DisplayInfo rotatedDisplayInfo,
Riddle Hsu6f548e92020-01-13 13:34:09 +0800139 DisplayFrames rotatedDisplayFrames, InsetsState rotatedInsetsState,
140 Configuration rotatedConfig, int currentRotation) {
141 mDisplayInfo = rotatedDisplayInfo;
142 mDisplayFrames = rotatedDisplayFrames;
143 mInsetsState = rotatedInsetsState;
144 mRotatedOverrideConfiguration = rotatedConfig;
145 // This will use unrotate as rotate, so the new and old rotation are inverted.
146 mRotator = new SeamlessRotator(rotatedDisplayInfo.rotation, currentRotation,
Vishnu Naireb53e522020-05-08 18:03:12 -0700147 rotatedDisplayInfo, true /* applyFixedTransformationHint */);
Riddle Hsu6f548e92020-01-13 13:34:09 +0800148 }
149
150 /**
151 * Transforms the window container from the next rotation to the current rotation for
152 * showing the window in a display with different rotation.
153 */
154 void transform(WindowContainer<?> container) {
155 mRotator.unrotate(container.getPendingTransaction(), container);
156 if (!mRotatedContainers.contains(container)) {
157 mRotatedContainers.add(container);
158 }
159 }
160
161 /**
162 * Resets the transformation of the window containers which have been rotated. This should
163 * be called when the window has the same rotation as display.
164 */
165 void resetTransform() {
166 for (int i = mRotatedContainers.size() - 1; i >= 0; i--) {
167 final WindowContainer<?> c = mRotatedContainers.get(i);
Riddle Hsuf41034c2020-03-19 13:10:46 +0800168 // If the window is detached (no parent), its surface may have been released.
169 if (c.getParent() != null) {
170 mRotator.finish(c.getPendingTransaction(), c);
171 }
Riddle Hsu6f548e92020-01-13 13:34:09 +0800172 }
173 }
174 }
175
Charles Chen4bff5be2020-03-11 10:17:19 +0800176 private class DeathRecipient implements IBinder.DeathRecipient {
177 private boolean mHasUnlinkToDeath = false;
178
179 @Override
180 public void binderDied() {
181 synchronized (mWmService.mGlobalLock) {
182 mBinderDied = true;
183 removeImmediately();
184 }
185 }
186
187 void linkToDeath() throws RemoteException {
188 token.linkToDeath(DeathRecipient.this, 0);
189 }
190
191 void unlinkToDeath() {
192 if (mHasUnlinkToDeath) {
193 return;
194 }
195 token.unlinkToDeath(DeathRecipient.this, 0);
196 mHasUnlinkToDeath = true;
197 }
198 }
199
Wale Ogunwale07bcab72016-10-14 15:30:09 -0700200 /**
201 * Compares two child window of this token and returns -1 if the first is lesser than the
202 * second in terms of z-order and 1 otherwise.
203 */
204 private final Comparator<WindowState> mWindowComparator =
205 (WindowState newWindow, WindowState existingWindow) -> {
206 final WindowToken token = WindowToken.this;
207 if (newWindow.mToken != token) {
208 throw new IllegalArgumentException("newWindow=" + newWindow
209 + " is not a child of token=" + token);
210 }
211
212 if (existingWindow.mToken != token) {
213 throw new IllegalArgumentException("existingWindow=" + existingWindow
214 + " is not a child of token=" + token);
215 }
216
217 return isFirstChildWindowGreaterThanSecond(newWindow, existingWindow) ? 1 : -1;
218 };
219
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800220 WindowToken(WindowManagerService service, IBinder _token, int type, boolean persistOnEmpty,
Wale Ogunwale5cd907d2017-01-26 14:14:08 -0800221 DisplayContent dc, boolean ownerCanManageAppTokens) {
Adrian Roos4bef62e2018-03-21 19:52:09 +0100222 this(service, _token, type, persistOnEmpty, dc, ownerCanManageAppTokens,
Charles Chen525e1e72020-03-02 15:40:25 +0800223 false /* roundedCornerOverlay */);
Adrian Roos4bef62e2018-03-21 19:52:09 +0100224 }
225
226 WindowToken(WindowManagerService service, IBinder _token, int type, boolean persistOnEmpty,
Charles Chen525e1e72020-03-02 15:40:25 +0800227 DisplayContent dc, boolean ownerCanManageAppTokens, boolean roundedCornerOverlay) {
Charles Chen4bff5be2020-03-11 10:17:19 +0800228 this(service, _token, type, persistOnEmpty, dc, ownerCanManageAppTokens, INVALID_UID,
Charles Chen525e1e72020-03-02 15:40:25 +0800229 roundedCornerOverlay, false /* fromClientToken */);
Andrii Kulian02c0e4d2020-01-27 22:17:31 -0800230 }
231
232 WindowToken(WindowManagerService service, IBinder _token, int type, boolean persistOnEmpty,
Charles Chen4bff5be2020-03-11 10:17:19 +0800233 DisplayContent dc, boolean ownerCanManageAppTokens, int ownerUid,
234 boolean roundedCornerOverlay, boolean fromClientToken) {
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100235 super(service);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800236 token = _token;
237 windowType = type;
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800238 mPersistOnEmpty = persistOnEmpty;
Wale Ogunwale5cd907d2017-01-26 14:14:08 -0800239 mOwnerCanManageAppTokens = ownerCanManageAppTokens;
Charles Chen4bff5be2020-03-11 10:17:19 +0800240 mOwnerUid = ownerUid;
Adrian Roos4bef62e2018-03-21 19:52:09 +0100241 mRoundedCornerOverlay = roundedCornerOverlay;
Andrii Kulian02c0e4d2020-01-27 22:17:31 -0800242 mFromClientToken = fromClientToken;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800243 if (dc != null) {
lumarkbde15132019-12-18 22:29:43 +0800244 dc.addWindowToken(token, this);
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800245 }
Charles Chen4bff5be2020-03-11 10:17:19 +0800246 if (shouldReportToClient()) {
247 try {
248 mDeathRecipient = new DeathRecipient();
249 mDeathRecipient.linkToDeath();
250 } catch (RemoteException e) {
251 Slog.e(TAG, "Unable to add window token with type " + windowType + " on "
252 + "display " + dc.getDisplayId(), e);
253 mDeathRecipient = null;
254 return;
255 }
256 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800257 }
258
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800259 void removeAllWindowsIfPossible() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700260 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700261 final WindowState win = mChildren.get(i);
Adrian Roosb125e0b2019-10-02 14:55:14 +0200262 ProtoLog.w(WM_DEBUG_WINDOW_MOVEMENT,
263 "removeAllWindowsIfPossible: removing win=%s", win);
Wale Ogunwale92fc3722016-08-05 12:19:08 -0700264 win.removeIfPossible();
Svetoslav3a5c7212014-10-14 09:54:26 -0700265 }
266 }
267
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700268 void setExiting() {
Charles Chen4bff5be2020-03-11 10:17:19 +0800269 if (isEmpty()) {
chaviwaec55ff52017-12-04 18:39:34 -0800270 super.removeImmediately();
271 return;
272 }
273
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800274 // This token is exiting, so allow it to be removed when it no longer contains any windows.
275 mPersistOnEmpty = false;
276
Issei Suzukif2f6c912019-11-08 11:24:18 +0100277 if (!isVisible()) {
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700278 return;
279 }
280
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700281 final int count = mChildren.size();
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700282 boolean changed = false;
lumark9bca6b42019-10-17 18:35:22 +0800283 final boolean delayed = isAnimating(TRANSITION | PARENTS | CHILDREN);
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700284
285 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700286 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700287 changed |= win.onSetAppExiting();
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700288 }
289
Issei Suzukif2f6c912019-11-08 11:24:18 +0100290 final ActivityRecord app = asActivityRecord();
291 if (app != null) {
292 app.setVisible(false);
293 }
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700294
295 if (changed) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800296 mWmService.mWindowPlacerLocked.performSurfacePlacement();
297 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /*updateInputWindows*/);
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700298 }
299
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700300 if (delayed) {
301 mDisplayContent.mExitingTokens.add(this);
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700302 }
303 }
304
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700305 /**
Riddle Hsub398da32019-01-21 21:48:16 +0800306 * @return The scale for applications running in compatibility mode. Multiply the size in the
307 * application by this scale will be the size in the screen.
308 */
309 float getSizeCompatScale() {
310 return mDisplayContent.mCompatibleScreenScale;
311 }
312
313 /**
Wale Ogunwale07bcab72016-10-14 15:30:09 -0700314 * Returns true if the new window is considered greater than the existing window in terms of
315 * z-order.
316 */
317 protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
318 WindowState existingWindow) {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700319 // New window is considered greater if it has a higher or equal base layer.
320 return newWindow.mBaseLayer >= existingWindow.mBaseLayer;
Wale Ogunwale07bcab72016-10-14 15:30:09 -0700321 }
322
Wale Ogunwale92fc3722016-08-05 12:19:08 -0700323 void addWindow(final WindowState win) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200324 ProtoLog.d(WM_DEBUG_FOCUS,
325 "addWindow: win=%s Callers=%s", win, Debug.getCallers(5));
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700326
Wale Ogunwale6213caa2016-12-02 16:47:15 +0000327 if (win.isChildWindow()) {
328 // Child windows are added to their parent windows.
Wale Ogunwaleb9a07c32016-10-12 14:55:56 -0700329 return;
330 }
wilsonshih07cb2722020-03-16 23:19:24 +0800331 // This token is created from WindowContext and the client requests to addView now, create a
332 // surface for this token.
333 if (mSurfaceControl == null) {
334 createSurfaceControl(true /* force */);
335 }
Wale Ogunwaleb9a07c32016-10-12 14:55:56 -0700336 if (!mChildren.contains(win)) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200337 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "Adding %s to %s", win, this);
Wale Ogunwale6213caa2016-12-02 16:47:15 +0000338 addChild(win, mWindowComparator);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800339 mWmService.mWindowsChanged = true;
Wale Ogunwale6213caa2016-12-02 16:47:15 +0000340 // TODO: Should we also be setting layout needed here and other places?
Wale Ogunwaleb9a07c32016-10-12 14:55:56 -0700341 }
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700342 }
343
wilsonshih07cb2722020-03-16 23:19:24 +0800344 @Override
345 void createSurfaceControl(boolean force) {
346 if (!mFromClientToken || force) {
347 super.createSurfaceControl(force);
348 }
349 }
350
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700351 /** Returns true if the token windows list is empty. */
352 boolean isEmpty() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700353 return mChildren.isEmpty();
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700354 }
355
356 WindowState getReplacingWindow() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700357 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700358 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700359 final WindowState replacing = win.getReplacingWindow();
360 if (replacing != null) {
361 return replacing;
Wale Ogunwalee4da0c12016-07-29 12:47:02 -0700362 }
363 }
364 return null;
365 }
366
Wale Ogunwale0c4a40ef2016-10-07 07:06:40 -0700367 /** Return true if this token has a window that wants the wallpaper displayed behind it. */
368 boolean windowsCanBeWallpaperTarget() {
369 for (int j = mChildren.size() - 1; j >= 0; j--) {
370 final WindowState w = mChildren.get(j);
371 if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
372 return true;
373 }
374 }
375
376 return false;
377 }
378
Wale Ogunwale02319a62016-09-26 15:21:22 -0700379 @Override
380 void removeImmediately() {
Wale Ogunwale02319a62016-09-26 15:21:22 -0700381 if (mDisplayContent != null) {
382 mDisplayContent.removeWindowToken(token);
Wale Ogunwale02319a62016-09-26 15:21:22 -0700383 }
Wale Ogunwalecfca2582016-10-19 09:53:25 -0700384 // Needs to occur after the token is removed from the display above to avoid attempt at
385 // duplicate removal of this window container from it's parent.
386 super.removeImmediately();
Charles Chen4bff5be2020-03-11 10:17:19 +0800387
388 reportWindowTokenRemovedToClient();
389 }
390
391 private void reportWindowTokenRemovedToClient() {
392 if (!shouldReportToClient()) {
393 return;
394 }
395 mDeathRecipient.unlinkToDeath();
396 IWindowToken windowTokenClient = IWindowToken.Stub.asInterface(token);
397 try {
398 windowTokenClient.onWindowTokenRemoved();
399 } catch (RemoteException e) {
400 ProtoLog.w(WM_ERROR, "Could not report token removal to the window token client.");
401 }
Wale Ogunwale02319a62016-09-26 15:21:22 -0700402 }
403
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800404 @Override
Wale Ogunwale02319a62016-09-26 15:21:22 -0700405 void onDisplayChanged(DisplayContent dc) {
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800406 dc.reParentWindowToken(this);
Robert Carrda61ba92017-03-29 15:52:23 -0700407
408 // TODO(b/36740756): One day this should perhaps be hooked
409 // up with goodToGo, so we don't move a window
410 // to another display before the window behind
411 // it is ready.
Wale Ogunwale02319a62016-09-26 15:21:22 -0700412 super.onDisplayChanged(dc);
Andrii Kulian02c0e4d2020-01-27 22:17:31 -0800413 reportConfigToWindowTokenClient();
414 }
415
416 @Override
417 public void onConfigurationChanged(Configuration newParentConfig) {
418 super.onConfigurationChanged(newParentConfig);
419 reportConfigToWindowTokenClient();
420 }
421
422 void reportConfigToWindowTokenClient() {
Charles Chen4bff5be2020-03-11 10:17:19 +0800423 if (!shouldReportToClient()) {
Andrii Kulian02c0e4d2020-01-27 22:17:31 -0800424 return;
425 }
Charles Chen7ba8e262020-03-27 16:42:29 +0800426 if (mLastReportedConfig == null) {
427 mLastReportedConfig = new Configuration();
428 }
Andrii Kulian02c0e4d2020-01-27 22:17:31 -0800429 final Configuration config = getConfiguration();
430 final int displayId = getDisplayContent().getDisplayId();
Charles Chen7ba8e262020-03-27 16:42:29 +0800431 if (config.diff(mLastReportedConfig) == 0 && displayId == mLastReportedDisplay) {
Andrii Kulian02c0e4d2020-01-27 22:17:31 -0800432 // No changes since last reported time.
433 return;
434 }
435
Charles Chen7ba8e262020-03-27 16:42:29 +0800436 mLastReportedConfig.setTo(config);
Andrii Kulian02c0e4d2020-01-27 22:17:31 -0800437 mLastReportedDisplay = displayId;
438
439 IWindowToken windowTokenClient = IWindowToken.Stub.asInterface(token);
Charles Chen4bff5be2020-03-11 10:17:19 +0800440 try {
441 windowTokenClient.onConfigurationChanged(config, displayId);
442 } catch (RemoteException e) {
443 ProtoLog.w(WM_ERROR,
444 "Could not report config changes to the window token client.");
Andrii Kulian02c0e4d2020-01-27 22:17:31 -0800445 }
Wale Ogunwale02319a62016-09-26 15:21:22 -0700446 }
447
Charles Chen4bff5be2020-03-11 10:17:19 +0800448 /**
449 * @return {@code true} if this {@link WindowToken} is not an {@link ActivityRecord} and
450 * registered from client side.
451 */
452 private boolean shouldReportToClient() {
453 // Only report to client for WindowToken because Activities are updated through ATM
454 // callbacks.
455 return asActivityRecord() == null
456 // Report to {@link android.view.WindowTokenClient} if this token was registered from it.
457 && mFromClientToken && !mBinderDied;
458 }
459
Adrian Roosefa40702020-01-08 17:58:45 +0100460 @Override
461 void assignLayer(SurfaceControl.Transaction t, int layer) {
462 if (windowType == TYPE_DOCK_DIVIDER) {
463 // See {@link DisplayContent#mSplitScreenDividerAnchor}
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700464 super.assignRelativeLayer(t,
465 mDisplayContent.getDefaultTaskDisplayArea().getSplitScreenDividerAnchor(), 1);
Adrian Roosefa40702020-01-08 17:58:45 +0100466 } else if (mRoundedCornerOverlay) {
467 super.assignLayer(t, WindowManagerPolicy.COLOR_FADE_LAYER + 1);
468 } else {
469 super.assignLayer(t, layer);
470 }
471 }
472
473 @Override
474 SurfaceControl.Builder makeSurface() {
475 final SurfaceControl.Builder builder = super.makeSurface();
476 if (mRoundedCornerOverlay) {
477 builder.setParent(null);
478 }
479 return builder;
480 }
481
Riddle Hsu6f548e92020-01-13 13:34:09 +0800482 boolean hasFixedRotationTransform() {
483 return mFixedRotationTransformState != null;
484 }
485
Riddle Hsud4957432020-04-24 22:06:29 +0800486 /** Returns {@code true} if the given token shares the same transform. */
487 boolean hasFixedRotationTransform(WindowToken token) {
488 if (mFixedRotationTransformState == null || token == null) {
489 return false;
490 }
491 return this == token || mFixedRotationTransformState == token.mFixedRotationTransformState;
492 }
493
Riddle Hsu6f548e92020-01-13 13:34:09 +0800494 boolean isFinishingFixedRotationTransform() {
495 return mFixedRotationTransformState != null
496 && !mFixedRotationTransformState.mIsTransforming;
497 }
498
499 boolean isFixedRotationTransforming() {
500 return mFixedRotationTransformState != null
501 && mFixedRotationTransformState.mIsTransforming;
502 }
503
504 DisplayInfo getFixedRotationTransformDisplayInfo() {
505 return isFixedRotationTransforming() ? mFixedRotationTransformState.mDisplayInfo : null;
506 }
507
508 DisplayFrames getFixedRotationTransformDisplayFrames() {
509 return isFixedRotationTransforming() ? mFixedRotationTransformState.mDisplayFrames : null;
510 }
511
512 Rect getFixedRotationTransformDisplayBounds() {
513 return isFixedRotationTransforming()
514 ? mFixedRotationTransformState.mRotatedOverrideConfiguration.windowConfiguration
515 .getBounds()
516 : null;
517 }
518
519 InsetsState getFixedRotationTransformInsetsState() {
520 return isFixedRotationTransforming() ? mFixedRotationTransformState.mInsetsState : null;
521 }
522
523 /** Applies the rotated layout environment to this token in the simulated rotated display. */
524 void applyFixedRotationTransform(DisplayInfo info, DisplayFrames displayFrames,
525 Configuration config) {
526 if (mFixedRotationTransformState != null) {
527 return;
528 }
529 final InsetsState insetsState = new InsetsState();
530 mDisplayContent.getDisplayPolicy().simulateLayoutDisplay(displayFrames, insetsState,
531 mDisplayContent.getConfiguration().uiMode);
Riddle Hsud4957432020-04-24 22:06:29 +0800532 mFixedRotationTransformState = new FixedRotationTransformState(info, displayFrames,
Riddle Hsu6f548e92020-01-13 13:34:09 +0800533 insetsState, new Configuration(config), mDisplayContent.getRotation());
534 onConfigurationChanged(getParent().getConfiguration());
Riddle Hsud490c572020-04-17 01:39:27 +0800535 notifyFixedRotationTransform(true /* enabled */);
Riddle Hsu6f548e92020-01-13 13:34:09 +0800536 }
537
Vadim Caen2a9ccc92020-01-29 12:21:41 +0100538 /**
Riddle Hsu6393ad12020-03-02 23:56:32 +0800539 * Reuses the {@link FixedRotationTransformState} (if any) from the other WindowToken to this
Riddle Hsud4957432020-04-24 22:06:29 +0800540 * one. This takes the same effect as {@link #applyFixedRotationTransform}.
Vadim Caen2a9ccc92020-01-29 12:21:41 +0100541 */
Riddle Hsu6393ad12020-03-02 23:56:32 +0800542 void linkFixedRotationTransform(WindowToken other) {
543 if (mFixedRotationTransformState != null) {
Riddle Hsu6f548e92020-01-13 13:34:09 +0800544 return;
545 }
Riddle Hsu6393ad12020-03-02 23:56:32 +0800546 final FixedRotationTransformState fixedRotationState = other.mFixedRotationTransformState;
547 if (fixedRotationState == null) {
548 return;
549 }
550 mFixedRotationTransformState = fixedRotationState;
551 fixedRotationState.mAssociatedTokens.add(this);
552 onConfigurationChanged(getParent().getConfiguration());
Riddle Hsud490c572020-04-17 01:39:27 +0800553 notifyFixedRotationTransform(true /* enabled */);
Riddle Hsu6393ad12020-03-02 23:56:32 +0800554 }
555
Riddle Hsu06aeb062020-03-24 23:38:40 +0800556 void finishFixedRotationTransform() {
Riddle Hsud4957432020-04-24 22:06:29 +0800557 finishFixedRotationTransform(null /* applyDisplayRotation */);
Riddle Hsu06aeb062020-03-24 23:38:40 +0800558 }
559
560 /**
Riddle Hsud4957432020-04-24 22:06:29 +0800561 * Finishes the transform and apply display rotation if the action is given. If the display will
Riddle Hsu522029a2020-04-10 21:21:24 +0800562 * not rotate, the transformed containers are restored to their original states.
Riddle Hsu06aeb062020-03-24 23:38:40 +0800563 */
Riddle Hsud4957432020-04-24 22:06:29 +0800564 void finishFixedRotationTransform(Runnable applyDisplayRotation) {
Riddle Hsu06aeb062020-03-24 23:38:40 +0800565 final FixedRotationTransformState state = mFixedRotationTransformState;
566 if (state == null) {
567 return;
568 }
569
570 state.resetTransform();
571 // Clear the flag so if the display will be updated to the same orientation, the transform
572 // won't take effect.
573 state.mIsTransforming = false;
574 if (applyDisplayRotation != null) {
575 applyDisplayRotation.run();
Riddle Hsu522029a2020-04-10 21:21:24 +0800576 } else {
577 // The display will not rotate to the rotation of this container, let's cancel them.
578 for (int i = state.mAssociatedTokens.size() - 1; i >= 0; i--) {
579 state.mAssociatedTokens.get(i).cancelFixedRotationTransform();
580 }
581 cancelFixedRotationTransform();
Riddle Hsu06aeb062020-03-24 23:38:40 +0800582 }
583 // The state is cleared at the end, because it is used to indicate that other windows can
584 // use seamless rotation when applying rotation to display.
Riddle Hsu6393ad12020-03-02 23:56:32 +0800585 for (int i = state.mAssociatedTokens.size() - 1; i >= 0; i--) {
Riddle Hsud490c572020-04-17 01:39:27 +0800586 state.mAssociatedTokens.get(i).cleanUpFixedRotationTransformState();
Riddle Hsu6393ad12020-03-02 23:56:32 +0800587 }
Riddle Hsud490c572020-04-17 01:39:27 +0800588 cleanUpFixedRotationTransformState();
589 }
590
591 private void cleanUpFixedRotationTransformState() {
Riddle Hsu6f548e92020-01-13 13:34:09 +0800592 mFixedRotationTransformState = null;
Riddle Hsud490c572020-04-17 01:39:27 +0800593 notifyFixedRotationTransform(false /* enabled */);
594 }
595
596 /** Notifies application side to enable or disable the rotation adjustment of display info. */
597 private void notifyFixedRotationTransform(boolean enabled) {
598 FixedRotationAdjustments adjustments = null;
599 // A token may contain windows of the same processes or different processes. The list is
600 // used to avoid sending the same adjustments to a process multiple times.
601 ArrayList<WindowProcessController> notifiedProcesses = null;
602 for (int i = mChildren.size() - 1; i >= 0; i--) {
603 final WindowState w = mChildren.get(i);
604 final WindowProcessController app;
605 if (w.mAttrs.type == TYPE_APPLICATION_STARTING) {
606 // Use the host activity because starting window is controlled by window manager.
607 final ActivityRecord r = asActivityRecord();
608 if (r == null) {
609 continue;
610 }
611 app = r.app;
612 } else {
613 app = mWmService.mAtmService.mProcessMap.getProcess(w.mSession.mPid);
614 }
615 if (app == null || !app.hasThread()) {
616 continue;
617 }
618 if (notifiedProcesses == null) {
619 notifiedProcesses = new ArrayList<>(2);
620 adjustments = enabled ? createFixedRotationAdjustmentsIfNeeded() : null;
621 } else if (notifiedProcesses.contains(app)) {
622 continue;
623 }
624 notifiedProcesses.add(app);
625 try {
626 mWmService.mAtmService.getLifecycleManager().scheduleTransaction(
627 app.getThread(), FixedRotationAdjustmentsItem.obtain(token, adjustments));
628 } catch (RemoteException e) {
629 Slog.w(TAG, "Failed to schedule DisplayAdjustmentsItem to " + app, e);
630 }
631 }
Riddle Hsu6f548e92020-01-13 13:34:09 +0800632 }
633
Riddle Hsu522029a2020-04-10 21:21:24 +0800634 /** Restores the changes that applies to this container. */
635 private void cancelFixedRotationTransform() {
636 final WindowContainer<?> parent = getParent();
637 if (parent == null) {
638 // The window may be detached or detaching.
639 return;
640 }
Riddle Hsud490c572020-04-17 01:39:27 +0800641 notifyFixedRotationTransform(false /* enabled */);
Riddle Hsud16620e2020-04-06 20:48:06 +0800642 final int originalRotation = getWindowConfiguration().getRotation();
Riddle Hsu522029a2020-04-10 21:21:24 +0800643 onConfigurationChanged(parent.getConfiguration());
Riddle Hsud16620e2020-04-06 20:48:06 +0800644 onCancelFixedRotationTransform(originalRotation);
645 }
646
647 /**
648 * It is called when the window is using fixed rotation transform, and before display applies
649 * the same rotation, the rotation change for display is canceled, e.g. the orientation from
650 * sensor is updated to previous direction.
651 */
652 void onCancelFixedRotationTransform(int originalDisplayRotation) {
Riddle Hsu522029a2020-04-10 21:21:24 +0800653 }
654
Riddle Hsud490c572020-04-17 01:39:27 +0800655 FixedRotationAdjustments createFixedRotationAdjustmentsIfNeeded() {
656 if (!isFixedRotationTransforming()) {
657 return null;
658 }
659 return new FixedRotationAdjustments(mFixedRotationTransformState.mDisplayInfo.rotation,
660 mFixedRotationTransformState.mDisplayInfo.displayCutout);
661 }
662
Riddle Hsu6f548e92020-01-13 13:34:09 +0800663 @Override
664 void resolveOverrideConfiguration(Configuration newParentConfig) {
665 super.resolveOverrideConfiguration(newParentConfig);
666 if (isFixedRotationTransforming()) {
667 // Apply the rotated configuration to current resolved configuration, so the merged
668 // override configuration can update to the same state.
669 getResolvedOverrideConfiguration().updateFrom(
670 mFixedRotationTransformState.mRotatedOverrideConfiguration);
671 }
672 }
673
674 @Override
Evan Rosky0ad8d2c2020-03-16 12:09:58 -0700675 void updateSurfacePosition(SurfaceControl.Transaction t) {
676 super.updateSurfacePosition(t);
Riddle Hsu6f548e92020-01-13 13:34:09 +0800677 if (isFixedRotationTransforming()) {
678 // The window is layouted in a simulated rotated display but the real display hasn't
679 // rotated, so here transforms its surface to fit in the real display.
680 mFixedRotationTransformState.transform(this);
681 }
682 }
683
Riddle Hsu3d0aa4f2020-04-09 17:58:50 +0800684 @Override
685 void resetSurfacePositionForAnimationLeash(SurfaceControl.Transaction t) {
686 // Keep the transformed position to animate because the surface will show in different
687 // rotation than the animator of leash.
688 if (!isFixedRotationTransforming()) {
689 super.resetSurfacePositionForAnimationLeash(t);
690 }
691 }
692
Riddle Hsu6f548e92020-01-13 13:34:09 +0800693 /**
Vadim Caenb46f9232020-02-14 17:54:39 +0100694 * Gives a chance to this {@link WindowToken} to adjust the {@link
695 * android.view.WindowManager.LayoutParams} of its windows.
696 */
697 void adjustWindowParams(WindowState win, WindowManager.LayoutParams attrs) {
698 }
699
700
Wale Ogunwale0d5609b2017-09-13 05:55:07 -0700701 @CallSuper
702 @Override
Jeffrey Huangcb782852019-12-05 11:28:11 -0800703 public void dumpDebug(ProtoOutputStream proto, long fieldId,
Nataniel Borges023ecb52019-01-16 14:15:43 -0800704 @WindowTraceLogLevel int logLevel) {
705 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
706 return;
707 }
708
Steven Timotiusaf03df62017-07-18 16:56:43 -0700709 final long token = proto.start(fieldId);
Jeffrey Huangcb782852019-12-05 11:28:11 -0800710 super.dumpDebug(proto, WINDOW_CONTAINER, logLevel);
Steven Timotiusaf03df62017-07-18 16:56:43 -0700711 proto.write(HASH_CODE, System.identityHashCode(this));
Vishnu Nair04ab4392018-01-10 11:00:06 -0800712 proto.write(WAITING_TO_SHOW, waitingToShow);
713 proto.write(PAUSED, paused);
Steven Timotiusaf03df62017-07-18 16:56:43 -0700714 proto.end(token);
715 }
716
Vishnu Nairdddc9f52020-03-09 09:37:27 -0700717 @Override
718 long getProtoFieldId() {
719 return WINDOW_TOKEN;
720 }
721
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200722 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
723 super.dump(pw, prefix, dumpAll);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700724 pw.print(prefix); pw.print("windows="); pw.println(mChildren);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800725 pw.print(prefix); pw.print("windowType="); pw.print(windowType);
Riddle Hsud8bdc452019-12-06 21:36:32 +0800726 pw.print(" hasVisible="); pw.print(hasVisible);
Wale Ogunwale7a8889a2019-11-16 08:23:42 -0800727 if (waitingToShow) {
Riddle Hsud8bdc452019-12-06 21:36:32 +0800728 pw.print(" waitingToShow=true");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800729 }
Riddle Hsud8bdc452019-12-06 21:36:32 +0800730 pw.println();
Riddle Hsu70a920c2020-05-05 17:20:32 +0800731 if (hasFixedRotationTransform()) {
732 pw.print(prefix);
733 pw.print("fixedRotationConfig=");
734 pw.println(mFixedRotationTransformState.mRotatedOverrideConfiguration);
735 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800736 }
737
738 @Override
739 public String toString() {
740 if (stringName == null) {
741 StringBuilder sb = new StringBuilder();
742 sb.append("WindowToken{");
743 sb.append(Integer.toHexString(System.identityHashCode(this)));
Dianne Hackbornef03a7f2012-10-29 18:46:52 -0700744 sb.append(" "); sb.append(token); sb.append('}');
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800745 stringName = sb.toString();
746 }
747 return stringName;
748 }
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700749
750 @Override
751 String getName() {
752 return toString();
753 }
David Stevens9440dc82017-03-16 19:00:20 -0700754
Robert Carr683e05d2018-04-18 15:11:04 -0700755 /**
756 * Return whether windows from this token can layer above the
757 * system bars, or in other words extend outside of the "Decor Frame"
758 */
759 boolean canLayerAboveSystemBars() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800760 int layer = mWmService.mPolicy.getWindowLayerFromTypeLw(windowType,
Robert Carr683e05d2018-04-18 15:11:04 -0700761 mOwnerCanManageAppTokens);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800762 int navLayer = mWmService.mPolicy.getWindowLayerFromTypeLw(TYPE_NAVIGATION_BAR,
Robert Carr683e05d2018-04-18 15:11:04 -0700763 mOwnerCanManageAppTokens);
764 return mOwnerCanManageAppTokens && (layer > navLayer);
765 }
Adrian Roosefa40702020-01-08 17:58:45 +0100766
767 int getWindowLayerFromType() {
768 return mWmService.mPolicy.getWindowLayerFromTypeLw(windowType, mOwnerCanManageAppTokens);
769 }
Charles Chen4bff5be2020-03-11 10:17:19 +0800770
771 int getOwnerUid() {
772 return mOwnerUid;
773 }
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800774}