blob: f1a9e60d18aa577085008dc36dbb1a1163a5420e [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
Evan Rosky2289ba12018-11-19 18:28:18 -080019import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
Winson Chunge55c0192017-08-24 14:50:48 -070020import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
Jorim Jaggic6976f02018-04-18 16:31:07 +020021import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
Winson Chunge55c0192017-08-24 14:50:48 -070022import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
Jorim Jaggiaf0d6d22018-06-08 15:25:35 +020023import static android.content.pm.ActivityInfo.COLOR_MODE_DEFAULT;
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -070024import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
Wale Ogunwale51362492016-09-08 17:49:17 -070025import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
Jorim Jaggif5f9e122017-10-24 18:21:09 +020026import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
Jorim Jaggife762342016-10-13 14:33:27 +020027import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
Jorim Jaggid635a4a2017-05-03 15:21:26 +020028import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080029import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
Jorim Jaggife762342016-10-13 14:33:27 +020030import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
Wale Ogunwaled1c37912016-08-16 03:19:39 -070031import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080032import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -070033import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080034import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
Evan Rosky2289ba12018-11-19 18:28:18 -080035import static android.view.WindowManager.TRANSIT_TASK_CHANGE_WINDOWING_MODE;
chaviw9c81e632018-07-31 11:17:52 -070036import static android.view.WindowManager.TRANSIT_UNSET;
Jorim Jaggic6976f02018-04-18 16:31:07 +020037import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
chaviw9c81e632018-07-31 11:17:52 -070038
Adrian Roose99bc052017-11-20 17:55:31 +010039import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
40import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070041import static com.android.server.wm.AppWindowTokenProto.ALL_DRAWN;
42import static com.android.server.wm.AppWindowTokenProto.APP_STOPPED;
43import static com.android.server.wm.AppWindowTokenProto.CLIENT_HIDDEN;
44import static com.android.server.wm.AppWindowTokenProto.DEFER_HIDING_CLIENT;
45import static com.android.server.wm.AppWindowTokenProto.FILLS_PARENT;
46import static com.android.server.wm.AppWindowTokenProto.FROZEN_BOUNDS;
47import static com.android.server.wm.AppWindowTokenProto.HIDDEN_REQUESTED;
48import static com.android.server.wm.AppWindowTokenProto.HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW;
49import static com.android.server.wm.AppWindowTokenProto.IS_REALLY_ANIMATING;
50import static com.android.server.wm.AppWindowTokenProto.IS_WAITING_FOR_TRANSITION_START;
51import static com.android.server.wm.AppWindowTokenProto.LAST_ALL_DRAWN;
52import static com.android.server.wm.AppWindowTokenProto.LAST_SURFACE_SHOWING;
53import static com.android.server.wm.AppWindowTokenProto.NAME;
54import static com.android.server.wm.AppWindowTokenProto.NUM_DRAWN_WINDOWS;
55import static com.android.server.wm.AppWindowTokenProto.NUM_INTERESTING_WINDOWS;
56import static com.android.server.wm.AppWindowTokenProto.REMOVED;
57import static com.android.server.wm.AppWindowTokenProto.REPORTED_DRAWN;
58import static com.android.server.wm.AppWindowTokenProto.REPORTED_VISIBLE;
59import static com.android.server.wm.AppWindowTokenProto.STARTING_DISPLAYED;
60import static com.android.server.wm.AppWindowTokenProto.STARTING_MOVED;
61import static com.android.server.wm.AppWindowTokenProto.STARTING_WINDOW;
62import static com.android.server.wm.AppWindowTokenProto.THUMBNAIL;
63import static com.android.server.wm.AppWindowTokenProto.WINDOW_TOKEN;
chaviw9c81e632018-07-31 11:17:52 -070064import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
65import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
66import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
67import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
68import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
69import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
70import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
71import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
72import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
73import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
74import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
75import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
76import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
77import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN;
78import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
79import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
80import static com.android.server.wm.WindowManagerService.logWithStack;
chaviw15ad49f2019-04-24 15:05:39 -070081import static com.android.server.wm.WindowState.LEGACY_POLICY_VISIBILITY;
Jorim Jaggi6ec52d42019-07-03 15:45:59 +020082import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
Vishnu Naira2977262018-07-26 13:31:26 -070083import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
Evan Rosky641daea2019-04-24 14:45:24 -070084import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080085
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070086import android.annotation.CallSuper;
chaviwdcf76ec2019-01-11 16:48:46 -080087import android.annotation.Size;
Jorim Jaggid635a4a2017-05-03 15:21:26 +020088import android.app.Activity;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080089import android.app.ActivityManager;
Winson Chung48b25652018-10-22 14:04:30 -070090import android.content.ComponentName;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080091import android.content.res.CompatibilityInfo;
Jorim Jaggi26c8c422016-05-09 19:57:25 -070092import android.content.res.Configuration;
Jorim Jaggi988f6682017-11-17 17:46:43 +010093import android.graphics.GraphicBuffer;
Jorim Jaggif5f9e122017-10-24 18:21:09 +020094import android.graphics.Point;
Jorim Jaggi0429f352015-12-22 16:29:16 +010095import android.graphics.Rect;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -070096import android.os.Binder;
Tiger Huang51c5a1d2018-12-11 20:24:51 +080097import android.os.Build;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -080098import android.os.Debug;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -070099import android.os.IBinder;
Steven Timotiusaf03df62017-07-18 16:56:43 -0700100import android.os.RemoteException;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800101import android.os.SystemClock;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200102import android.os.Trace;
Evan Rosky2289ba12018-11-19 18:28:18 -0800103import android.util.ArraySet;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800104import android.util.Slog;
Steven Timotiusaf03df62017-07-18 16:56:43 -0700105import android.util.proto.ProtoOutputStream;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200106import android.view.DisplayInfo;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800107import android.view.IApplicationToken;
Robert Carr788f5742018-07-30 17:46:45 -0700108import android.view.InputApplicationHandle;
Evan Rosky966759f2019-01-15 10:33:58 -0800109import android.view.RemoteAnimationAdapter;
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100110import android.view.RemoteAnimationDefinition;
Robert Carr6914f082017-03-20 19:04:30 -0700111import android.view.SurfaceControl;
Tony Mak64b8d562017-12-28 17:44:02 +0000112import android.view.SurfaceControl.Transaction;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800113import android.view.WindowManager;
Jorim Jaggi87fdbcb2017-08-17 13:41:11 +0200114import android.view.WindowManager.LayoutParams;
Tony Mak64b8d562017-12-28 17:44:02 +0000115import android.view.animation.Animation;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800116
Tony Mak64b8d562017-12-28 17:44:02 +0000117import com.android.internal.R;
Riddle Hsua118b3a2018-10-11 22:05:06 +0800118import com.android.internal.annotations.VisibleForTesting;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800119import com.android.internal.util.ToBooleanFunction;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800120import com.android.server.AttributeCache;
chaviwdcf76ec2019-01-11 16:48:46 -0800121import com.android.server.LocalServices;
Christine Franks0ada2772019-02-25 13:54:57 -0800122import com.android.server.display.color.ColorDisplayService;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800123import com.android.server.policy.WindowManagerPolicy;
Adrian Roose99bc052017-11-20 17:55:31 +0100124import com.android.server.policy.WindowManagerPolicy.StartingSurface;
Evan Rosky2289ba12018-11-19 18:28:18 -0800125import com.android.server.wm.RemoteAnimationController.RemoteAnimationRecord;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800126import com.android.server.wm.WindowManagerService.H;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800127
128import java.io.PrintWriter;
chaviwdcf76ec2019-01-11 16:48:46 -0800129import java.lang.ref.WeakReference;
Jorim Jaggi0429f352015-12-22 16:29:16 +0100130import java.util.ArrayDeque;
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800131import java.util.ArrayList;
lumark588a3e82018-07-20 18:53:54 +0800132import java.util.function.Consumer;
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800133
134class AppTokenList extends ArrayList<AppWindowToken> {
135}
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800136
137/**
138 * Version of WindowToken that is specifically for a particular application (or
139 * really activity) that is displaying windows.
140 */
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800141class AppWindowToken extends WindowToken implements WindowManagerService.AppFreezeListener,
142 ConfigurationContainerListener {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800143 private static final String TAG = TAG_WITH_CLASS_NAME ? "AppWindowToken" : TAG_WM;
144
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100145 /**
146 * Value to increment the z-layer when boosting a layer during animations. BOOST in l33tsp34k.
147 */
Jorim Jaggi9cd99132019-04-24 17:41:35 +0200148 @VisibleForTesting static final int Z_BOOST_BASE = 800570000;
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100149
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800150 // Non-null only for application tokens.
151 final IApplicationToken appToken;
Winson Chung48b25652018-10-22 14:04:30 -0700152 final ComponentName mActivityComponent;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800153 final boolean mVoiceInteraction;
Dianne Hackborne30e02f2014-05-27 18:24:45 -0700154
Wale Ogunwale51362492016-09-08 17:49:17 -0700155 /** @see WindowContainer#fillsParent() */
156 private boolean mFillsParent;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800157 boolean mShowForAllUsers;
158 int mTargetSdk;
Craig Mautnera2c77052012-03-26 12:14:43 -0700159
Bryce Lee6d410262017-02-28 15:30:17 -0800160 // Flag set while reparenting to prevent actions normally triggered by an individual parent
161 // change.
162 private boolean mReparenting;
163
Wale Ogunwalee287e192017-04-21 09:30:12 -0700164 // True if we are current in the process of removing this app token from the display
165 private boolean mRemovingFromDisplay = false;
166
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800167 // The input dispatching timeout for this application token in nanoseconds.
Wale Ogunwale72919d22016-12-08 18:58:50 -0800168 long mInputDispatchingTimeoutNanos;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800169
170 // These are used for determining when all windows associated with
171 // an activity have been drawn, so they can be made visible together
172 // at the same time.
Craig Mautner764983d2012-03-22 11:37:36 -0700173 // initialize so that it doesn't match mTransactionSequence which is an int.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700174 private long mLastTransactionSequence = Long.MIN_VALUE;
175 private int mNumInterestingWindows;
176 private int mNumDrawnWindows;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800177 boolean inPendingTransaction;
178 boolean allDrawn;
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000179 private boolean mLastAllDrawn;
Tiger Huangc9d0d002019-05-29 22:55:29 +0800180 private boolean mUseTransferredAnimation;
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000181
Craig Mautner7636dfb2012-11-16 15:24:11 -0800182 // Set to true when this app creates a surface while in the middle of an animation. In that
183 // case do not clear allDrawn until the animation completes.
184 boolean deferClearAllDrawn;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800185
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800186 // Is this window's surface needed? This is almost like hidden, except
187 // it will sometimes be true a little earlier: when the token has
188 // been shown, but is still waiting for its app transition to execute
189 // before making its windows shown.
190 boolean hiddenRequested;
191
192 // Have we told the window clients to hide themselves?
Wale Ogunwale89973222017-04-23 18:39:45 -0700193 private boolean mClientHidden;
194
195 // If true we will defer setting mClientHidden to true and reporting to the client that it is
196 // hidden.
197 boolean mDeferHidingClient;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800198
199 // Last visibility state we reported to the app token.
200 boolean reportedVisible;
201
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700202 // Last drawn state we reported to the app token.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700203 private boolean reportedDrawn;
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700204
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800205 // Set to true when the token has been removed from the window mgr.
206 boolean removed;
207
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800208 // Information about an application starting window if displayed.
Tarandeep Singh69ab1042019-07-30 13:30:03 -0700209 // Note: these are de-referenced before the starting window animates away.
chaviwa8f07a72019-05-01 16:25:39 -0700210 StartingData mStartingData;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800211 WindowState startingWindow;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800212 StartingSurface startingSurface;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800213 boolean startingDisplayed;
214 boolean startingMoved;
Jorim Jaggi60f9c972018-02-01 19:21:07 +0100215
Wale Ogunwale6c459212017-05-17 08:56:03 -0700216 // True if the hidden state of this token was forced to false due to a transferred starting
217 // window.
218 private boolean mHiddenSetFromTransferredStartingWindow;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800219 boolean firstWindowDrawn;
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700220 private final WindowState.UpdateReportedVisibilityResults mReportedVisibilityResults =
221 new WindowState.UpdateReportedVisibilityResults();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800222
223 // Input application handle used by the input dispatcher.
Jeff Brown9302c872011-07-13 22:51:29 -0700224 final InputApplicationHandle mInputApplicationHandle;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800225
Wale Ogunwale571771c2016-08-26 13:18:50 -0700226 // TODO: Have a WindowContainer state for tracking exiting/deferred removal.
Craig Mautner799bc1d2015-01-14 10:33:48 -0800227 boolean mIsExiting;
Craig Mautner9ef471f2014-02-07 13:11:47 -0800228
Craig Mautnerbb742462014-07-07 15:28:55 -0700229 boolean mLaunchTaskBehind;
Craig Mautner8746a472014-07-24 15:12:54 -0700230 boolean mEnteringAnimation;
Craig Mautnerbb742462014-07-07 15:28:55 -0700231
Wale Ogunwale72919d22016-12-08 18:58:50 -0800232 private boolean mAlwaysFocusable;
Wale Ogunwale6cae7652015-12-26 07:36:26 -0800233
Robert Carre12aece2016-02-02 22:43:27 -0800234 boolean mAppStopped;
Robert Carrfd10cd12016-06-29 16:41:50 -0700235 int mRotationAnimationHint;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700236 private int mPendingRelaunchCount;
Robert Carre12aece2016-02-02 22:43:27 -0800237
Jorim Jaggife762342016-10-13 14:33:27 +0200238 private boolean mLastContainsShowWhenLockedWindow;
239 private boolean mLastContainsDismissKeyguardWindow;
240
Jorim Jaggi0429f352015-12-22 16:29:16 +0100241 ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
Jorim Jaggi26c8c422016-05-09 19:57:25 -0700242 ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
Jorim Jaggi0429f352015-12-22 16:29:16 +0100243
Riddle Hsub398da32019-01-21 21:48:16 +0800244 /**
245 * The scale to fit at least one side of the activity to its parent. If the activity uses
246 * 1920x1080, and the actually size on the screen is 960x540, then the scale is 0.5.
247 */
248 private float mSizeCompatScale = 1f;
249 /**
250 * The bounds in global coordinates for activity in size compatibility mode.
251 * @see ActivityRecord#inSizeCompatMode
252 */
253 private Rect mSizeCompatBounds;
254
Wale Ogunwale6c459212017-05-17 08:56:03 -0700255 private boolean mDisablePreviewScreenshots;
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +0100256
Wale Ogunwale034a8ec2017-09-02 17:14:40 -0700257 private Task mLastParent;
Robert Carred3e83b2017-04-21 13:26:55 -0700258
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800259 // TODO: Remove after unification
260 ActivityRecord mActivityRecord;
261
chaviwd3bf08d2017-08-01 17:24:59 -0700262 /**
263 * See {@link #canTurnScreenOn()}
264 */
265 private boolean mCanTurnScreenOn = true;
266
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200267 /**
268 * If we are running an animation, this determines the transition type. Must be one of
269 * AppTransition.TRANSIT_* constants.
270 */
271 private int mTransit;
272
273 /**
274 * If we are running an animation, this determines the flags during this animation. Must be a
275 * bitwise combination of AppTransition.TRANSIT_FLAG_* constants.
276 */
277 private int mTransitFlags;
278
279 /** Whether our surface was set to be showing in the last call to {@link #prepareSurfaces} */
Jorim Jaggifd1891462017-12-29 15:41:36 +0100280 private boolean mLastSurfaceShowing = true;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200281
Evan Rosky2289ba12018-11-19 18:28:18 -0800282 /**
283 * This gets used during some open/close transitions as well as during a change transition
284 * where it represents the starting-state snapshot.
285 */
Jorim Jaggi988f6682017-11-17 17:46:43 +0100286 private AppWindowThumbnail mThumbnail;
Evan Rosky2289ba12018-11-19 18:28:18 -0800287 private final Rect mTransitStartRect = new Rect();
288
289 /**
290 * This leash is used to "freeze" the app surface in place after the state change, but before
291 * the animation is ready to start.
292 */
293 private SurfaceControl mTransitChangeLeash = null;
Jorim Jaggi988f6682017-11-17 17:46:43 +0100294
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000295 /** Have we been asked to have this token keep the screen frozen? */
296 private boolean mFreezingScreen;
297
298 /** Whether this token should be boosted at the top of all app window tokens. */
Jorim Jaggi9cd99132019-04-24 17:41:35 +0200299 @VisibleForTesting boolean mNeedsZBoost;
Adrian Roos4d18a2e2017-12-19 19:08:05 +0100300 private Letterbox mLetterbox;
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000301
chaviw23ee71c2017-12-18 11:29:41 -0800302 private final Point mTmpPoint = new Point();
chaviw23012112017-12-20 15:29:04 -0800303 private final Rect mTmpRect = new Rect();
Evan Rosky2289ba12018-11-19 18:28:18 -0800304 private final Rect mTmpPrevBounds = new Rect();
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100305 private RemoteAnimationDefinition mRemoteAnimationDefinition;
Jorim Jaggi6de61012018-03-19 14:53:23 +0100306 private AnimatingAppWindowTokenRegistry mAnimatingAppWindowTokenRegistry;
chaviw23ee71c2017-12-18 11:29:41 -0800307
chaviw4ad54912018-05-30 11:05:44 -0700308 /**
309 * A flag to determine if this AWT is in the process of closing or entering PIP. This is needed
310 * to help AWT know that the app is in the process of closing but hasn't yet started closing on
311 * the WM side.
312 */
313 private boolean mWillCloseOrEnterPip;
314
Vishnu Naira2977262018-07-26 13:31:26 -0700315 /** Layer used to constrain the animation to a token's stack bounds. */
316 SurfaceControl mAnimationBoundsLayer;
317
318 /** Whether this token needs to create mAnimationBoundsLayer for cropping animations. */
319 boolean mNeedsAnimationBoundsLayer;
320
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800321 private static final int STARTING_WINDOW_TYPE_NONE = 0;
322 private static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
323 private static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
324
chaviwdcf76ec2019-01-11 16:48:46 -0800325 private AppSaturationInfo mLastAppSaturationInfo;
326
327 private final ColorDisplayService.ColorTransformController mColorTransformController =
328 (matrix, translation) -> mWmService.mH.post(() -> {
329 synchronized (mWmService.mGlobalLock) {
330 if (mLastAppSaturationInfo == null) {
331 mLastAppSaturationInfo = new AppSaturationInfo();
332 }
333
334 mLastAppSaturationInfo.setSaturation(matrix, translation);
335 updateColorTransform();
336 }
337 });
338
Winson Chung48b25652018-10-22 14:04:30 -0700339 AppWindowToken(WindowManagerService service, IApplicationToken token,
340 ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
341 long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers,
Jorim Jaggi91d382a2019-03-27 17:00:48 +0100342 int targetSdk, int orientation, int rotationAnimationHint,
Winson Chung48b25652018-10-22 14:04:30 -0700343 boolean launchTaskBehind, boolean alwaysFocusable,
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800344 ActivityRecord activityRecord) {
Winson Chung48b25652018-10-22 14:04:30 -0700345 this(service, token, activityComponent, voiceInteraction, dc, fullscreen);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800346 // TODO: remove after unification
347 mActivityRecord = activityRecord;
348 mActivityRecord.registerConfigurationChangeListener(this);
Wale Ogunwale72919d22016-12-08 18:58:50 -0800349 mInputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800350 mShowForAllUsers = showForAllUsers;
351 mTargetSdk = targetSdk;
352 mOrientation = orientation;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800353 mLaunchTaskBehind = launchTaskBehind;
354 mAlwaysFocusable = alwaysFocusable;
355 mRotationAnimationHint = rotationAnimationHint;
356
357 // Application tokens start out hidden.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200358 setHidden(true);
Wale Ogunwale72919d22016-12-08 18:58:50 -0800359 hiddenRequested = true;
chaviwdcf76ec2019-01-11 16:48:46 -0800360
361 ColorDisplayService.ColorDisplayServiceInternal cds = LocalServices.getService(
362 ColorDisplayService.ColorDisplayServiceInternal.class);
363 cds.attachColorTransformController(activityRecord.packageName, activityRecord.mUserId,
364 new WeakReference<>(mColorTransformController));
Wale Ogunwale72919d22016-12-08 18:58:50 -0800365 }
366
Winson Chung48b25652018-10-22 14:04:30 -0700367 AppWindowToken(WindowManagerService service, IApplicationToken token,
368 ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
369 boolean fillsParent) {
Wale Ogunwale5cd907d2017-01-26 14:14:08 -0800370 super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true, dc,
371 false /* ownerCanManageAppTokens */);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700372 appToken = token;
Winson Chung48b25652018-10-22 14:04:30 -0700373 mActivityComponent = activityComponent;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800374 mVoiceInteraction = voiceInteraction;
Wale Ogunwale17f175c2017-02-07 16:54:10 -0800375 mFillsParent = fillsParent;
Robert Carr0bcbe642018-10-11 19:07:43 -0700376 mInputApplicationHandle = new InputApplicationHandle(appToken.asBinder());
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800377 }
378
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800379 void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
380 firstWindowDrawn = true;
381
382 // We now have a good window to show, remove dead placeholders
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700383 removeDeadWindows();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800384
Jorim Jaggi02886a82016-12-06 09:10:06 -0800385 if (startingWindow != null) {
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800386 if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Slog.v(TAG, "Finish starting "
387 + win.mToken + ": first real window is shown, no animation");
388 // If this initial window is animating, stop it -- we will do an animation to reveal
389 // it from behind the starting window, so there is no need for it to also be doing its
390 // own stuff.
Jorim Jaggia5e10572017-11-15 14:36:26 +0100391 win.cancelAnimation();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800392 }
chaviwa8f07a72019-05-01 16:25:39 -0700393 removeStartingWindow();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800394 updateReportedVisibilityLocked();
395 }
396
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800397 void updateReportedVisibilityLocked() {
398 if (appToken == null) {
399 return;
400 }
401
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700402 if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700403 final int count = mChildren.size();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800404
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700405 mReportedVisibilityResults.reset();
406
407 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700408 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700409 win.updateReportedVisibility(mReportedVisibilityResults);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800410 }
411
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700412 int numInteresting = mReportedVisibilityResults.numInteresting;
413 int numVisible = mReportedVisibilityResults.numVisible;
414 int numDrawn = mReportedVisibilityResults.numDrawn;
415 boolean nowGone = mReportedVisibilityResults.nowGone;
416
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700417 boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200418 boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting && !isHidden();
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700419 if (!nowGone) {
420 // If the app is not yet gone, then it can only become visible/drawn.
421 if (!nowDrawn) {
422 nowDrawn = reportedDrawn;
423 }
424 if (!nowVisible) {
425 nowVisible = reportedVisible;
426 }
427 }
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800428 if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800429 + numInteresting + " visible=" + numVisible);
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700430 if (nowDrawn != reportedDrawn) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800431 if (mActivityRecord != null) {
432 mActivityRecord.onWindowsDrawn(nowDrawn, SystemClock.uptimeMillis());
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700433 }
434 reportedDrawn = nowDrawn;
435 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800436 if (nowVisible != reportedVisible) {
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700437 if (DEBUG_VISIBILITY) Slog.v(TAG,
438 "Visibility changed in " + this + ": vis=" + nowVisible);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800439 reportedVisible = nowVisible;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800440 if (mActivityRecord != null) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800441 if (nowVisible) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800442 onWindowsVisible();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800443 } else {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800444 onWindowsGone();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800445 }
446 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800447 }
448 }
449
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800450 private void onWindowsGone() {
451 if (mActivityRecord == null) {
452 return;
453 }
454 if (DEBUG_VISIBILITY) {
455 Slog.v(TAG_WM, "Reporting gone in " + mActivityRecord.appToken);
456 }
457 mActivityRecord.onWindowsGone();
458 }
459
460 private void onWindowsVisible() {
461 if (mActivityRecord == null) {
462 return;
463 }
464 if (DEBUG_VISIBILITY) {
465 Slog.v(TAG_WM, "Reporting visible in " + mActivityRecord.appToken);
466 }
467 mActivityRecord.onWindowsVisible();
468 }
469
Wale Ogunwale89973222017-04-23 18:39:45 -0700470 boolean isClientHidden() {
471 return mClientHidden;
472 }
473
474 void setClientHidden(boolean hideClient) {
475 if (mClientHidden == hideClient || (hideClient && mDeferHidingClient)) {
476 return;
477 }
Jorim Jaggi067b5bf2018-02-23 17:42:39 +0100478 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "setClientHidden: " + this
479 + " clientHidden=" + hideClient + " Callers=" + Debug.getCallers(5));
Wale Ogunwale89973222017-04-23 18:39:45 -0700480 mClientHidden = hideClient;
481 sendAppVisibilityToClients();
482 }
483
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800484 void setVisibility(boolean visible, boolean deferHidingClient) {
485 final AppTransition appTransition = getDisplayContent().mAppTransition;
486
487 // Don't set visibility to false if we were already not visible. This prevents WM from
488 // adding the app to the closing app list which doesn't make sense for something that is
489 // already not visible. However, set visibility to true even if we are already visible.
490 // This makes sure the app is added to the opening apps list so that the right
491 // transition can be selected.
492 // TODO: Probably a good idea to separate the concept of opening/closing apps from the
493 // concept of setting visibility...
494 if (!visible && hiddenRequested) {
495
496 if (!deferHidingClient && mDeferHidingClient) {
497 // We previously deferred telling the client to hide itself when visibility was
498 // initially set to false. Now we would like it to hide, so go ahead and set it.
499 mDeferHidingClient = deferHidingClient;
500 setClientHidden(true);
501 }
502 return;
503 }
504
505 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) {
506 Slog.v(TAG_WM, "setAppVisibility("
507 + appToken + ", visible=" + visible + "): " + appTransition
508 + " hidden=" + isHidden() + " hiddenRequested="
509 + hiddenRequested + " Callers=" + Debug.getCallers(6));
510 }
511
512 final DisplayContent displayContent = getDisplayContent();
513 displayContent.mOpeningApps.remove(this);
514 displayContent.mClosingApps.remove(this);
Evan Roskyb1e75f72019-04-26 20:23:26 -0700515 if (isInChangeTransition()) {
516 clearChangeLeash(getPendingTransaction(), true /* cancel */);
517 }
518 displayContent.mChangingApps.remove(this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800519 waitingToShow = false;
520 hiddenRequested = !visible;
521 mDeferHidingClient = deferHidingClient;
522
523 if (!visible) {
524 // If the app is dead while it was visible, we kept its dead window on screen.
525 // Now that the app is going invisible, we can remove it. It will be restarted
526 // if made visible again.
527 removeDeadWindows();
528 } else {
529 if (!appTransition.isTransitionSet()
530 && appTransition.isReady()) {
531 // Add the app mOpeningApps if transition is unset but ready. This means
532 // we're doing a screen freeze, and the unfreeze will wait for all opening
533 // apps to be ready.
534 displayContent.mOpeningApps.add(this);
535 }
536 startingMoved = false;
537 // If the token is currently hidden (should be the common case), or has been
538 // stopped, then we need to set up to wait for its windows to be ready.
539 if (isHidden() || mAppStopped) {
540 clearAllDrawn();
541
542 // If the app was already visible, don't reset the waitingToShow state.
543 if (isHidden()) {
544 waitingToShow = true;
Jorim Jaggi6ec52d42019-07-03 15:45:59 +0200545
546 // Let's reset the draw state in order to prevent the starting window to be
547 // immediately dismissed when the app still has the surface.
548 forAllWindows(w -> {
549 if (w.mWinAnimator.mDrawState == HAS_DRAWN) {
550 w.mWinAnimator.resetDrawState();
551
552 // Force add to mResizingWindows, so that we are guaranteed to get
553 // another reportDrawn callback.
554 w.resetLastContentInsets();
555 }
556 }, true /* traverseTopToBottom */);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800557 }
558 }
559
560 // In the case where we are making an app visible but holding off for a transition,
561 // we still need to tell the client to make its windows visible so they get drawn.
562 // Otherwise, we will wait on performing the transition until all windows have been
563 // drawn, they never will be, and we are sad.
564 setClientHidden(false);
565
566 requestUpdateWallpaperIfNeeded();
567
568 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "No longer Stopped: " + this);
569 mAppStopped = false;
570
571 transferStartingWindowFromHiddenAboveTokenIfNeeded();
572 }
573
574 // If we are preparing an app transition, then delay changing
575 // the visibility of this token until we execute that transition.
576 if (okToAnimate() && appTransition.isTransitionSet()) {
577 inPendingTransaction = true;
578 if (visible) {
579 displayContent.mOpeningApps.add(this);
580 mEnteringAnimation = true;
581 } else {
582 displayContent.mClosingApps.add(this);
583 mEnteringAnimation = false;
584 }
585 if (appTransition.getAppTransition()
586 == WindowManager.TRANSIT_TASK_OPEN_BEHIND) {
587 // We're launchingBehind, add the launching activity to mOpeningApps.
588 final WindowState win = getDisplayContent().findFocusedWindow();
589 if (win != null) {
590 final AppWindowToken focusedToken = win.mAppToken;
591 if (focusedToken != null) {
592 if (DEBUG_APP_TRANSITIONS) {
593 Slog.d(TAG_WM, "TRANSIT_TASK_OPEN_BEHIND, "
594 + " adding " + focusedToken + " to mOpeningApps");
595 }
596 // Force animation to be loaded.
597 focusedToken.setHidden(true);
598 displayContent.mOpeningApps.add(focusedToken);
599 }
600 }
601 }
Garfield Tanb6776602019-02-20 14:44:26 -0800602 // Changes in opening apps and closing apps may cause orientation change.
603 reportDescendantOrientationChangeIfNeeded();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800604 return;
605 }
606
607 commitVisibility(null, visible, TRANSIT_UNSET, true, mVoiceInteraction);
608 updateReportedVisibilityLocked();
609 }
610
611 boolean commitVisibility(WindowManager.LayoutParams lp,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700612 boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
613
614 boolean delayed = false;
615 inPendingTransaction = false;
Wale Ogunwale9e4721f2017-05-23 19:37:30 -0700616 // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually
617 // been set by the app now.
618 mHiddenSetFromTransferredStartingWindow = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700619
620 // Allow for state changes and animation to be applied if:
621 // * token is transitioning visibility state
622 // * or the token was marked as hidden and is exiting before we had a chance to play the
623 // transition animation
624 // * or this is an opening app and windows are being replaced.
625 boolean visibilityChanged = false;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200626 if (isHidden() == visible || (isHidden() && mIsExiting) || (visible && waitingForReplacement())) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800627 final AccessibilityController accessibilityController =
628 mWmService.mAccessibilityController;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700629 boolean changed = false;
630 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM,
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200631 "Changing app " + this + " hidden=" + isHidden() + " performLayout=" + performLayout);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700632
633 boolean runningAppAnimation = false;
634
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100635 if (transit != WindowManager.TRANSIT_UNSET) {
Tiger Huangc9d0d002019-05-29 22:55:29 +0800636 if (mUseTransferredAnimation) {
637 runningAppAnimation = isReallyAnimating();
638 } else if (applyAnimationLocked(lp, transit, visible, isVoiceInteraction)) {
639 runningAppAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700640 }
Tiger Huangc9d0d002019-05-29 22:55:29 +0800641 delayed = runningAppAnimation;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700642 final WindowState window = findMainWindow();
Rhed Jao02655dc2018-10-30 20:44:52 +0800643 if (window != null && accessibilityController != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700644 accessibilityController.onAppWindowTransitionLocked(window, transit);
645 }
646 changed = true;
647 }
648
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700649 final int windowsCount = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700650 for (int i = 0; i < windowsCount; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700651 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700652 changed |= win.onAppVisibilityChanged(visible, runningAppAnimation);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700653 }
654
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200655 setHidden(!visible);
656 hiddenRequested = !visible;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700657 visibilityChanged = true;
658 if (!visible) {
659 stopFreezingScreen(true, true);
660 } else {
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700661 // If we are being set visible, and the starting window is not yet displayed,
662 // then make sure it doesn't get displayed.
663 if (startingWindow != null && !startingWindow.isDrawnLw()) {
chaviw15ad49f2019-04-24 15:05:39 -0700664 startingWindow.clearPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY);
665 startingWindow.mLegacyPolicyVisibilityAfterAnim = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700666 }
Jorim Jaggi38d44ec2017-06-14 16:04:59 -0700667
668 // We are becoming visible, so better freeze the screen with the windows that are
669 // getting visible so we also wait for them.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800670 forAllWindows(mWmService::makeWindowFreezingScreenIfNeededLocked, true);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700671 }
672
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800673 if (DEBUG_APP_TRANSITIONS) {
674 Slog.v(TAG_WM, "commitVisibility: " + this
675 + ": hidden=" + isHidden() + " hiddenRequested=" + hiddenRequested);
676 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700677
678 if (changed) {
Arthur Hung95b38a92018-07-20 18:56:12 +0800679 getDisplayContent().getInputMonitor().setUpdateInputWindowsNeededLw();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700680 if (performLayout) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800681 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700682 false /*updateInputWindows*/);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800683 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700684 }
Arthur Hung95b38a92018-07-20 18:56:12 +0800685 getDisplayContent().getInputMonitor().updateInputWindowsLw(false /*force*/);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700686 }
687 }
Tiger Huangc9d0d002019-05-29 22:55:29 +0800688 mUseTransferredAnimation = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700689
lumarkd14173e2019-03-27 19:14:33 +0800690 if (isReallyAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700691 delayed = true;
Jorim Jaggiab9fcb22018-03-15 23:46:12 +0100692 } else {
693
694 // We aren't animating anything, but exiting windows rely on the animation finished
695 // callback being called in case the AppWindowToken was pretending to be animating,
696 // which we might have done because we were in closing/opening apps list.
697 onAnimationFinished();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700698 }
699
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700700 for (int i = mChildren.size() - 1; i >= 0 && !delayed; i--) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100701 if ((mChildren.get(i)).isSelfOrChildAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700702 delayed = true;
703 }
704 }
705
706 if (visibilityChanged) {
707 if (visible && !delayed) {
708 // The token was made immediately visible, there will be no entrance animation.
709 // We need to inform the client the enter animation was finished.
710 mEnteringAnimation = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800711 mWmService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(
712 token);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700713 }
Robert Carr61b81112017-07-17 18:08:15 -0700714
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800715 // If we're becoming visible, immediately change client visibility as well. there seem
716 // to be some edge cases where we change our visibility but client visibility never gets
717 // updated.
Jorim Jaggi110839b2018-01-22 12:49:04 +0100718 // If we're becoming invisible, update the client visibility if we are not running an
719 // animation. Otherwise, we'll update client visibility in onAnimationFinished.
Jorim Jaggi3cad57f2018-02-20 18:32:01 +0100720 if (visible || !isReallyAnimating()) {
Jorim Jaggi110839b2018-01-22 12:49:04 +0100721 setClientHidden(!visible);
Jorim Jaggi4876b4a2018-01-11 15:43:49 +0100722 }
723
lumark588a3e82018-07-20 18:53:54 +0800724 if (!getDisplayContent().mClosingApps.contains(this)
725 && !getDisplayContent().mOpeningApps.contains(this)) {
chaviwa953fcf2018-03-01 12:00:39 -0800726 // The token is not closing nor opening, so even if there is an animation set, that
727 // doesn't mean that it goes through the normal app transition cycle so we have
728 // to inform the docked controller about visibility change.
729 // TODO(multi-display): notify docked divider on all displays where visibility was
730 // affected.
lumark588a3e82018-07-20 18:53:54 +0800731 getDisplayContent().getDockedDividerController().notifyAppVisibilityChanged();
chaviwa953fcf2018-03-01 12:00:39 -0800732
733 // Take the screenshot before possibly hiding the WSA, otherwise the screenshot
734 // will not be taken.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800735 mWmService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible);
chaviwa953fcf2018-03-01 12:00:39 -0800736 }
737
Robert Carre7cc44d2017-03-20 19:04:30 -0700738 // If we are hidden but there is no delay needed we immediately
739 // apply the Surface transaction so that the ActivityManager
Robert Carr61b81112017-07-17 18:08:15 -0700740 // can have some guarantee on the Surface state following
741 // setting the visibility. This captures cases like dismissing
742 // the docked or pinned stack where there is no app transition.
743 //
744 // In the case of a "Null" animation, there will be
745 // no animation but there will still be a transition set.
746 // We still need to delay hiding the surface such that it
747 // can be synchronized with showing the next surface in the transition.
lumark588a3e82018-07-20 18:53:54 +0800748 if (isHidden() && !delayed && !getDisplayContent().mAppTransition.isTransitionSet()) {
Robert Carr6914f082017-03-20 19:04:30 -0700749 SurfaceControl.openTransaction();
750 for (int i = mChildren.size() - 1; i >= 0; i--) {
751 mChildren.get(i).mWinAnimator.hide("immediately hidden");
752 }
753 SurfaceControl.closeTransaction();
754 }
Garfield Tanb6776602019-02-20 14:44:26 -0800755
756 // Visibility changes may cause orientation request change.
757 reportDescendantOrientationChangeIfNeeded();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700758 }
759
760 return delayed;
761 }
762
Garfield Tanb6776602019-02-20 14:44:26 -0800763 private void reportDescendantOrientationChangeIfNeeded() {
764 // Orientation request is exposed only when we're visible. Therefore visibility change
765 // will change requested orientation. Notify upward the hierarchy ladder to adjust
766 // configuration. This is important to cases where activities with incompatible
767 // orientations launch, or user goes back from an activity of bi-orientation to an
768 // activity with specified orientation.
769 if (mActivityRecord.getRequestedConfigurationOrientation() == getConfiguration().orientation
770 || getOrientationIgnoreVisibility() == SCREEN_ORIENTATION_UNSET) {
771 return;
772 }
773
774 final IBinder freezeToken =
775 mActivityRecord.mayFreezeScreenLocked(mActivityRecord.app)
776 ? mActivityRecord.appToken : null;
777 onDescendantOrientationChanged(freezeToken, mActivityRecord);
778 }
779
Jorim Jaggi87fdbcb2017-08-17 13:41:11 +0200780 /**
781 * @return The to top most child window for which {@link LayoutParams#isFullscreen()} returns
782 * true.
783 */
784 WindowState getTopFullscreenWindow() {
785 for (int i = mChildren.size() - 1; i >= 0; i--) {
786 final WindowState win = mChildren.get(i);
787 if (win != null && win.mAttrs.isFullscreen()) {
788 return win;
789 }
790 }
791 return null;
792 }
793
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800794 WindowState findMainWindow() {
Matthew Ng53e66b22018-01-12 17:13:13 -0800795 return findMainWindow(true);
796 }
797
798 /**
799 * Finds the main window that either has type base application or application starting if
800 * requested.
801 *
802 * @param includeStartingApp Allow to search application-starting windows to also be returned.
803 * @return The main window of type base application or application starting if requested.
804 */
805 WindowState findMainWindow(boolean includeStartingApp) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700806 WindowState candidate = null;
Matthew Ng53e66b22018-01-12 17:13:13 -0800807 for (int j = mChildren.size() - 1; j >= 0; --j) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700808 final WindowState win = mChildren.get(j);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700809 final int type = win.mAttrs.type;
810 // No need to loop through child window as base application and starting types can't be
811 // child windows.
Matthew Ng53e66b22018-01-12 17:13:13 -0800812 if (type == TYPE_BASE_APPLICATION
813 || (includeStartingApp && type == TYPE_APPLICATION_STARTING)) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700814 // In cases where there are multiple windows, we prefer the non-exiting window. This
Sungsoo Lim0d3d1f82015-12-02 14:47:59 +0900815 // happens for example when replacing windows during an activity relaunch. When
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700816 // constructing the animation, we want the new window, not the exiting one.
Wale Ogunwalec48a3542016-02-19 15:18:45 -0800817 if (win.mAnimatingExit) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700818 candidate = win;
819 } else {
820 return win;
821 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800822 }
823 }
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700824 return candidate;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800825 }
826
Wale Ogunwale6cae7652015-12-26 07:36:26 -0800827 boolean windowsAreFocusable() {
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800828 if (mTargetSdk < Build.VERSION_CODES.Q) {
829 final int pid = mActivityRecord != null
830 ? (mActivityRecord.app != null ? mActivityRecord.app.getPid() : 0) : 0;
831 final AppWindowToken topFocusedAppOfMyProcess =
832 mWmService.mRoot.mTopFocusedAppByProcess.get(pid);
833 if (topFocusedAppOfMyProcess != null && topFocusedAppOfMyProcess != this) {
834 // For the apps below Q, there can be only one app which has the focused window per
835 // process, because legacy apps may not be ready for a multi-focus system.
836 return false;
837 }
838 }
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700839 return getWindowConfiguration().canReceiveKeys() || mAlwaysFocusable;
Wale Ogunwaled045c822015-12-02 09:14:28 -0800840 }
841
Wale Ogunwale571771c2016-08-26 13:18:50 -0700842 @Override
Wale Ogunwale44f21802016-09-02 12:49:48 -0700843 boolean isVisible() {
Wale Ogunwalee471be62016-10-03 07:53:55 -0700844 // If the app token isn't hidden then it is considered visible and there is no need to check
845 // its children windows to see if they are visible.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200846 return !isHidden();
Wale Ogunwale44f21802016-09-02 12:49:48 -0700847 }
848
849 @Override
Wale Ogunwalee287e192017-04-21 09:30:12 -0700850 void removeImmediately() {
851 onRemovedFromDisplay();
Yunfan Chen3a77f282018-12-12 15:47:52 -0800852 if (mActivityRecord != null) {
853 mActivityRecord.unregisterConfigurationChangeListener(this);
854 }
Wale Ogunwalee287e192017-04-21 09:30:12 -0700855 super.removeImmediately();
856 }
857
858 @Override
Wale Ogunwale571771c2016-08-26 13:18:50 -0700859 void removeIfPossible() {
Craig Mautnere3119b72015-01-20 15:02:36 -0800860 mIsExiting = false;
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800861 removeAllWindowsIfPossible();
Bryce Lee6d410262017-02-28 15:30:17 -0800862 removeImmediately();
Craig Mautnere3119b72015-01-20 15:02:36 -0800863 }
864
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700865 @Override
866 boolean checkCompleteDeferredRemoval() {
867 if (mIsExiting) {
868 removeIfPossible();
869 }
870 return super.checkCompleteDeferredRemoval();
871 }
872
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700873 void onRemovedFromDisplay() {
Wale Ogunwalee287e192017-04-21 09:30:12 -0700874 if (mRemovingFromDisplay) {
875 return;
876 }
877 mRemovingFromDisplay = true;
878
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700879 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app token: " + this);
880
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800881 boolean delayed = commitVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700882
lumark588a3e82018-07-20 18:53:54 +0800883 getDisplayContent().mOpeningApps.remove(this);
Evan Rosky2289ba12018-11-19 18:28:18 -0800884 getDisplayContent().mChangingApps.remove(this);
lumark588a3e82018-07-20 18:53:54 +0800885 getDisplayContent().mUnknownAppVisibilityController.appRemovedOrHidden(this);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800886 mWmService.mTaskSnapshotController.onAppRemoved(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700887 waitingToShow = false;
lumark588a3e82018-07-20 18:53:54 +0800888 if (getDisplayContent().mClosingApps.contains(this)) {
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700889 delayed = true;
lumark588a3e82018-07-20 18:53:54 +0800890 } else if (getDisplayContent().mAppTransition.isTransitionSet()) {
891 getDisplayContent().mClosingApps.add(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700892 delayed = true;
893 }
894
895 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app " + this + " delayed=" + delayed
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200896 + " animation=" + getAnimation() + " animating=" + isSelfAnimating());
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700897
898 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: "
899 + this + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
900
chaviwa8f07a72019-05-01 16:25:39 -0700901 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800902 removeStartingWindow();
Jorim Jaggi19be6052017-08-03 18:33:43 +0200903 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800904
Winson Chung87e5d552017-04-05 11:49:38 -0700905 // If this window was animating, then we need to ensure that the app transition notifies
lumark588a3e82018-07-20 18:53:54 +0800906 // that animations have completed in DisplayContent.handleAnimatingStoppedAndTransition(),
907 // so add to that list now
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200908 if (isSelfAnimating()) {
lumark588a3e82018-07-20 18:53:54 +0800909 getDisplayContent().mNoAnimationNotifyOnTransitionFinished.add(token);
Winson Chung87e5d552017-04-05 11:49:38 -0700910 }
911
Wale Ogunwalee287e192017-04-21 09:30:12 -0700912 final TaskStack stack = getStack();
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700913 if (delayed && !isEmpty()) {
914 // set the token aside because it has an active animation to be finished
915 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM,
916 "removeAppToken make exiting: " + this);
Wale Ogunwalee287e192017-04-21 09:30:12 -0700917 if (stack != null) {
918 stack.mExitingAppTokens.add(this);
919 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700920 mIsExiting = true;
921 } else {
922 // Make sure there is no animation running on this token, so any windows associated
923 // with it will be removed as soon as their animations are complete
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200924 cancelAnimation();
Wale Ogunwale3106ae012017-05-16 08:56:37 -0700925 if (stack != null) {
926 stack.mExitingAppTokens.remove(this);
927 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700928 removeIfPossible();
929 }
930
931 removed = true;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700932 stopFreezingScreen(true, true);
Bryce Lee6d410262017-02-28 15:30:17 -0800933
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800934 final DisplayContent dc = getDisplayContent();
935 if (dc.mFocusedApp == this) {
936 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + this
937 + " displayId=" + dc.getDisplayId());
938 dc.setFocusedApp(null);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800939 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700940 }
Riddle Hsu192fe762019-01-15 23:41:57 +0800941 if (mLetterbox != null) {
942 mLetterbox.destroy();
943 mLetterbox = null;
944 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700945
946 if (!delayed) {
947 updateReportedVisibilityLocked();
948 }
Wale Ogunwalee287e192017-04-21 09:30:12 -0700949
950 mRemovingFromDisplay = false;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700951 }
952
Chong Zhange05bcb12016-07-26 17:47:29 -0700953 void clearAnimatingFlags() {
Chong Zhangb0d26702016-08-12 16:03:29 -0700954 boolean wallpaperMightChange = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700955 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700956 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700957 wallpaperMightChange |= win.clearAnimatingFlags();
Chong Zhange05bcb12016-07-26 17:47:29 -0700958 }
Chong Zhangb0d26702016-08-12 16:03:29 -0700959 if (wallpaperMightChange) {
960 requestUpdateWallpaperIfNeeded();
961 }
Chong Zhange05bcb12016-07-26 17:47:29 -0700962 }
963
Robert Carre12aece2016-02-02 22:43:27 -0800964 void destroySurfaces() {
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700965 destroySurfaces(false /*cleanupOnResume*/);
966 }
967
968 /**
969 * Destroy surfaces which have been marked as eligible by the animator, taking care to ensure
970 * the client has finished with them.
971 *
972 * @param cleanupOnResume whether this is done when app is resumed without fully stopped. If
973 * set to true, destroy only surfaces of removed windows, and clear relevant flags of the
974 * others so that they are ready to be reused. If set to false (common case), destroy all
975 * surfaces that's eligible, if the app is already stopped.
976 */
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700977 private void destroySurfaces(boolean cleanupOnResume) {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700978 boolean destroyedSomething = false;
Jorim Jaggia5e10572017-11-15 14:36:26 +0100979
980 // Copying to a different list as multiple children can be removed.
Jorim Jaggi59f3e922018-01-05 15:40:32 +0100981 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
Jorim Jaggia5e10572017-11-15 14:36:26 +0100982 for (int i = children.size() - 1; i >= 0; i--) {
983 final WindowState win = children.get(i);
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700984 destroyedSomething |= win.destroySurface(cleanupOnResume, mAppStopped);
Robert Carre12aece2016-02-02 22:43:27 -0800985 }
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700986 if (destroyedSomething) {
987 final DisplayContent dc = getDisplayContent();
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700988 dc.assignWindowLayers(true /*setLayoutNeeded*/);
Adrian Roos23df3a32018-03-15 15:41:13 +0100989 updateLetterboxSurface(null);
Robert Carre12aece2016-02-02 22:43:27 -0800990 }
991 }
992
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800993 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700994 * Notify that the app is now resumed, and it was not stopped before, perform a clean
995 * up of the surfaces
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800996 */
Jorim Jaggibae01b12017-04-11 16:29:10 -0700997 void notifyAppResumed(boolean wasStopped) {
Chong Zhangad24f962016-08-25 12:12:33 -0700998 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppResumed: wasStopped=" + wasStopped
Jorim Jaggibae01b12017-04-11 16:29:10 -0700999 + " " + this);
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001000 mAppStopped = false;
chaviwd3bf08d2017-08-01 17:24:59 -07001001 // Allow the window to turn the screen on once the app is resumed again.
1002 setCanTurnScreenOn(true);
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001003 if (!wasStopped) {
1004 destroySurfaces(true /*cleanupOnResume*/);
Wale Ogunwale8d5a5422016-03-03 18:28:21 -08001005 }
Robert Carre12aece2016-02-02 22:43:27 -08001006 }
1007
Chong Zhangbef461f2015-10-27 11:38:24 -07001008 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001009 * Notify that the app has stopped, and it is okay to destroy any surfaces which were
1010 * keeping alive in case they were still being used.
1011 */
1012 void notifyAppStopped() {
1013 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: " + this);
1014 mAppStopped = true;
1015 destroySurfaces();
1016 // Remove any starting window that was added for this app if they are still around.
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001017 removeStartingWindow();
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001018 }
1019
Chong Zhang92147042016-05-09 12:47:11 -07001020 void clearAllDrawn() {
1021 allDrawn = false;
1022 deferClearAllDrawn = false;
Chong Zhangbef461f2015-10-27 11:38:24 -07001023 }
1024
Bryce Lee6d410262017-02-28 15:30:17 -08001025 Task getTask() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001026 return (Task) getParent();
Bryce Lee6d410262017-02-28 15:30:17 -08001027 }
1028
Jorim Jaggi3878ca32017-02-02 17:13:05 -08001029 TaskStack getStack() {
1030 final Task task = getTask();
1031 if (task != null) {
1032 return task.mStack;
1033 } else {
1034 return null;
1035 }
1036 }
1037
Bryce Lee6d410262017-02-28 15:30:17 -08001038 @Override
Riddle Hsu3a4bb612019-01-31 00:02:22 +08001039 void onParentChanged() {
1040 super.onParentChanged();
Bryce Lee6d410262017-02-28 15:30:17 -08001041
Robert Carred3e83b2017-04-21 13:26:55 -07001042 final Task task = getTask();
1043
Bryce Lee6d410262017-02-28 15:30:17 -08001044 // When the associated task is {@code null}, the {@link AppWindowToken} can no longer
1045 // access visual elements like the {@link DisplayContent}. We must remove any associations
1046 // such as animations.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001047 if (!mReparenting) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001048 if (task == null) {
1049 // It is possible we have been marked as a closing app earlier. We must remove ourselves
1050 // from this list so we do not participate in any future animations.
lumark588a3e82018-07-20 18:53:54 +08001051 getDisplayContent().mClosingApps.remove(this);
Robert Carred3e83b2017-04-21 13:26:55 -07001052 } else if (mLastParent != null && mLastParent.mStack != null) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001053 task.mStack.mExitingAppTokens.remove(this);
1054 }
Bryce Lee6d410262017-02-28 15:30:17 -08001055 }
Jorim Jaggi6de61012018-03-19 14:53:23 +01001056 final TaskStack stack = getStack();
1057
1058 // If we reparent, make sure to remove ourselves from the old animation registry.
1059 if (mAnimatingAppWindowTokenRegistry != null) {
1060 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
1061 }
1062 mAnimatingAppWindowTokenRegistry = stack != null
1063 ? stack.getAnimatingAppWindowTokenRegistry()
1064 : null;
1065
Robert Carred3e83b2017-04-21 13:26:55 -07001066 mLastParent = task;
chaviwdcf76ec2019-01-11 16:48:46 -08001067
1068 updateColorTransform();
Bryce Lee6d410262017-02-28 15:30:17 -08001069 }
1070
Wale Ogunwalefa854eb2016-09-20 13:43:52 -07001071 void postWindowRemoveStartingWindowCleanup(WindowState win) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001072 // TODO: Something smells about the code below...Is there a better way?
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001073 if (startingWindow == win) {
1074 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Notify removed startingWindow " + win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001075 removeStartingWindow();
Wale Ogunwale6c459212017-05-17 08:56:03 -07001076 } else if (mChildren.size() == 0) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001077 // If this is the last window and we had requested a starting transition window,
1078 // well there is no point now.
Jorim Jaggi02886a82016-12-06 09:10:06 -08001079 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Nulling last startingData");
chaviwa8f07a72019-05-01 16:25:39 -07001080 mStartingData = null;
Wale Ogunwale6c459212017-05-17 08:56:03 -07001081 if (mHiddenSetFromTransferredStartingWindow) {
1082 // We set the hidden state to false for the token from a transferred starting window.
1083 // We now reset it back to true since the starting window was the last window in the
1084 // token.
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001085 setHidden(true);
Wale Ogunwale6c459212017-05-17 08:56:03 -07001086 }
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01001087 } else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001088 // If this is the last window except for a starting transition window,
1089 // we need to get rid of the starting transition.
Jorim Jaggie4b0f282017-05-17 15:10:29 +02001090 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Last window, removing starting window "
1091 + win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001092 removeStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001093 }
1094 }
1095
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001096 void removeDeadWindows() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001097 for (int winNdx = mChildren.size() - 1; winNdx >= 0; --winNdx) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001098 WindowState win = mChildren.get(winNdx);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001099 if (win.mAppDied) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001100 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.w(TAG,
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001101 "removeDeadWindows: " + win);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001102 // Set mDestroying, we don't want any animation or delayed removal here.
1103 win.mDestroying = true;
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001104 // Also removes child windows.
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001105 win.removeIfPossible();
Chong Zhang112eb8c2015-11-02 11:17:00 -08001106 }
1107 }
1108 }
1109
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001110 boolean hasWindowsAlive() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001111 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001112 // No need to loop through child windows as the answer should be the same as that of the
1113 // parent window.
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001114 if (!(mChildren.get(i)).mAppDied) {
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001115 return true;
1116 }
1117 }
1118 return false;
1119 }
1120
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001121 void setWillReplaceWindows(boolean animate) {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001122 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
1123 "Marking app token " + this + " with replacing windows.");
Robert Carra1eb4392015-12-10 12:43:51 -08001124
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001125 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001126 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001127 w.setWillReplaceWindow(animate);
Robert Carra1eb4392015-12-10 12:43:51 -08001128 }
Robert Carra1eb4392015-12-10 12:43:51 -08001129 }
1130
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001131 void setWillReplaceChildWindows() {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001132 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Marking app token " + this
Robert Carr23fa16b2016-01-13 13:19:58 -08001133 + " with replacing child windows.");
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001134 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001135 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001136 w.setWillReplaceChildWindows();
Robert Carr23fa16b2016-01-13 13:19:58 -08001137 }
1138 }
1139
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001140 void clearWillReplaceWindows() {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001141 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
1142 "Resetting app token " + this + " of replacing window marks.");
Chong Zhangf596cd52016-01-05 13:42:44 -08001143
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001144 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001145 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001146 w.clearWillReplaceWindow();
Chong Zhangf596cd52016-01-05 13:42:44 -08001147 }
1148 }
1149
Chong Zhang4d7369a2016-04-25 16:09:14 -07001150 void requestUpdateWallpaperIfNeeded() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001151 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001152 final WindowState w = mChildren.get(i);
Chong Zhang4d7369a2016-04-25 16:09:14 -07001153 w.requestUpdateWallpaperIfNeeded();
1154 }
1155 }
1156
Chong Zhangd78ddb42016-03-02 17:01:14 -08001157 boolean isRelaunching() {
1158 return mPendingRelaunchCount > 0;
1159 }
1160
Robert Carr68375192017-06-13 12:41:53 -07001161 boolean shouldFreezeBounds() {
1162 final Task task = getTask();
1163
1164 // For freeform windows, we can't freeze the bounds at the moment because this would make
1165 // the resizing unresponsive.
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001166 if (task == null || task.inFreeformWindowingMode()) {
Robert Carr68375192017-06-13 12:41:53 -07001167 return false;
1168 }
1169
1170 // We freeze the bounds while drag resizing to deal with the time between
1171 // the divider/drag handle being released, and the handling it's new
1172 // configuration. If we are relaunched outside of the drag resizing state,
1173 // we need to be careful not to do this.
1174 return getTask().isDragResizing();
1175 }
1176
Chong Zhangd78ddb42016-03-02 17:01:14 -08001177 void startRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001178 if (shouldFreezeBounds()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08001179 freezeBounds();
1180 }
Robert Carrd5c7dd62017-03-08 10:39:30 -08001181
1182 // In the process of tearing down before relaunching, the app will
1183 // try and clean up it's child surfaces. We need to prevent this from
1184 // happening, so we sever the children, transfering their ownership
1185 // from the client it-self to the parent surface (owned by us).
Robert Carr29daa922018-04-27 11:56:48 -07001186 detachChildren();
1187
1188 mPendingRelaunchCount++;
1189 }
1190
1191 void detachChildren() {
Robert Carrfd8e93b2018-05-10 13:40:25 -07001192 SurfaceControl.openTransaction();
Robert Carrd5c7dd62017-03-08 10:39:30 -08001193 for (int i = mChildren.size() - 1; i >= 0; i--) {
1194 final WindowState w = mChildren.get(i);
1195 w.mWinAnimator.detachChildren();
1196 }
Robert Carrfd8e93b2018-05-10 13:40:25 -07001197 SurfaceControl.closeTransaction();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001198 }
1199
1200 void finishRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001201 unfreezeBounds();
1202
Chong Zhangd78ddb42016-03-02 17:01:14 -08001203 if (mPendingRelaunchCount > 0) {
1204 mPendingRelaunchCount--;
Bryce Lee081554b2017-05-25 07:52:12 -07001205 } else {
1206 // Update keyguard flags upon finishing relaunch.
1207 checkKeyguardFlagsChanged();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001208 }
1209 }
1210
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001211 void clearRelaunching() {
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001212 if (mPendingRelaunchCount == 0) {
1213 return;
1214 }
Robert Carr68375192017-06-13 12:41:53 -07001215 unfreezeBounds();
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001216 mPendingRelaunchCount = 0;
1217 }
1218
Wale Ogunwale07bcab72016-10-14 15:30:09 -07001219 /**
1220 * Returns true if the new child window we are adding to this token is considered greater than
1221 * the existing child window in this token in terms of z-order.
1222 */
1223 @Override
1224 protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
1225 WindowState existingWindow) {
1226 final int type1 = newWindow.mAttrs.type;
1227 final int type2 = existingWindow.mAttrs.type;
1228
1229 // Base application windows should be z-ordered BELOW all other windows in the app token.
1230 if (type1 == TYPE_BASE_APPLICATION && type2 != TYPE_BASE_APPLICATION) {
1231 return false;
1232 } else if (type1 != TYPE_BASE_APPLICATION && type2 == TYPE_BASE_APPLICATION) {
1233 return true;
1234 }
1235
1236 // Starting windows should be z-ordered ABOVE all other windows in the app token.
1237 if (type1 == TYPE_APPLICATION_STARTING && type2 != TYPE_APPLICATION_STARTING) {
1238 return true;
1239 } else if (type1 != TYPE_APPLICATION_STARTING && type2 == TYPE_APPLICATION_STARTING) {
1240 return false;
1241 }
1242
1243 // Otherwise the new window is greater than the existing window.
1244 return true;
1245 }
1246
Tarandeep Singh69ab1042019-07-30 13:30:03 -07001247 /**
1248 * @return {@code true} if starting window is in app's hierarchy.
1249 */
1250 boolean hasStartingWindow() {
1251 if (startingDisplayed || mStartingData != null) {
1252 return true;
1253 }
1254 for (int i = mChildren.size() - 1; i >= 0; i--) {
1255 if (getChildAt(i).mAttrs.type == TYPE_APPLICATION_STARTING) {
1256 return true;
1257 }
1258 }
1259 return false;
1260 }
1261
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001262 @Override
Robert Carra1eb4392015-12-10 12:43:51 -08001263 void addWindow(WindowState w) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001264 super.addWindow(w);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001265
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001266 boolean gotReplacementWindow = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001267 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001268 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001269 gotReplacementWindow |= candidate.setReplacementWindowIfNeeded(w);
1270 }
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001271
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001272 // if we got a replacement window, reset the timeout to give drawing more time
1273 if (gotReplacementWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001274 mWmService.scheduleWindowReplacementTimeouts(this);
Robert Carra1eb4392015-12-10 12:43:51 -08001275 }
Jorim Jaggife762342016-10-13 14:33:27 +02001276 checkKeyguardFlagsChanged();
1277 }
1278
1279 @Override
1280 void removeChild(WindowState child) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001281 if (!mChildren.contains(child)) {
1282 // This can be true when testing.
1283 return;
1284 }
Jorim Jaggife762342016-10-13 14:33:27 +02001285 super.removeChild(child);
1286 checkKeyguardFlagsChanged();
Adrian Roos23df3a32018-03-15 15:41:13 +01001287 updateLetterboxSurface(child);
Robert Carra1eb4392015-12-10 12:43:51 -08001288 }
1289
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001290 private boolean waitingForReplacement() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001291 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001292 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001293 if (candidate.waitingForReplacement()) {
Robert Carra1eb4392015-12-10 12:43:51 -08001294 return true;
1295 }
1296 }
1297 return false;
1298 }
1299
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001300 void onWindowReplacementTimeout() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001301 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001302 (mChildren.get(i)).onWindowReplacementTimeout();
Robert Carra1eb4392015-12-10 12:43:51 -08001303 }
1304 }
1305
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001306 void reparent(Task task, int position) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001307 if (DEBUG_ADD_REMOVE) {
1308 Slog.i(TAG_WM, "reparent: moving app token=" + this
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001309 + " to task=" + task.mTaskId + " at " + position);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001310 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001311 if (task == null) {
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001312 throw new IllegalArgumentException("reparent: could not find task");
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001313 }
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001314 final Task currentTask = getTask();
1315 if (task == currentTask) {
Winson Chung30480042017-01-26 10:55:34 -08001316 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001317 "window token=" + this + " already child of task=" + currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001318 }
Bryce Lee6d410262017-02-28 15:30:17 -08001319
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001320 if (currentTask.mStack != task.mStack) {
Bryce Lee6d410262017-02-28 15:30:17 -08001321 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001322 "window token=" + this + " current task=" + currentTask
Bryce Lee6d410262017-02-28 15:30:17 -08001323 + " belongs to a different stack than " + task);
1324 }
1325
Winson Chung30480042017-01-26 10:55:34 -08001326 if (DEBUG_ADD_REMOVE) Slog.i(TAG, "reParentWindowToken: removing window token=" + this
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001327 + " from task=" + currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001328 final DisplayContent prevDisplayContent = getDisplayContent();
1329
Bryce Lee6d410262017-02-28 15:30:17 -08001330 mReparenting = true;
1331
Winson Chung30480042017-01-26 10:55:34 -08001332 getParent().removeChild(this);
1333 task.addChild(this, position);
1334
Bryce Lee6d410262017-02-28 15:30:17 -08001335 mReparenting = false;
1336
Winson Chung30480042017-01-26 10:55:34 -08001337 // Relayout display(s).
1338 final DisplayContent displayContent = task.getDisplayContent();
1339 displayContent.setLayoutNeeded();
1340 if (prevDisplayContent != displayContent) {
1341 onDisplayChanged(displayContent);
1342 prevDisplayContent.setLayoutNeeded();
1343 }
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001344 getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
Winson Chung30480042017-01-26 10:55:34 -08001345 }
1346
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001347 @Override
1348 void onDisplayChanged(DisplayContent dc) {
1349 DisplayContent prevDc = mDisplayContent;
1350 super.onDisplayChanged(dc);
Evan Roskyb1e75f72019-04-26 20:23:26 -07001351 if (prevDc == null || prevDc == mDisplayContent) {
Evan Rosky25b56192019-02-06 16:10:56 -08001352 return;
1353 }
Wale Ogunwaleb8e6b632019-06-28 15:19:25 +00001354
1355 if (prevDc.mOpeningApps.remove(this)) {
1356 // Transfer opening transition to new display.
1357 mDisplayContent.mOpeningApps.add(this);
1358 mDisplayContent.prepareAppTransition(prevDc.mAppTransition.getAppTransition(), true);
1359 mDisplayContent.executeAppTransition();
1360 }
1361
1362 if (prevDc.mChangingApps.remove(this)) {
Evan Rosky25b56192019-02-06 16:10:56 -08001363 // This gets called *after* the AppWindowToken has been reparented to the new display.
1364 // That reparenting resulted in this window changing modes (eg. FREEFORM -> FULLSCREEN),
1365 // so this token is now "frozen" while waiting for the animation to start on prevDc
1366 // (which will be cancelled since the window is no-longer a child). However, since this
1367 // is no longer a child of prevDc, this won't be notified of the cancelled animation,
1368 // so we need to cancel the change transition here.
1369 clearChangeLeash(getPendingTransaction(), true /* cancel */);
1370 }
Wale Ogunwaleb8e6b632019-06-28 15:19:25 +00001371 prevDc.mClosingApps.remove(this);
1372
Evan Rosky25b56192019-02-06 16:10:56 -08001373 if (prevDc.mFocusedApp == this) {
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001374 prevDc.setFocusedApp(null);
lumarkbf844642018-11-23 17:11:36 +08001375 final TaskStack stack = dc.getTopStack();
1376 if (stack != null) {
1377 final Task task = stack.getTopChild();
1378 if (task != null && task.getTopChild() == this) {
1379 dc.setFocusedApp(this);
1380 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001381 }
1382 }
Riddle Hsu192fe762019-01-15 23:41:57 +08001383
Evan Roskyb1e75f72019-04-26 20:23:26 -07001384 if (mLetterbox != null) {
Riddle Hsu192fe762019-01-15 23:41:57 +08001385 mLetterbox.onMovedToDisplay(mDisplayContent.getDisplayId());
1386 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001387 }
1388
Jorim Jaggi0429f352015-12-22 16:29:16 +01001389 /**
1390 * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds
1391 * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even
1392 * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen
1393 * with a queue.
1394 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001395 private void freezeBounds() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001396 final Task task = getTask();
1397 mFrozenBounds.offer(new Rect(task.mPreparedFrozenBounds));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001398
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001399 if (task.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001400 // We didn't call prepareFreezingBounds on the task, so use the current value.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001401 mFrozenMergedConfig.offer(new Configuration(task.getConfiguration()));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001402 } else {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001403 mFrozenMergedConfig.offer(new Configuration(task.mPreparedFrozenMergedConfig));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001404 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001405 // Calling unset() to make it equal to Configuration.EMPTY.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001406 task.mPreparedFrozenMergedConfig.unset();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001407 }
1408
1409 /**
1410 * Unfreezes the previously frozen bounds. See {@link #freezeBounds}.
1411 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001412 private void unfreezeBounds() {
Robert Carr68375192017-06-13 12:41:53 -07001413 if (mFrozenBounds.isEmpty()) {
1414 return;
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001415 }
Robert Carr68375192017-06-13 12:41:53 -07001416 mFrozenBounds.remove();
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001417 if (!mFrozenMergedConfig.isEmpty()) {
1418 mFrozenMergedConfig.remove();
1419 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001420 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001421 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001422 win.onUnfreezeBounds();
Jorim Jaggi4846ee32016-01-07 17:39:12 +01001423 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001424 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001425 }
1426
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001427 void setAppLayoutChanges(int changes, String reason) {
1428 if (!mChildren.isEmpty()) {
1429 final DisplayContent dc = getDisplayContent();
1430 dc.pendingLayoutChanges |= changes;
1431 if (DEBUG_LAYOUT_REPEATS) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001432 mWmService.mWindowPlacerLocked.debugLayoutRepeats(reason, dc.pendingLayoutChanges);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001433 }
1434 }
1435 }
1436
1437 void removeReplacedWindowIfNeeded(WindowState replacement) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001438 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001439 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001440 if (win.removeReplacedWindowIfNeeded(replacement)) {
1441 return;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001442 }
1443 }
1444 }
1445
1446 void startFreezingScreen() {
1447 if (DEBUG_ORIENTATION) logWithStack(TAG, "Set freezing of " + appToken + ": hidden="
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001448 + isHidden() + " freezing=" + mFreezingScreen + " hiddenRequested="
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001449 + hiddenRequested);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001450 if (!hiddenRequested) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001451 if (!mFreezingScreen) {
1452 mFreezingScreen = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001453 mWmService.registerAppFreezeListener(this);
1454 mWmService.mAppsFreezingScreen++;
1455 if (mWmService.mAppsFreezingScreen == 1) {
1456 mWmService.startFreezingDisplayLocked(0, 0, getDisplayContent());
1457 mWmService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
1458 mWmService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001459 }
1460 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001461 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001462 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001463 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001464 w.onStartFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001465 }
1466 }
1467 }
1468
1469 void stopFreezingScreen(boolean unfreezeSurfaceNow, boolean force) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001470 if (!mFreezingScreen) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001471 return;
1472 }
1473 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + this + " force=" + force);
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001474 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001475 boolean unfrozeWindows = false;
1476 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001477 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001478 unfrozeWindows |= w.onStopFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001479 }
1480 if (force || unfrozeWindows) {
1481 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "No longer freezing: " + this);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001482 mFreezingScreen = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001483 mWmService.unregisterAppFreezeListener(this);
1484 mWmService.mAppsFreezingScreen--;
1485 mWmService.mLastFinishedFreezeSource = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001486 }
1487 if (unfreezeSurfaceNow) {
1488 if (unfrozeWindows) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001489 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001490 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001491 mWmService.stopFreezingDisplayLocked();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001492 }
1493 }
1494
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001495 @Override
1496 public void onAppFreezeTimeout() {
1497 Slog.w(TAG_WM, "Force clearing freeze: " + this);
1498 stopFreezingScreen(true, true);
1499 }
1500
Jorim Jaggi60f9c972018-02-01 19:21:07 +01001501 /**
1502 * Tries to transfer the starting window from a token that's above ourselves in the task but
1503 * not visible anymore. This is a common scenario apps use: Trampoline activity T start main
1504 * activity M in the same task. Now, when reopening the task, T starts on top of M but then
1505 * immediately finishes after, so we have to transfer T to M.
1506 */
1507 void transferStartingWindowFromHiddenAboveTokenIfNeeded() {
1508 final Task task = getTask();
1509 for (int i = task.mChildren.size() - 1; i >= 0; i--) {
1510 final AppWindowToken fromToken = task.mChildren.get(i);
1511 if (fromToken == this) {
1512 return;
1513 }
1514 if (fromToken.hiddenRequested && transferStartingWindow(fromToken.token)) {
1515 return;
1516 }
1517 }
1518 }
1519
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001520 boolean transferStartingWindow(IBinder transferFrom) {
Wale Ogunwale02319a62016-09-26 15:21:22 -07001521 final AppWindowToken fromToken = getDisplayContent().getAppWindowToken(transferFrom);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001522 if (fromToken == null) {
1523 return false;
1524 }
1525
1526 final WindowState tStartingWindow = fromToken.startingWindow;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08001527 if (tStartingWindow != null && fromToken.startingSurface != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001528 // In this case, the starting icon has already been displayed, so start
1529 // letting windows get shown immediately without any more transitions.
lumark588a3e82018-07-20 18:53:54 +08001530 getDisplayContent().mSkipAppTransitionAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001531
1532 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Moving existing starting " + tStartingWindow
1533 + " from " + fromToken + " to " + this);
1534
1535 final long origId = Binder.clearCallingIdentity();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001536 try {
1537 // Transfer the starting window over to the new token.
chaviwa8f07a72019-05-01 16:25:39 -07001538 mStartingData = fromToken.mStartingData;
Peter Visontay3556a3b2017-11-01 17:23:17 +00001539 startingSurface = fromToken.startingSurface;
1540 startingDisplayed = fromToken.startingDisplayed;
1541 fromToken.startingDisplayed = false;
1542 startingWindow = tStartingWindow;
1543 reportedVisible = fromToken.reportedVisible;
chaviwa8f07a72019-05-01 16:25:39 -07001544 fromToken.mStartingData = null;
Peter Visontay3556a3b2017-11-01 17:23:17 +00001545 fromToken.startingSurface = null;
1546 fromToken.startingWindow = null;
1547 fromToken.startingMoved = true;
1548 tStartingWindow.mToken = this;
1549 tStartingWindow.mAppToken = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001550
Peter Visontay3556a3b2017-11-01 17:23:17 +00001551 if (DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
1552 "Removing starting " + tStartingWindow + " from " + fromToken);
1553 fromToken.removeChild(tStartingWindow);
1554 fromToken.postWindowRemoveStartingWindowCleanup(tStartingWindow);
1555 fromToken.mHiddenSetFromTransferredStartingWindow = false;
1556 addWindow(tStartingWindow);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001557
Peter Visontay3556a3b2017-11-01 17:23:17 +00001558 // Propagate other interesting state between the tokens. If the old token is displayed,
1559 // we should immediately force the new one to be displayed. If it is animating, we need
1560 // to move that animation to the new one.
1561 if (fromToken.allDrawn) {
1562 allDrawn = true;
1563 deferClearAllDrawn = fromToken.deferClearAllDrawn;
1564 }
1565 if (fromToken.firstWindowDrawn) {
1566 firstWindowDrawn = true;
1567 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001568 if (!fromToken.isHidden()) {
1569 setHidden(false);
Peter Visontay3556a3b2017-11-01 17:23:17 +00001570 hiddenRequested = false;
1571 mHiddenSetFromTransferredStartingWindow = true;
1572 }
1573 setClientHidden(fromToken.mClientHidden);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001574
Jorim Jaggi980c9de2017-11-17 01:41:37 +01001575 transferAnimation(fromToken);
1576
1577 // When transferring an animation, we no longer need to apply an animation to the
Tiger Huangc9d0d002019-05-29 22:55:29 +08001578 // the token we transfer the animation over. Thus, set this flag to indicate we've
1579 // transferred the animation.
1580 mUseTransferredAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001581
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001582 mWmService.updateFocusedWindowLocked(
Peter Visontay3556a3b2017-11-01 17:23:17 +00001583 UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/);
1584 getDisplayContent().setLayoutNeeded();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001585 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001586 } finally {
1587 Binder.restoreCallingIdentity(origId);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001588 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001589 return true;
chaviwa8f07a72019-05-01 16:25:39 -07001590 } else if (fromToken.mStartingData != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001591 // The previous app was getting ready to show a
1592 // starting window, but hasn't yet done so. Steal it!
1593 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
1594 "Moving pending starting from " + fromToken + " to " + this);
chaviwa8f07a72019-05-01 16:25:39 -07001595 mStartingData = fromToken.mStartingData;
1596 fromToken.mStartingData = null;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001597 fromToken.startingMoved = true;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001598 scheduleAddStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001599 return true;
1600 }
1601
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001602 // TODO: Transfer thumbnail
1603
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001604 return false;
1605 }
1606
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001607 boolean isLastWindow(WindowState win) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001608 return mChildren.size() == 1 && mChildren.get(0) == win;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001609 }
1610
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001611 @Override
1612 void onAppTransitionDone() {
1613 sendingToBottom = false;
1614 }
1615
Wale Ogunwale51362492016-09-08 17:49:17 -07001616 /**
1617 * We override because this class doesn't want its children affecting its reported orientation
1618 * in anyway.
1619 */
1620 @Override
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001621 int getOrientation(int candidate) {
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001622 if (candidate == SCREEN_ORIENTATION_BEHIND) {
1623 // Allow app to specify orientation regardless of its visibility state if the current
1624 // candidate want us to use orientation behind. I.e. the visible app on-top of this one
1625 // wants us to use the orientation of the app behind it.
1626 return mOrientation;
1627 }
1628
Bryce Lee61fbcbc2017-03-10 14:14:03 -08001629 // The {@link AppWindowToken} should only specify an orientation when it is not closing or
1630 // going to the bottom. Allowing closing {@link AppWindowToken} to participate can lead to
1631 // an Activity in another task being started in the wrong orientation during the transition.
lumark588a3e82018-07-20 18:53:54 +08001632 if (!(sendingToBottom || getDisplayContent().mClosingApps.contains(this))
1633 && (isVisible() || getDisplayContent().mOpeningApps.contains(this))) {
Bryce Leea163b762017-01-24 11:05:01 -08001634 return mOrientation;
Wale Ogunwale51362492016-09-08 17:49:17 -07001635 }
Bryce Leea163b762017-01-24 11:05:01 -08001636
1637 return SCREEN_ORIENTATION_UNSET;
Wale Ogunwale51362492016-09-08 17:49:17 -07001638 }
1639
Wale Ogunwaleb198b742016-12-01 08:44:09 -08001640 /** Returns the app's preferred orientation regardless of its currently visibility state. */
1641 int getOrientationIgnoreVisibility() {
1642 return mOrientation;
1643 }
1644
Riddle Hsub398da32019-01-21 21:48:16 +08001645 /** @return {@code true} if the compatibility bounds is taking effect. */
1646 boolean inSizeCompatMode() {
1647 return mSizeCompatBounds != null;
1648 }
1649
1650 @Override
1651 float getSizeCompatScale() {
1652 return inSizeCompatMode() ? mSizeCompatScale : super.getSizeCompatScale();
1653 }
1654
1655 /**
1656 * @return Non-empty bounds if the activity has override bounds.
1657 * @see ActivityRecord#resolveOverrideConfiguration(Configuration)
1658 */
1659 Rect getResolvedOverrideBounds() {
1660 // Get bounds from resolved override configuration because it is computed with orientation.
1661 return getResolvedOverrideConfiguration().windowConfiguration.getBounds();
1662 }
1663
Craig Mautnerdbb79912012-03-01 18:59:14 -08001664 @Override
Winson Chunge55c0192017-08-24 14:50:48 -07001665 public void onConfigurationChanged(Configuration newParentConfig) {
1666 final int prevWinMode = getWindowingMode();
Evan Rosky2289ba12018-11-19 18:28:18 -08001667 mTmpPrevBounds.set(getBounds());
Winson Chunge55c0192017-08-24 14:50:48 -07001668 super.onConfigurationChanged(newParentConfig);
Riddle Hsub398da32019-01-21 21:48:16 +08001669
1670 final Task task = getTask();
1671 final Rect overrideBounds = getResolvedOverrideBounds();
1672 if (task != null && !overrideBounds.isEmpty()
1673 // If the changes come from change-listener, the incoming parent configuration is
1674 // still the old one. Make sure their orientations are the same to reduce computing
1675 // the compatibility bounds for the intermediate state.
Riddle Hsu04164182019-03-07 18:03:27 +08001676 && (task.mTaskRecord == null || task.mTaskRecord
1677 .getConfiguration().orientation == newParentConfig.orientation)) {
Riddle Hsub398da32019-01-21 21:48:16 +08001678 final Rect taskBounds = task.getBounds();
1679 // Since we only center the activity horizontally, if only the fixed height is smaller
1680 // than its container, the override bounds don't need to take effect.
1681 if ((overrideBounds.width() != taskBounds.width()
1682 || overrideBounds.height() > taskBounds.height())) {
1683 calculateCompatBoundsTransformation(newParentConfig);
1684 updateSurfacePosition();
1685 } else if (mSizeCompatBounds != null) {
1686 mSizeCompatBounds = null;
1687 mSizeCompatScale = 1f;
1688 updateSurfacePosition();
1689 }
1690 }
1691
Winson Chunge55c0192017-08-24 14:50:48 -07001692 final int winMode = getWindowingMode();
1693
1694 if (prevWinMode == winMode) {
1695 return;
1696 }
1697
1698 if (prevWinMode != WINDOWING_MODE_UNDEFINED && winMode == WINDOWING_MODE_PINNED) {
1699 // Entering PiP from fullscreen, reset the snap fraction
1700 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(this);
Winson Chung82267ce2018-04-06 16:38:26 -07001701 } else if (prevWinMode == WINDOWING_MODE_PINNED && winMode != WINDOWING_MODE_UNDEFINED
1702 && !isHidden()) {
Winson Chunge55c0192017-08-24 14:50:48 -07001703 // Leaving PiP to fullscreen, save the snap fraction based on the pre-animation bounds
1704 // for the next re-entry into PiP (assuming the activity is not hidden or destroyed)
1705 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
1706 if (pinnedStack != null) {
Winson Chung8efa1652018-06-06 09:34:23 -07001707 final Rect stackBounds;
1708 if (pinnedStack.lastAnimatingBoundsWasToFullscreen()) {
1709 // We are animating the bounds, use the pre-animation bounds to save the snap
1710 // fraction
1711 stackBounds = pinnedStack.mPreAnimationBounds;
1712 } else {
1713 // We skip the animation if the fullscreen configuration is not compatible, so
1714 // use the current bounds to calculate the saved snap fraction instead
1715 // (see PinnedActivityStack.skipResizeAnimation())
1716 stackBounds = mTmpRect;
1717 pinnedStack.getBounds(stackBounds);
1718 }
Winson Chunge55c0192017-08-24 14:50:48 -07001719 mDisplayContent.mPinnedStackControllerLocked.saveReentrySnapFraction(this,
Winson Chung8efa1652018-06-06 09:34:23 -07001720 stackBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001721 }
Evan Rosky2289ba12018-11-19 18:28:18 -08001722 } else if (shouldStartChangeTransition(prevWinMode, winMode)) {
1723 initializeChangeTransition(mTmpPrevBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001724 }
1725 }
1726
Evan Rosky2289ba12018-11-19 18:28:18 -08001727 private boolean shouldStartChangeTransition(int prevWinMode, int newWinMode) {
Evan Rosky25b56192019-02-06 16:10:56 -08001728 if (mWmService.mDisableTransitionAnimation
1729 || !isVisible()
1730 || getDisplayContent().mAppTransition.isTransitionSet()
1731 || getSurfaceControl() == null) {
Evan Rosky2289ba12018-11-19 18:28:18 -08001732 return false;
1733 }
1734 // Only do an animation into and out-of freeform mode for now. Other mode
1735 // transition animations are currently handled by system-ui.
1736 return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
1737 }
1738
1739 /**
1740 * Initializes a change transition. Because the app is visible already, there is a small period
1741 * of time where the user can see the app content/window update before the transition starts.
1742 * To prevent this, we immediately take a snapshot and place the app/snapshot into a leash which
1743 * "freezes" the location/crop until the transition starts.
1744 * <p>
1745 * Here's a walk-through of the process:
1746 * 1. Create a temporary leash ("interim-change-leash") and reparent the app to it.
1747 * 2. Set the temporary leash's position/crop to the current state.
1748 * 3. Create a snapshot and place that at the top of the leash to cover up content changes.
1749 * 4. Once the transition is ready, it will reparent the app to the animation leash.
1750 * 5. Detach the interim-change-leash.
1751 */
1752 private void initializeChangeTransition(Rect startBounds) {
1753 mDisplayContent.prepareAppTransition(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
1754 false /* alwaysKeepCurrent */, 0, false /* forceOverride */);
1755 mDisplayContent.mChangingApps.add(this);
1756 mTransitStartRect.set(startBounds);
1757
1758 final SurfaceControl.Builder builder = makeAnimationLeash()
1759 .setParent(getAnimationLeashParent())
1760 .setName(getSurfaceControl() + " - interim-change-leash");
1761 mTransitChangeLeash = builder.build();
1762 Transaction t = getPendingTransaction();
1763 t.setWindowCrop(mTransitChangeLeash, startBounds.width(), startBounds.height());
1764 t.setPosition(mTransitChangeLeash, startBounds.left, startBounds.top);
1765 t.show(mTransitChangeLeash);
1766 t.reparent(getSurfaceControl(), mTransitChangeLeash);
1767 onAnimationLeashCreated(t, mTransitChangeLeash);
1768
Evan Rosky966759f2019-01-15 10:33:58 -08001769 // Skip creating snapshot if this transition is controlled by a remote animator which
1770 // doesn't need it.
1771 ArraySet<Integer> activityTypes = new ArraySet<>();
1772 activityTypes.add(getActivityType());
1773 RemoteAnimationAdapter adapter =
1774 mDisplayContent.mAppTransitionController.getRemoteAnimationOverride(
1775 this, TRANSIT_TASK_CHANGE_WINDOWING_MODE, activityTypes);
1776 if (adapter != null && !adapter.getChangeNeedsSnapshot()) {
1777 return;
1778 }
1779
Evan Rosky08e20932019-05-14 10:54:07 -07001780 Task task = getTask();
1781 if (mThumbnail == null && task != null && !hasCommittedReparentToAnimationLeash()) {
1782 SurfaceControl.ScreenshotGraphicBuffer snapshot =
1783 mWmService.mTaskSnapshotController.createTaskSnapshot(
1784 task, 1 /* scaleFraction */);
Yunfan Chendcb1fcf2019-02-07 19:08:41 +09001785 if (snapshot != null) {
Evan Rosky08e20932019-05-14 10:54:07 -07001786 mThumbnail = new AppWindowThumbnail(t, this, snapshot.getGraphicBuffer(),
Yunfan Chendcb1fcf2019-02-07 19:08:41 +09001787 true /* relative */);
1788 }
Evan Rosky2289ba12018-11-19 18:28:18 -08001789 }
1790 }
1791
1792 boolean isInChangeTransition() {
Evan Roskyec9488c2019-03-01 19:32:12 -08001793 return mTransitChangeLeash != null || AppTransition.isChangeTransit(mTransit);
Evan Rosky2289ba12018-11-19 18:28:18 -08001794 }
1795
Evan Rosky966759f2019-01-15 10:33:58 -08001796 @VisibleForTesting
1797 AppWindowThumbnail getThumbnail() {
1798 return mThumbnail;
1799 }
1800
Riddle Hsub398da32019-01-21 21:48:16 +08001801 /**
1802 * Calculates the scale and offset to horizontal center the size compatibility bounds into the
1803 * region which is available to application.
1804 */
1805 private void calculateCompatBoundsTransformation(Configuration newParentConfig) {
1806 final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds();
Riddle Hsu74826262019-04-17 14:57:42 +08001807 final Rect parentBounds = newParentConfig.windowConfiguration.getBounds();
1808 final Rect viewportBounds = parentAppBounds != null ? parentAppBounds : parentBounds;
Riddle Hsu04164182019-03-07 18:03:27 +08001809 final Rect appBounds = getWindowConfiguration().getAppBounds();
1810 final Rect contentBounds = appBounds != null ? appBounds : getResolvedOverrideBounds();
Riddle Hsub398da32019-01-21 21:48:16 +08001811 final float contentW = contentBounds.width();
1812 final float contentH = contentBounds.height();
1813 final float viewportW = viewportBounds.width();
1814 final float viewportH = viewportBounds.height();
1815 // Only allow to scale down.
1816 mSizeCompatScale = (contentW <= viewportW && contentH <= viewportH)
1817 ? 1 : Math.min(viewportW / contentW, viewportH / contentH);
1818 final int offsetX = (int) ((viewportW - contentW * mSizeCompatScale + 1) * 0.5f)
1819 + viewportBounds.left;
1820
1821 if (mSizeCompatBounds == null) {
1822 mSizeCompatBounds = new Rect();
1823 }
1824 mSizeCompatBounds.set(contentBounds);
1825 mSizeCompatBounds.offsetTo(0, 0);
1826 mSizeCompatBounds.scale(mSizeCompatScale);
Riddle Hsu74826262019-04-17 14:57:42 +08001827 // Ensure to align the top with the parent.
1828 mSizeCompatBounds.top = parentBounds.top;
Riddle Hsu04164182019-03-07 18:03:27 +08001829 // The decor inset is included in height.
1830 mSizeCompatBounds.bottom += viewportBounds.top;
Riddle Hsub398da32019-01-21 21:48:16 +08001831 mSizeCompatBounds.left += offsetX;
1832 mSizeCompatBounds.right += offsetX;
1833 }
1834
1835 @Override
1836 public Rect getBounds() {
1837 if (mSizeCompatBounds != null) {
1838 return mSizeCompatBounds;
1839 }
1840 return super.getBounds();
1841 }
1842
1843 @Override
1844 public boolean matchParentBounds() {
1845 if (super.matchParentBounds()) {
1846 return true;
1847 }
1848 // An activity in size compatibility mode may have override bounds which equals to its
1849 // parent bounds, so the exact bounds should also be checked.
1850 final WindowContainer parent = getParent();
1851 return parent == null || parent.getBounds().equals(getResolvedOverrideBounds());
1852 }
1853
Winson Chunge55c0192017-08-24 14:50:48 -07001854 @Override
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001855 void checkAppWindowsReadyToShow() {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001856 if (allDrawn == mLastAllDrawn) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001857 return;
1858 }
1859
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001860 mLastAllDrawn = allDrawn;
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001861 if (!allDrawn) {
1862 return;
1863 }
1864
1865 // The token has now changed state to having all windows shown... what to do, what to do?
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001866 if (mFreezingScreen) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001867 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001868 stopFreezingScreen(false, true);
1869 if (DEBUG_ORIENTATION) Slog.i(TAG,
1870 "Setting mOrientationChangeComplete=true because wtoken " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001871 + " numInteresting=" + mNumInterestingWindows + " numDrawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001872 // This will set mOrientationChangeComplete and cause a pass through layout.
1873 setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001874 "checkAppWindowsReadyToShow: freezingScreen");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001875 } else {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001876 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001877
1878 // We can now show all of the drawn windows!
lumark588a3e82018-07-20 18:53:54 +08001879 if (!getDisplayContent().mOpeningApps.contains(this) && canShowWindows()) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001880 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001881 }
1882 }
1883 }
1884
Matthew Ng5d23afa2017-06-21 16:16:24 -07001885 /**
Bryce Leed390deb2017-06-22 13:14:28 -07001886 * Returns whether the drawn window states of this {@link AppWindowToken} has considered every
1887 * child {@link WindowState}. A child is considered if it has been passed into
1888 * {@link #updateDrawnWindowStates(WindowState)} after being added. This is used to determine
1889 * whether states, such as {@code allDrawn}, can be set, which relies on state variables such as
1890 * {@code mNumInterestingWindows}, which depend on all {@link WindowState}s being considered.
1891 *
1892 * @return {@code true} If all children have been considered, {@code false}.
1893 */
1894 private boolean allDrawnStatesConsidered() {
Bryce Lee6311c4b2017-07-06 14:09:29 -07001895 for (int i = mChildren.size() - 1; i >= 0; --i) {
1896 final WindowState child = mChildren.get(i);
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001897 if (child.mightAffectAllDrawn() && !child.getDrawnStateEvaluated()) {
Bryce Leed390deb2017-06-22 13:14:28 -07001898 return false;
1899 }
1900 }
1901 return true;
1902 }
1903
1904 /**
Matthew Ng5d23afa2017-06-21 16:16:24 -07001905 * Determines if the token has finished drawing. This should only be called from
1906 * {@link DisplayContent#applySurfaceChangesTransaction}
1907 */
Matthew Ng498c71d2017-04-18 13:55:45 -07001908 void updateAllDrawn() {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001909 if (!allDrawn) {
Matthew Ng498c71d2017-04-18 13:55:45 -07001910 // Number of drawn windows can be less when a window is being relaunched, wait for
Bryce Leed390deb2017-06-22 13:14:28 -07001911 // all windows to be launched and drawn for this token be considered all drawn.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001912 final int numInteresting = mNumInterestingWindows;
Bryce Leed390deb2017-06-22 13:14:28 -07001913
1914 // We must make sure that all present children have been considered (determined by
1915 // {@link #allDrawnStatesConsidered}) before evaluating whether everything has been
1916 // drawn.
1917 if (numInteresting > 0 && allDrawnStatesConsidered()
1918 && mNumDrawnWindows >= numInteresting && !isRelaunching()) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001919 if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawn: " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001920 + " interesting=" + numInteresting + " drawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001921 allDrawn = true;
1922 // Force an additional layout pass where
1923 // WindowStateAnimator#commitFinishDrawingLocked() will call performShowLocked().
Matthew Ng498c71d2017-04-18 13:55:45 -07001924 if (mDisplayContent != null) {
1925 mDisplayContent.setLayoutNeeded();
1926 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001927 mWmService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
Robert Carrecc06b32017-04-18 14:25:10 -07001928
Winson Chunge7ba6862017-05-24 12:13:33 -07001929 // Notify the pinned stack upon all windows drawn. If there was an animation in
1930 // progress then this signal will resume that animation.
Wale Ogunwale61911492017-10-11 08:50:50 -07001931 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
Winson Chunge7ba6862017-05-24 12:13:33 -07001932 if (pinnedStack != null) {
1933 pinnedStack.onAllWindowsDrawn();
Robert Carrecc06b32017-04-18 14:25:10 -07001934 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001935 }
1936 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001937 }
1938
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001939 boolean keyDispatchingTimedOut(String reason, int windowPid) {
1940 return mActivityRecord != null && mActivityRecord.keyDispatchingTimedOut(reason, windowPid);
1941 }
1942
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001943 /**
1944 * Updated this app token tracking states for interesting and drawn windows based on the window.
1945 *
1946 * @return Returns true if the input window is considered interesting and drawn while all the
1947 * windows in this app token where not considered drawn as of the last pass.
1948 */
1949 boolean updateDrawnWindowStates(WindowState w) {
Bryce Leed390deb2017-06-22 13:14:28 -07001950 w.setDrawnStateEvaluated(true /*evaluated*/);
1951
Jorim Jaggie4b0f282017-05-17 15:10:29 +02001952 if (DEBUG_STARTING_WINDOW_VERBOSE && w == startingWindow) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001953 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + w.isOnScreen()
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001954 + " allDrawn=" + allDrawn + " freezingScreen=" + mFreezingScreen);
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001955 }
1956
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001957 if (allDrawn && !mFreezingScreen) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001958 return false;
1959 }
1960
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001961 if (mLastTransactionSequence != mWmService.mTransactionSequence) {
1962 mLastTransactionSequence = mWmService.mTransactionSequence;
Matthew Ng53e66b22018-01-12 17:13:13 -08001963 mNumDrawnWindows = 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001964 startingDisplayed = false;
Matthew Ng53e66b22018-01-12 17:13:13 -08001965
1966 // There is the main base application window, even if it is exiting, wait for it
1967 mNumInterestingWindows = findMainWindow(false /* includeStartingApp */) != null ? 1 : 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001968 }
1969
1970 final WindowStateAnimator winAnimator = w.mWinAnimator;
1971
1972 boolean isInterestingAndDrawn = false;
1973
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001974 if (!allDrawn && w.mightAffectAllDrawn()) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001975 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
1976 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001977 + ", isAnimationSet=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001978 if (!w.isDrawnLw()) {
1979 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController
chaviw15ad49f2019-04-24 15:05:39 -07001980 + " pv=" + w.isVisibleByPolicy()
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001981 + " mDrawState=" + winAnimator.drawStateToString()
1982 + " ph=" + w.isParentWindowHidden() + " th=" + hiddenRequested
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001983 + " a=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001984 }
1985 }
1986
1987 if (w != startingWindow) {
1988 if (w.isInteresting()) {
Matthew Ng53e66b22018-01-12 17:13:13 -08001989 // Add non-main window as interesting since the main app has already been added
1990 if (findMainWindow(false /* includeStartingApp */) != w) {
1991 mNumInterestingWindows++;
1992 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001993 if (w.isDrawnLw()) {
1994 mNumDrawnWindows++;
1995
1996 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, "tokenMayBeDrawn: "
1997 + this + " w=" + w + " numInteresting=" + mNumInterestingWindows
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001998 + " freezingScreen=" + mFreezingScreen
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001999 + " mAppFreezing=" + w.mAppFreezing);
2000
2001 isInterestingAndDrawn = true;
2002 }
2003 }
2004 } else if (w.isDrawnLw()) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002005 if (mActivityRecord != null) {
2006 mActivityRecord.onStartingWindowDrawn(SystemClock.uptimeMillis());
Jorim Jaggi3878ca32017-02-02 17:13:05 -08002007 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002008 startingDisplayed = true;
2009 }
2010 }
2011
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002012 return isInterestingAndDrawn;
2013 }
2014
Adrian Roos23df3a32018-03-15 15:41:13 +01002015 void layoutLetterbox(WindowState winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002016 final WindowState w = findMainWindow();
Adrian Roosf93b6d22018-03-21 13:48:26 +01002017 if (w == null || winHint != null && w != winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002018 return;
2019 }
Jorim Jaggia32da382018-03-28 18:01:22 +02002020 final boolean surfaceReady = w.isDrawnLw() // Regular case
Adrian Roosf93b6d22018-03-21 13:48:26 +01002021 || w.mWinAnimator.mSurfaceDestroyDeferred // The preserved surface is still ready.
2022 || w.isDragResizeChanged(); // Waiting for relayoutWindow to call preserveSurface.
Jorim Jaggi4981f152019-03-26 18:58:45 +01002023 final boolean needsLetterbox = surfaceReady && w.isLetterboxedAppWindow() && fillsParent();
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002024 if (needsLetterbox) {
2025 if (mLetterbox == null) {
2026 mLetterbox = new Letterbox(() -> makeChildSurface(null));
Riddle Hsu192fe762019-01-15 23:41:57 +08002027 mLetterbox.attachInput(w);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002028 }
Adrian Roos7af9d972018-11-30 15:26:27 +01002029 getPosition(mTmpPoint);
Evan Rosky67c15642019-04-24 13:17:28 -07002030 // Get the bounds of the "space-to-fill". In multi-window mode, the task-level
2031 // represents this. In fullscreen-mode, the stack does (since the orientation letterbox
2032 // is also applied to the task).
2033 Rect spaceToFill = (inMultiWindowMode() || getStack() == null)
2034 ? getTask().getDisplayedBounds() : getStack().getDisplayedBounds();
Evan Rosky4fb1e912019-03-06 13:54:43 -08002035 mLetterbox.layout(spaceToFill, w.getFrameLw(), mTmpPoint);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002036 } else if (mLetterbox != null) {
Adrian Roos23df3a32018-03-15 15:41:13 +01002037 mLetterbox.hide();
2038 }
2039 }
2040
2041 void updateLetterboxSurface(WindowState winHint) {
2042 final WindowState w = findMainWindow();
2043 if (w != winHint && winHint != null && w != null) {
2044 return;
2045 }
2046 layoutLetterbox(winHint);
2047 if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) {
Tiger Huanged6794e2019-05-07 20:07:59 +08002048 mLetterbox.applySurfaceChanges(getPendingTransaction());
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002049 }
2050 }
2051
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07002052 @Override
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002053 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002054 // For legacy reasons we process the TaskStack.mExitingAppTokens first in DisplayContent
2055 // before the non-exiting app tokens. So, we skip the exiting app tokens here.
2056 // TODO: Investigate if we need to continue to do this or if we can just process them
2057 // in-order.
2058 if (mIsExiting && !waitingForReplacement()) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002059 return false;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002060 }
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002061 return forAllWindowsUnchecked(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002062 }
2063
lumark588a3e82018-07-20 18:53:54 +08002064 @Override
2065 void forAllAppWindows(Consumer<AppWindowToken> callback) {
2066 callback.accept(this);
2067 }
2068
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002069 boolean forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback,
2070 boolean traverseTopToBottom) {
2071 return super.forAllWindows(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002072 }
2073
2074 @Override
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002075 AppWindowToken asAppWindowToken() {
2076 // I am an app window token!
2077 return this;
2078 }
2079
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002080 boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
2081 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
2082 IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
2083 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
2084 // If the display is frozen, we won't do anything until the actual window is
2085 // displayed so there is no reason to put in the starting window.
2086 if (!okToDisplay()) {
2087 return false;
2088 }
2089
chaviwa8f07a72019-05-01 16:25:39 -07002090 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002091 return false;
2092 }
2093
2094 final WindowState mainWin = findMainWindow();
2095 if (mainWin != null && mainWin.mWinAnimator.getShown()) {
2096 // App already has a visible window...why would you want a starting window?
2097 return false;
2098 }
2099
2100 final ActivityManager.TaskSnapshot snapshot =
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002101 mWmService.mTaskSnapshotController.getSnapshot(
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002102 getTask().mTaskId, getTask().mUserId,
2103 false /* restoreFromDisk */, false /* reducedResolution */);
2104 final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
2105 allowTaskSnapshot, activityCreated, fromRecents, snapshot);
2106
2107 if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
2108 return createSnapshot(snapshot);
2109 }
2110
2111 // If this is a translucent window, then don't show a starting window -- the current
2112 // effect (a full-screen opaque starting window that fades away to the real contents
2113 // when it is ready) does not work for this.
2114 if (DEBUG_STARTING_WINDOW) {
2115 Slog.v(TAG, "Checking theme of starting window: 0x" + Integer.toHexString(theme));
2116 }
2117 if (theme != 0) {
2118 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
2119 com.android.internal.R.styleable.Window,
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002120 mWmService.mCurrentUserId);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002121 if (ent == null) {
2122 // Whoops! App doesn't exist. Um. Okay. We'll just pretend like we didn't
2123 // see that.
2124 return false;
2125 }
2126 final boolean windowIsTranslucent = ent.array.getBoolean(
2127 com.android.internal.R.styleable.Window_windowIsTranslucent, false);
2128 final boolean windowIsFloating = ent.array.getBoolean(
2129 com.android.internal.R.styleable.Window_windowIsFloating, false);
2130 final boolean windowShowWallpaper = ent.array.getBoolean(
2131 com.android.internal.R.styleable.Window_windowShowWallpaper, false);
2132 final boolean windowDisableStarting = ent.array.getBoolean(
2133 com.android.internal.R.styleable.Window_windowDisablePreview, false);
2134 if (DEBUG_STARTING_WINDOW) {
2135 Slog.v(TAG, "Translucent=" + windowIsTranslucent
2136 + " Floating=" + windowIsFloating
2137 + " ShowWallpaper=" + windowShowWallpaper);
2138 }
2139 if (windowIsTranslucent) {
2140 return false;
2141 }
2142 if (windowIsFloating || windowDisableStarting) {
2143 return false;
2144 }
2145 if (windowShowWallpaper) {
2146 if (getDisplayContent().mWallpaperController
2147 .getWallpaperTarget() == null) {
2148 // If this theme is requesting a wallpaper, and the wallpaper
2149 // is not currently visible, then this effectively serves as
2150 // an opaque window and our starting window transition animation
2151 // can still work. We just need to make sure the starting window
2152 // is also showing the wallpaper.
2153 windowFlags |= FLAG_SHOW_WALLPAPER;
2154 } else {
2155 return false;
2156 }
2157 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002158 }
Yunfan Chen8a8c0ed2018-12-18 16:46:32 -08002159
2160 if (transferStartingWindow(transferFrom)) {
2161 return true;
2162 }
2163
2164 // There is no existing starting window, and we don't want to create a splash screen, so
2165 // that's it!
2166 if (type != STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
2167 return false;
2168 }
2169
2170 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SplashScreenStartingData");
chaviwa8f07a72019-05-01 16:25:39 -07002171 mStartingData = new SplashScreenStartingData(mWmService, pkg,
Yunfan Chen8a8c0ed2018-12-18 16:46:32 -08002172 theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
2173 getMergedOverrideConfiguration());
2174 scheduleAddStartingWindow();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002175 return true;
2176 }
2177
2178
2179 private boolean createSnapshot(ActivityManager.TaskSnapshot snapshot) {
2180 if (snapshot == null) {
2181 return false;
2182 }
2183
2184 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SnapshotStartingData");
chaviwa8f07a72019-05-01 16:25:39 -07002185 mStartingData = new SnapshotStartingData(mWmService, snapshot);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002186 scheduleAddStartingWindow();
2187 return true;
2188 }
2189
2190 void scheduleAddStartingWindow() {
2191 // Note: we really want to do sendMessageAtFrontOfQueue() because we
2192 // want to process the message ASAP, before any other queued
2193 // messages.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002194 if (!mWmService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002195 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING");
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002196 mWmService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002197 }
2198 }
2199
2200 private final Runnable mAddStartingWindow = new Runnable() {
2201
2202 @Override
2203 public void run() {
chaviwa8f07a72019-05-01 16:25:39 -07002204 // Can be accessed without holding the global lock
2205 final StartingData startingData;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002206 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002207 // There can only be one adding request, silly caller!
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002208 mWmService.mAnimationHandler.removeCallbacks(this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002209
chaviwa8f07a72019-05-01 16:25:39 -07002210 if (mStartingData == null) {
2211 // Animation has been canceled... do nothing.
2212 if (DEBUG_STARTING_WINDOW) {
2213 Slog.v(TAG, "startingData was nulled out before handling"
2214 + " mAddStartingWindow: " + AppWindowToken.this);
2215 }
2216 return;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002217 }
chaviwa8f07a72019-05-01 16:25:39 -07002218 startingData = mStartingData;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002219 }
2220
2221 if (DEBUG_STARTING_WINDOW) {
2222 Slog.v(TAG, "Add starting " + this + ": startingData=" + startingData);
2223 }
2224
2225 WindowManagerPolicy.StartingSurface surface = null;
2226 try {
2227 surface = startingData.createStartingSurface(AppWindowToken.this);
2228 } catch (Exception e) {
2229 Slog.w(TAG, "Exception when adding starting window", e);
2230 }
2231 if (surface != null) {
2232 boolean abort = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002233 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002234 // If the window was successfully added, then
2235 // we need to remove it.
chaviwa8f07a72019-05-01 16:25:39 -07002236 if (removed || mStartingData == null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002237 if (DEBUG_STARTING_WINDOW) {
2238 Slog.v(TAG, "Aborted starting " + AppWindowToken.this
chaviwa8f07a72019-05-01 16:25:39 -07002239 + ": removed=" + removed + " startingData=" + mStartingData);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002240 }
2241 startingWindow = null;
chaviwa8f07a72019-05-01 16:25:39 -07002242 mStartingData = null;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002243 abort = true;
2244 } else {
2245 startingSurface = surface;
2246 }
2247 if (DEBUG_STARTING_WINDOW && !abort) {
chaviwa8f07a72019-05-01 16:25:39 -07002248 Slog.v(TAG,
2249 "Added starting " + AppWindowToken.this + ": startingWindow="
2250 + startingWindow + " startingView=" + startingSurface);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002251 }
2252 }
2253 if (abort) {
2254 surface.remove();
2255 }
2256 } else if (DEBUG_STARTING_WINDOW) {
2257 Slog.v(TAG, "Surface returned was null: " + AppWindowToken.this);
2258 }
2259 }
2260 };
2261
2262 private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
2263 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents,
2264 ActivityManager.TaskSnapshot snapshot) {
2265 if (getDisplayContent().mAppTransition.getAppTransition()
2266 == TRANSIT_DOCK_TASK_FROM_RECENTS) {
2267 // TODO(b/34099271): Remove this statement to add back the starting window and figure
2268 // out why it causes flickering, the starting window appears over the thumbnail while
2269 // the docked from recents transition occurs
2270 return STARTING_WINDOW_TYPE_NONE;
2271 } else if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
2272 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2273 } else if (taskSwitch && allowTaskSnapshot) {
Kevin716a9db2018-12-18 16:53:39 -08002274 if (mWmService.mLowRamTaskSnapshotsAndRecents) {
Kevin58b47f12018-12-17 14:09:01 -08002275 // For low RAM devices, we use the splash screen starting window instead of the
2276 // task snapshot starting window.
2277 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2278 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002279 return snapshot == null ? STARTING_WINDOW_TYPE_NONE
2280 : snapshotOrientationSameAsTask(snapshot) || fromRecents
2281 ? STARTING_WINDOW_TYPE_SNAPSHOT : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2282 } else {
2283 return STARTING_WINDOW_TYPE_NONE;
2284 }
2285 }
2286
2287
2288 private boolean snapshotOrientationSameAsTask(ActivityManager.TaskSnapshot snapshot) {
2289 if (snapshot == null) {
2290 return false;
2291 }
2292 return getTask().getConfiguration().orientation == snapshot.getOrientation();
2293 }
2294
2295 void removeStartingWindow() {
2296 if (startingWindow == null) {
chaviwa8f07a72019-05-01 16:25:39 -07002297 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002298 // Starting window has not been added yet, but it is scheduled to be added.
2299 // Go ahead and cancel the request.
2300 if (DEBUG_STARTING_WINDOW) {
2301 Slog.v(TAG_WM, "Clearing startingData for token=" + this);
2302 }
chaviwa8f07a72019-05-01 16:25:39 -07002303 mStartingData = null;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002304 }
2305 return;
2306 }
2307
2308 final WindowManagerPolicy.StartingSurface surface;
chaviwa8f07a72019-05-01 16:25:39 -07002309 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002310 surface = startingSurface;
chaviwa8f07a72019-05-01 16:25:39 -07002311 mStartingData = null;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002312 startingSurface = null;
2313 startingWindow = null;
2314 startingDisplayed = false;
2315 if (surface == null) {
2316 if (DEBUG_STARTING_WINDOW) {
2317 Slog.v(TAG_WM, "startingWindow was set but startingSurface==null, couldn't "
2318 + "remove");
2319 }
2320 return;
2321 }
2322 } else {
2323 if (DEBUG_STARTING_WINDOW) {
2324 Slog.v(TAG_WM, "Tried to remove starting window but startingWindow was null:"
2325 + this);
2326 }
2327 return;
2328 }
2329
2330 if (DEBUG_STARTING_WINDOW) {
2331 Slog.v(TAG_WM, "Schedule remove starting " + this
2332 + " startingWindow=" + startingWindow
2333 + " startingView=" + startingSurface
2334 + " Callers=" + Debug.getCallers(5));
2335 }
2336
2337 // Use the same thread to remove the window as we used to add it, as otherwise we end up
2338 // with things in the view hierarchy being called from different threads.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002339 mWmService.mAnimationHandler.post(() -> {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002340 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Removing startingView=" + surface);
2341 try {
2342 surface.remove();
2343 } catch (Exception e) {
2344 Slog.w(TAG_WM, "Exception when removing starting window", e);
2345 }
2346 });
2347 }
2348
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002349 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -07002350 boolean fillsParent() {
2351 return mFillsParent;
2352 }
2353
2354 void setFillsParent(boolean fillsParent) {
2355 mFillsParent = fillsParent;
2356 }
2357
Jorim Jaggife762342016-10-13 14:33:27 +02002358 boolean containsDismissKeyguardWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002359 // Window state is transient during relaunch. We are not guaranteed to be frozen during the
2360 // entirety of the relaunch.
2361 if (isRelaunching()) {
2362 return mLastContainsDismissKeyguardWindow;
2363 }
2364
Jorim Jaggife762342016-10-13 14:33:27 +02002365 for (int i = mChildren.size() - 1; i >= 0; i--) {
2366 if ((mChildren.get(i).mAttrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
2367 return true;
2368 }
2369 }
2370 return false;
2371 }
2372
2373 boolean containsShowWhenLockedWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002374 // When we are relaunching, it is possible for us to be unfrozen before our previous
2375 // windows have been added back. Using the cached value ensures that our previous
2376 // showWhenLocked preference is honored until relaunching is complete.
2377 if (isRelaunching()) {
2378 return mLastContainsShowWhenLockedWindow;
2379 }
2380
Jorim Jaggife762342016-10-13 14:33:27 +02002381 for (int i = mChildren.size() - 1; i >= 0; i--) {
2382 if ((mChildren.get(i).mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
2383 return true;
2384 }
2385 }
Bryce Lee081554b2017-05-25 07:52:12 -07002386
Jorim Jaggife762342016-10-13 14:33:27 +02002387 return false;
2388 }
2389
2390 void checkKeyguardFlagsChanged() {
2391 final boolean containsDismissKeyguard = containsDismissKeyguardWindow();
2392 final boolean containsShowWhenLocked = containsShowWhenLockedWindow();
2393 if (containsDismissKeyguard != mLastContainsDismissKeyguardWindow
2394 || containsShowWhenLocked != mLastContainsShowWhenLockedWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002395 mWmService.notifyKeyguardFlagsChanged(null /* callback */,
lumark588a3e82018-07-20 18:53:54 +08002396 getDisplayContent().getDisplayId());
Jorim Jaggife762342016-10-13 14:33:27 +02002397 }
2398 mLastContainsDismissKeyguardWindow = containsDismissKeyguard;
2399 mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
2400 }
2401
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002402 WindowState getImeTargetBelowWindow(WindowState w) {
2403 final int index = mChildren.indexOf(w);
2404 if (index > 0) {
2405 final WindowState target = mChildren.get(index - 1);
2406 if (target.canBeImeTarget()) {
2407 return target;
2408 }
2409 }
2410 return null;
2411 }
2412
2413 WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
2414 WindowState candidate = null;
2415 for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
2416 final WindowState w = mChildren.get(i);
2417 if (w.mRemoved) {
2418 continue;
2419 }
Jorim Jaggi35d328a2018-08-14 17:00:20 +02002420 if (candidate == null) {
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002421 candidate = w;
2422 }
2423 }
2424 return candidate;
2425 }
2426
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002427 /**
2428 * See {@link Activity#setDisablePreviewScreenshots}.
2429 */
2430 void setDisablePreviewScreenshots(boolean disable) {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002431 mDisablePreviewScreenshots = disable;
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002432 }
2433
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002434 /**
chaviwd3bf08d2017-08-01 17:24:59 -07002435 * Sets whether the current launch can turn the screen on. See {@link #canTurnScreenOn()}
2436 */
2437 void setCanTurnScreenOn(boolean canTurnScreenOn) {
2438 mCanTurnScreenOn = canTurnScreenOn;
2439 }
2440
2441 /**
2442 * Indicates whether the current launch can turn the screen on. This is to prevent multiple
2443 * relayouts from turning the screen back on. The screen should only turn on at most
2444 * once per activity resume.
2445 *
2446 * @return true if the screen can be turned on.
2447 */
2448 boolean canTurnScreenOn() {
2449 return mCanTurnScreenOn;
2450 }
2451
2452 /**
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002453 * Retrieves whether we'd like to generate a snapshot that's based solely on the theme. This is
2454 * the case when preview screenshots are disabled {@link #setDisablePreviewScreenshots} or when
2455 * we can't take a snapshot for other reasons, for example, if we have a secure window.
2456 *
2457 * @return True if we need to generate an app theme snapshot, false if we'd like to take a real
2458 * screenshot.
2459 */
2460 boolean shouldUseAppThemeSnapshot() {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002461 return mDisablePreviewScreenshots || forAllWindows(w -> (w.mAttrs.flags & FLAG_SECURE) != 0,
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002462 true /* topToBottom */);
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002463 }
2464
Jorim Jaggibe418292018-03-26 16:14:12 +02002465 SurfaceControl getAppAnimationLayer() {
Jorim Jaggi391790622018-04-18 15:30:44 +02002466 return getAppAnimationLayer(isActivityTypeHome() ? ANIMATION_LAYER_HOME
2467 : needsZBoost() ? ANIMATION_LAYER_BOOSTED
2468 : ANIMATION_LAYER_STANDARD);
Jorim Jaggibe418292018-03-26 16:14:12 +02002469 }
2470
chaviw23ee71c2017-12-18 11:29:41 -08002471 @Override
Jorim Jaggi596a1992017-12-29 14:48:02 +01002472 public SurfaceControl getAnimationLeashParent() {
Robert Carrb9506032018-02-13 13:54:00 -08002473 // All normal app transitions take place in an animation layer which is below the pinned
2474 // stack but may be above the parent stacks of the given animating apps.
2475 // For transitions in the pinned stack (menu activity) we just let them occur as a child
2476 // of the pinned stack.
2477 if (!inPinnedWindowingMode()) {
2478 return getAppAnimationLayer();
2479 } else {
2480 return getStack().getSurfaceControl();
2481 }
chaviw23ee71c2017-12-18 11:29:41 -08002482 }
2483
lumarkb5a78b32019-04-25 20:31:30 +08002484
2485 @VisibleForTesting
2486 boolean shouldAnimate(int transit) {
Jorim Jaggic6976f02018-04-18 16:31:07 +02002487 final boolean isSplitScreenPrimary =
2488 getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
2489 final boolean allowSplitScreenPrimaryAnimation = transit != TRANSIT_WALLPAPER_OPEN;
2490
lumarkb5a78b32019-04-25 20:31:30 +08002491 // Don't animate while the task runs recents animation but only if we are in the mode
2492 // where we cancel with deferred screenshot, which means that the controller has
2493 // transformed the task.
lumark54284462019-03-05 20:44:27 +08002494 final RecentsAnimationController controller = mWmService.getRecentsAnimationController();
lumarkb5a78b32019-04-25 20:31:30 +08002495 if (controller != null && controller.isAnimatingTask(getTask())
Winson Chung7a545ae2019-07-16 14:52:13 -07002496 && controller.shouldDeferCancelUntilNextTransition()) {
lumark54284462019-03-05 20:44:27 +08002497 return false;
2498 }
2499
Jorim Jaggic6976f02018-04-18 16:31:07 +02002500 // We animate always if it's not split screen primary, and only some special cases in split
2501 // screen primary because it causes issues with stack clipping when we run an un-minimize
2502 // animation at the same time.
2503 return !isSplitScreenPrimary || allowSplitScreenPrimaryAnimation;
2504 }
2505
Vishnu Naira2977262018-07-26 13:31:26 -07002506 /**
2507 * Creates a layer to apply crop to an animation.
2508 */
2509 private SurfaceControl createAnimationBoundsLayer(Transaction t) {
2510 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.i(TAG, "Creating animation bounds layer");
2511 final SurfaceControl.Builder builder = makeAnimationLeash()
2512 .setParent(getAnimationLeashParent())
Vishnu Naire86bd982018-11-28 13:23:17 -08002513 .setName(getSurfaceControl() + " - animation-bounds");
Vishnu Naira2977262018-07-26 13:31:26 -07002514 final SurfaceControl boundsLayer = builder.build();
2515 t.show(boundsLayer);
2516 return boundsLayer;
2517 }
2518
Evan Roskyed6767f2018-10-26 17:21:06 -07002519 @Override
2520 Rect getDisplayedBounds() {
2521 final Task task = getTask();
2522 if (task != null) {
2523 final Rect overrideDisplayedBounds = task.getOverrideDisplayedBounds();
2524 if (!overrideDisplayedBounds.isEmpty()) {
2525 return overrideDisplayedBounds;
2526 }
2527 }
2528 return getBounds();
2529 }
2530
Evan Rosky641daea2019-04-24 14:45:24 -07002531 @VisibleForTesting
2532 Rect getAnimationBounds(int appStackClipMode) {
2533 if (appStackClipMode == STACK_CLIP_BEFORE_ANIM && getStack() != null) {
2534 // Using the stack bounds here effectively applies the clipping before animation.
2535 return getStack().getBounds();
2536 }
2537 // Use task-bounds if available so that activity-level letterbox (maxAspectRatio) is
2538 // included in the animation.
2539 return getTask() != null ? getTask().getBounds() : getBounds();
2540 }
2541
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002542 boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter,
2543 boolean isVoiceInteraction) {
2544
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002545 if (mWmService.mDisableTransitionAnimation || !shouldAnimate(transit)) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002546 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
Jorim Jaggic6976f02018-04-18 16:31:07 +02002547 Slog.v(TAG_WM, "applyAnimation: transition animation is disabled or skipped."
2548 + " atoken=" + this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002549 }
2550 cancelAnimation();
2551 return false;
2552 }
2553
2554 // Only apply an animation if the display isn't frozen. If it is frozen, there is no reason
2555 // to animate and it can cause strange artifacts when we unfreeze the display if some
2556 // different animation is running.
2557 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#applyAnimationLocked");
2558 if (okToAnimate()) {
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002559 final AnimationAdapter adapter;
Evan Rosky2289ba12018-11-19 18:28:18 -08002560 AnimationAdapter thumbnailAdapter = null;
Evan Rosky4fb1e912019-03-06 13:54:43 -08002561
Evan Rosky641daea2019-04-24 14:45:24 -07002562 final int appStackClipMode =
2563 getDisplayContent().mAppTransition.getAppStackClipMode();
2564
2565 // Separate position and size for use in animators.
2566 mTmpRect.set(getAnimationBounds(appStackClipMode));
Evan Rosky4fb1e912019-03-06 13:54:43 -08002567 mTmpPoint.set(mTmpRect.left, mTmpRect.top);
2568 mTmpRect.offsetTo(0, 0);
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002569
Evan Roskyec9488c2019-03-01 19:32:12 -08002570 final boolean isChanging = AppTransition.isChangeTransit(transit) && enter
2571 && getDisplayContent().mChangingApps.contains(this);
Evan Rosky2289ba12018-11-19 18:28:18 -08002572
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002573 // Delaying animation start isn't compatible with remote animations at all.
lumark588a3e82018-07-20 18:53:54 +08002574 if (getDisplayContent().mAppTransition.getRemoteAnimationController() != null
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002575 && !mSurfaceAnimator.isAnimationStartDelayed()) {
Evan Rosky2289ba12018-11-19 18:28:18 -08002576 RemoteAnimationRecord adapters =
2577 getDisplayContent().mAppTransition.getRemoteAnimationController()
2578 .createRemoteAnimationRecord(this, mTmpPoint, mTmpRect,
2579 (isChanging ? mTransitStartRect : null));
2580 adapter = adapters.mAdapter;
2581 thumbnailAdapter = adapters.mThumbnailAdapter;
2582 } else if (isChanging) {
Evan Roskycf76bed2019-01-15 10:33:58 -08002583 final float durationScale = mWmService.getTransitionAnimationScaleLocked();
Evan Rosky2289ba12018-11-19 18:28:18 -08002584 mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y);
2585 adapter = new LocalAnimationAdapter(
2586 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
Evan Roskycf76bed2019-01-15 10:33:58 -08002587 getDisplayContent().getDisplayInfo(), durationScale,
Evan Rosky2289ba12018-11-19 18:28:18 -08002588 true /* isAppAnimation */, false /* isThumbnail */),
2589 mWmService.mSurfaceAnimationRunner);
Evan Rosky966759f2019-01-15 10:33:58 -08002590 if (mThumbnail != null) {
2591 thumbnailAdapter = new LocalAnimationAdapter(
2592 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
Evan Roskycf76bed2019-01-15 10:33:58 -08002593 getDisplayContent().getDisplayInfo(), durationScale,
Evan Rosky966759f2019-01-15 10:33:58 -08002594 true /* isAppAnimation */, true /* isThumbnail */),
2595 mWmService.mSurfaceAnimationRunner);
2596 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002597 mTransit = transit;
2598 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002599 } else {
Vishnu Naira2977262018-07-26 13:31:26 -07002600 mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM);
2601
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002602 final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
2603 if (a != null) {
Lucas Dupin95acf432019-04-29 17:55:38 -07002604 // Only apply corner radius to animation if we're not in multi window mode.
2605 // We don't want rounded corners when in pip or split screen.
2606 final float windowCornerRadius = !inMultiWindowMode()
2607 ? getDisplayContent().getWindowCornerRadius()
2608 : 0;
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002609 adapter = new LocalAnimationAdapter(
2610 new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
lumark588a3e82018-07-20 18:53:54 +08002611 getDisplayContent().mAppTransition.canSkipFirstFrame(),
Vishnu Naira2977262018-07-26 13:31:26 -07002612 appStackClipMode,
Lucas Dupin3e1dc202018-12-02 15:14:20 -08002613 true /* isAppAnimation */,
Lucas Dupin95acf432019-04-29 17:55:38 -07002614 windowCornerRadius),
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002615 mWmService.mSurfaceAnimationRunner);
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002616 if (a.getZAdjustment() == Animation.ZORDER_TOP) {
2617 mNeedsZBoost = true;
2618 }
2619 mTransit = transit;
lumark588a3e82018-07-20 18:53:54 +08002620 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002621 } else {
2622 adapter = null;
chaviw23ee71c2017-12-18 11:29:41 -08002623 }
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002624 }
2625 if (adapter != null) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002626 startAnimation(getPendingTransaction(), adapter, !isVisible());
Jorim Jaggi82c17862018-02-21 17:50:18 +01002627 if (adapter.getShowWallpaper()) {
2628 mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2629 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002630 if (thumbnailAdapter != null) {
2631 mThumbnail.startAnimation(
2632 getPendingTransaction(), thumbnailAdapter, !isVisible());
2633 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002634 }
2635 } else {
2636 cancelAnimation();
2637 }
2638 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2639
2640 return isReallyAnimating();
2641 }
2642
2643 private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
2644 boolean isVoiceInteraction) {
2645 final DisplayContent displayContent = getTask().getDisplayContent();
2646 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2647 final int width = displayInfo.appWidth;
2648 final int height = displayInfo.appHeight;
2649 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG_WM,
2650 "applyAnimation: atoken=" + this);
2651
2652 // Determine the visible rect to calculate the thumbnail clip
2653 final WindowState win = findMainWindow();
2654 final Rect frame = new Rect(0, 0, width, height);
2655 final Rect displayFrame = new Rect(0, 0,
2656 displayInfo.logicalWidth, displayInfo.logicalHeight);
2657 final Rect insets = new Rect();
2658 final Rect stableInsets = new Rect();
2659 Rect surfaceInsets = null;
2660 final boolean freeform = win != null && win.inFreeformWindowingMode();
2661 if (win != null) {
2662 // Containing frame will usually cover the whole screen, including dialog windows.
2663 // For freeform workspace windows it will not cover the whole screen and it also
2664 // won't exactly match the final freeform window frame (e.g. when overlapping with
2665 // the status bar). In that case we need to use the final frame.
2666 if (freeform) {
chaviw492139a2018-07-16 16:07:35 -07002667 frame.set(win.getFrameLw());
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002668 } else if (win.isLetterboxedAppWindow()) {
2669 frame.set(getTask().getBounds());
Winson Chungc1674272018-02-21 10:15:17 -08002670 } else if (win.isDockedResizing()) {
2671 // If we are animating while docked resizing, then use the stack bounds as the
2672 // animation target (which will be different than the task bounds)
2673 frame.set(getTask().getParent().getBounds());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002674 } else {
chaviw553b0212018-07-12 13:37:01 -07002675 frame.set(win.getContainingFrame());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002676 }
2677 surfaceInsets = win.getAttrs().surfaceInsets;
Adrian Roos20e07892018-02-23 19:12:01 +01002678 // XXX(b/72757033): These are insets relative to the window frame, but we're really
2679 // interested in the insets relative to the frame we chose in the if-blocks above.
chaviw9c81e632018-07-31 11:17:52 -07002680 win.getContentInsets(insets);
2681 win.getStableInsets(stableInsets);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002682 }
2683
2684 if (mLaunchTaskBehind) {
2685 // Differentiate the two animations. This one which is briefly on the screen
2686 // gets the !enter animation, and the other activity which remains on the
2687 // screen gets the enter animation. Both appear in the mOpeningApps set.
2688 enter = false;
2689 }
2690 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "Loading animation for app transition."
2691 + " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter
2692 + " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets);
2693 final Configuration displayConfig = displayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08002694 final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002695 displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
2696 surfaceInsets, stableInsets, isVoiceInteraction, freeform, getTask().mTaskId);
2697 if (a != null) {
2698 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
2699 final int containingWidth = frame.width();
2700 final int containingHeight = frame.height();
2701 a.initialize(containingWidth, containingHeight, width, height);
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002702 a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002703 }
2704 return a;
2705 }
2706
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002707 @Override
Jorim Jaggi6de61012018-03-19 14:53:23 +01002708 public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
2709 return mAnimatingAppWindowTokenRegistry != null
2710 && mAnimatingAppWindowTokenRegistry.notifyAboutToFinish(
2711 this, endDeferFinishCallback);
2712 }
2713
2714 @Override
lumarkf6f34942019-04-29 16:56:50 +08002715 public void onAnimationLeashLost(Transaction t) {
2716 super.onAnimationLeashLost(t);
Vishnu Naira2977262018-07-26 13:31:26 -07002717 if (mAnimationBoundsLayer != null) {
Robert Carr71200f22019-02-05 09:44:53 -08002718 t.remove(mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002719 mAnimationBoundsLayer = null;
2720 }
2721
Jorim Jaggi6de61012018-03-19 14:53:23 +01002722 if (mAnimatingAppWindowTokenRegistry != null) {
2723 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
2724 }
2725 }
2726
2727 @Override
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002728 protected void setLayer(Transaction t, int layer) {
2729 if (!mSurfaceAnimator.hasLeash()) {
2730 t.setLayer(mSurfaceControl, layer);
2731 }
2732 }
2733
2734 @Override
2735 protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
2736 if (!mSurfaceAnimator.hasLeash()) {
2737 t.setRelativeLayer(mSurfaceControl, relativeTo, layer);
2738 }
2739 }
2740
2741 @Override
2742 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
2743 if (!mSurfaceAnimator.hasLeash()) {
Robert Carr10584fa2019-01-14 15:55:19 -08002744 t.reparent(mSurfaceControl, newParent);
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002745 }
2746 }
2747
2748 @Override
2749 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002750 // The leash is parented to the animation layer. We need to preserve the z-order by using
2751 // the prefix order index, but we boost if necessary.
Robert Carrb9506032018-02-13 13:54:00 -08002752 int layer = 0;
2753 if (!inPinnedWindowingMode()) {
2754 layer = getPrefixOrderIndex();
2755 } else {
2756 // Pinned stacks have animations take place within themselves rather than an animation
2757 // layer so we need to preserve the order relative to the stack (e.g. the order of our
2758 // task/parent).
2759 layer = getParent().getPrefixOrderIndex();
2760 }
2761
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002762 if (mNeedsZBoost) {
2763 layer += Z_BOOST_BASE;
2764 }
Jorim Jaggi9cd99132019-04-24 17:41:35 +02002765 if (!mNeedsAnimationBoundsLayer) {
2766 leash.setLayer(layer);
2767 }
Robert Carr2f8aa392018-01-31 14:46:51 -08002768
2769 final DisplayContent dc = getDisplayContent();
Jorim Jaggibe418292018-03-26 16:14:12 +02002770 dc.assignStackOrdering();
Evan Rosky2289ba12018-11-19 18:28:18 -08002771
2772 if (leash == mTransitChangeLeash) {
2773 // This is a temporary state so skip any animation notifications
2774 return;
2775 } else if (mTransitChangeLeash != null) {
2776 // unparent mTransitChangeLeash for clean-up
Evan Rosky25b56192019-02-06 16:10:56 -08002777 clearChangeLeash(t, false /* cancel */);
Evan Rosky2289ba12018-11-19 18:28:18 -08002778 }
2779
Jorim Jaggi6de61012018-03-19 14:53:23 +01002780 if (mAnimatingAppWindowTokenRegistry != null) {
2781 mAnimatingAppWindowTokenRegistry.notifyStarting(this);
2782 }
Vishnu Naira2977262018-07-26 13:31:26 -07002783
2784 // If the animation needs to be cropped then an animation bounds layer is created as a child
2785 // of the pinned stack or animation layer. The leash is then reparented to this new layer.
2786 if (mNeedsAnimationBoundsLayer) {
Evan Rosky7735d352019-03-18 17:27:27 -07002787 mTmpRect.setEmpty();
2788 final Task task = getTask();
2789 if (getDisplayContent().mAppTransitionController.isTransitWithinTask(
2790 getTransit(), task)) {
2791 task.getBounds(mTmpRect);
2792 } else {
2793 final TaskStack stack = getStack();
2794 if (stack == null) {
2795 return;
2796 }
2797 // Set clip rect to stack bounds.
2798 stack.getBounds(mTmpRect);
Vishnu Naira2977262018-07-26 13:31:26 -07002799 }
2800 mAnimationBoundsLayer = createAnimationBoundsLayer(t);
2801
Vishnu Naira2977262018-07-26 13:31:26 -07002802 // Crop to stack bounds.
2803 t.setWindowCrop(mAnimationBoundsLayer, mTmpRect);
Jorim Jaggi9cd99132019-04-24 17:41:35 +02002804 t.setLayer(mAnimationBoundsLayer, layer);
Vishnu Naira2977262018-07-26 13:31:26 -07002805
2806 // Reparent leash to animation bounds layer.
Robert Carr10584fa2019-01-14 15:55:19 -08002807 t.reparent(leash, mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002808 }
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002809 }
2810
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002811 /**
2812 * This must be called while inside a transaction.
2813 */
2814 void showAllWindowsLocked() {
2815 forAllWindows(windowState -> {
2816 if (DEBUG_VISIBILITY) Slog.v(TAG, "performing show on: " + windowState);
2817 windowState.performShowLocked();
2818 }, false /* traverseTopToBottom */);
Jorim Jaggia5e10572017-11-15 14:36:26 +01002819 }
2820
2821 @Override
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002822 protected void onAnimationFinished() {
2823 super.onAnimationFinished();
2824
Ian8b2822e2019-05-14 11:59:02 -07002825 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#onAnimationFinished");
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002826 mTransit = TRANSIT_UNSET;
2827 mTransitFlags = 0;
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002828 mNeedsZBoost = false;
Vishnu Naira2977262018-07-26 13:31:26 -07002829 mNeedsAnimationBoundsLayer = false;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002830
2831 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER,
2832 "AppWindowToken");
2833
Jorim Jaggi988f6682017-11-17 17:46:43 +01002834 clearThumbnail();
Jorim Jaggi752cd822018-03-29 16:29:18 +02002835 setClientHidden(isHidden() && hiddenRequested);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002836
lumarkff0ab692018-11-05 20:32:30 +08002837 getDisplayContent().computeImeTargetIfNeeded(this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002838
2839 if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + this
2840 + ": reportedVisible=" + reportedVisible
2841 + " okToDisplay=" + okToDisplay()
2842 + " okToAnimate=" + okToAnimate()
2843 + " startingDisplayed=" + startingDisplayed);
2844
Evan Rosky2289ba12018-11-19 18:28:18 -08002845 // clean up thumbnail window
2846 if (mThumbnail != null) {
2847 mThumbnail.destroy();
2848 mThumbnail = null;
2849 }
2850
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002851 // WindowState.onExitAnimationDone might modify the children list, so make a copy and then
2852 // traverse the copy.
2853 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
2854 children.forEach(WindowState::onExitAnimationDone);
2855
lumark588a3e82018-07-20 18:53:54 +08002856 getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002857 scheduleAnimation();
Jorim Jaggi9b5e3312019-03-01 18:08:00 +01002858
2859 mActivityRecord.onAnimationFinished();
Ian8b2822e2019-05-14 11:59:02 -07002860 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002861 }
2862
2863 @Override
2864 boolean isAppAnimating() {
2865 return isSelfAnimating();
2866 }
2867
2868 @Override
2869 boolean isSelfAnimating() {
2870 // If we are about to start a transition, we also need to be considered animating.
2871 return isWaitingForTransitionStart() || isReallyAnimating();
2872 }
2873
2874 /**
2875 * @return True if and only if we are actually running an animation. Note that
2876 * {@link #isSelfAnimating} also returns true if we are waiting for an animation to
2877 * start.
2878 */
2879 private boolean isReallyAnimating() {
2880 return super.isSelfAnimating();
2881 }
2882
Evan Rosky25b56192019-02-06 16:10:56 -08002883 /**
2884 * @param cancel {@code true} if clearing the leash due to cancelling instead of transferring
2885 * to another leash.
2886 */
2887 private void clearChangeLeash(Transaction t, boolean cancel) {
2888 if (mTransitChangeLeash == null) {
2889 return;
2890 }
2891 if (cancel) {
2892 clearThumbnail();
2893 SurfaceControl sc = getSurfaceControl();
2894 SurfaceControl parentSc = getParentSurfaceControl();
2895 // Don't reparent if surface is getting destroyed
2896 if (parentSc != null && sc != null) {
2897 t.reparent(sc, getParentSurfaceControl());
2898 }
2899 }
2900 t.hide(mTransitChangeLeash);
Evan Rosky08e20932019-05-14 10:54:07 -07002901 t.remove(mTransitChangeLeash);
Evan Rosky25b56192019-02-06 16:10:56 -08002902 mTransitChangeLeash = null;
2903 if (cancel) {
lumarkf6f34942019-04-29 16:56:50 +08002904 onAnimationLeashLost(t);
Evan Rosky25b56192019-02-06 16:10:56 -08002905 }
2906 }
2907
Jorim Jaggi988f6682017-11-17 17:46:43 +01002908 @Override
2909 void cancelAnimation() {
Evan Rosky2289ba12018-11-19 18:28:18 -08002910 cancelAnimationOnly();
Jorim Jaggi988f6682017-11-17 17:46:43 +01002911 clearThumbnail();
Evan Rosky25b56192019-02-06 16:10:56 -08002912 clearChangeLeash(getPendingTransaction(), true /* cancel */);
Evan Rosky2289ba12018-11-19 18:28:18 -08002913 }
2914
2915 /**
2916 * This only cancels the animation. It doesn't do other teardown like cleaning-up thumbnail
2917 * or interim leashes.
2918 * <p>
2919 * Used when canceling in preparation for starting a new animation.
2920 */
2921 void cancelAnimationOnly() {
2922 super.cancelAnimation();
Jorim Jaggi988f6682017-11-17 17:46:43 +01002923 }
2924
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002925 boolean isWaitingForTransitionStart() {
lumark588a3e82018-07-20 18:53:54 +08002926 return getDisplayContent().mAppTransition.isTransitionSet()
2927 && (getDisplayContent().mOpeningApps.contains(this)
Evan Rosky2289ba12018-11-19 18:28:18 -08002928 || getDisplayContent().mClosingApps.contains(this)
2929 || getDisplayContent().mChangingApps.contains(this));
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002930 }
2931
2932 public int getTransit() {
2933 return mTransit;
2934 }
2935
2936 int getTransitFlags() {
2937 return mTransitFlags;
2938 }
2939
Jorim Jaggi988f6682017-11-17 17:46:43 +01002940 void attachThumbnailAnimation() {
2941 if (!isReallyAnimating()) {
2942 return;
2943 }
2944 final int taskId = getTask().mTaskId;
2945 final GraphicBuffer thumbnailHeader =
lumark588a3e82018-07-20 18:53:54 +08002946 getDisplayContent().mAppTransition.getAppTransitionThumbnailHeader(taskId);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002947 if (thumbnailHeader == null) {
2948 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG, "No thumbnail header bitmap for: " + taskId);
2949 return;
2950 }
2951 clearThumbnail();
2952 mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnailHeader);
2953 mThumbnail.startAnimation(getPendingTransaction(), loadThumbnailAnimation(thumbnailHeader));
2954 }
2955
Tony Mak64b8d562017-12-28 17:44:02 +00002956 /**
2957 * Attaches a surface with a thumbnail for the
2958 * {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation.
2959 */
2960 void attachCrossProfileAppsThumbnailAnimation() {
2961 if (!isReallyAnimating()) {
2962 return;
2963 }
2964 clearThumbnail();
2965
2966 final WindowState win = findMainWindow();
2967 if (win == null) {
2968 return;
2969 }
chaviw492139a2018-07-16 16:07:35 -07002970 final Rect frame = win.getFrameLw();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002971 final int thumbnailDrawableRes = getTask().mUserId == mWmService.mCurrentUserId
Tony Mak64b8d562017-12-28 17:44:02 +00002972 ? R.drawable.ic_account_circle
Tony Makda4af232018-04-27 11:01:10 +01002973 : R.drawable.ic_corp_badge;
Tony Mak64b8d562017-12-28 17:44:02 +00002974 final GraphicBuffer thumbnail =
lumark588a3e82018-07-20 18:53:54 +08002975 getDisplayContent().mAppTransition
Tony Mak64b8d562017-12-28 17:44:02 +00002976 .createCrossProfileAppsThumbnail(thumbnailDrawableRes, frame);
2977 if (thumbnail == null) {
2978 return;
2979 }
2980 mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnail);
2981 final Animation animation =
lumark588a3e82018-07-20 18:53:54 +08002982 getDisplayContent().mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(
chaviw492139a2018-07-16 16:07:35 -07002983 win.getFrameLw());
Tony Mak64b8d562017-12-28 17:44:02 +00002984 mThumbnail.startAnimation(getPendingTransaction(), animation, new Point(frame.left,
2985 frame.top));
2986 }
2987
Jorim Jaggi988f6682017-11-17 17:46:43 +01002988 private Animation loadThumbnailAnimation(GraphicBuffer thumbnailHeader) {
2989 final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
2990
2991 // If this is a multi-window scenario, we use the windows frame as
2992 // destination of the thumbnail header animation. If this is a full screen
2993 // window scenario, we use the whole display as the target.
2994 WindowState win = findMainWindow();
2995 Rect appRect = win != null ? win.getContentFrameLw() :
2996 new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
chaviw9c81e632018-07-31 11:17:52 -07002997 final Rect insets = win != null ? win.getContentInsets() : null;
Jorim Jaggi988f6682017-11-17 17:46:43 +01002998 final Configuration displayConfig = mDisplayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08002999 return getDisplayContent().mAppTransition.createThumbnailAspectScaleAnimationLocked(
Jorim Jaggi988f6682017-11-17 17:46:43 +01003000 appRect, insets, thumbnailHeader, getTask().mTaskId, displayConfig.uiMode,
3001 displayConfig.orientation);
3002 }
3003
3004 private void clearThumbnail() {
3005 if (mThumbnail == null) {
3006 return;
3007 }
3008 mThumbnail.destroy();
3009 mThumbnail = null;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003010 }
3011
Jorim Jaggif84e2f62018-01-16 14:17:59 +01003012 void registerRemoteAnimations(RemoteAnimationDefinition definition) {
3013 mRemoteAnimationDefinition = definition;
3014 }
3015
3016 RemoteAnimationDefinition getRemoteAnimationDefinition() {
3017 return mRemoteAnimationDefinition;
3018 }
3019
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003020 @Override
3021 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
3022 super.dump(pw, prefix, dumpAll);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003023 if (appToken != null) {
Wale Ogunwale72919d22016-12-08 18:58:50 -08003024 pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003025 }
Winson Chung48b25652018-10-22 14:04:30 -07003026 pw.println(prefix + "component=" + mActivityComponent.flattenToShortString());
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08003027 pw.print(prefix); pw.print("task="); pw.println(getTask());
Wale Ogunwale51362492016-09-08 17:49:17 -07003028 pw.print(prefix); pw.print(" mFillsParent="); pw.print(mFillsParent);
3029 pw.print(" mOrientation="); pw.println(mOrientation);
Wale Ogunwale89973222017-04-23 18:39:45 -07003030 pw.println(prefix + "hiddenRequested=" + hiddenRequested + " mClientHidden=" + mClientHidden
3031 + ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "")
3032 + " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible);
Craig Mautner59431632012-04-04 11:56:44 -07003033 if (paused) {
3034 pw.print(prefix); pw.print("paused="); pw.println(paused);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003035 }
Wale Ogunwale9017ec02016-02-25 08:55:25 -08003036 if (mAppStopped) {
3037 pw.print(prefix); pw.print("mAppStopped="); pw.println(mAppStopped);
3038 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07003039 if (mNumInterestingWindows != 0 || mNumDrawnWindows != 0
Jorim Jaggib0fc8172017-11-23 17:04:08 +00003040 || allDrawn || mLastAllDrawn) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07003041 pw.print(prefix); pw.print("mNumInterestingWindows=");
3042 pw.print(mNumInterestingWindows);
3043 pw.print(" mNumDrawnWindows="); pw.print(mNumDrawnWindows);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003044 pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
Craig Mautner6fbda632012-07-03 09:26:39 -07003045 pw.print(" allDrawn="); pw.print(allDrawn);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00003046 pw.print(" lastAllDrawn="); pw.print(mLastAllDrawn);
Craig Mautner6fbda632012-07-03 09:26:39 -07003047 pw.println(")");
3048 }
3049 if (inPendingTransaction) {
3050 pw.print(prefix); pw.print("inPendingTransaction=");
3051 pw.println(inPendingTransaction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003052 }
chaviwa8f07a72019-05-01 16:25:39 -07003053 if (mStartingData != null || removed || firstWindowDrawn || mIsExiting) {
3054 pw.print(prefix); pw.print("startingData="); pw.print(mStartingData);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003055 pw.print(" removed="); pw.print(removed);
Craig Mautner3d7ca312015-01-08 10:56:00 -08003056 pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
Craig Mautner799bc1d2015-01-14 10:33:48 -08003057 pw.print(" mIsExiting="); pw.println(mIsExiting);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003058 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08003059 if (startingWindow != null || startingSurface != null
Wale Ogunwale6c459212017-05-17 08:56:03 -07003060 || startingDisplayed || startingMoved || mHiddenSetFromTransferredStartingWindow) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003061 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08003062 pw.print(" startingSurface="); pw.print(startingSurface);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003063 pw.print(" startingDisplayed="); pw.print(startingDisplayed);
Wale Ogunwale6c459212017-05-17 08:56:03 -07003064 pw.print(" startingMoved="); pw.print(startingMoved);
3065 pw.println(" mHiddenSetFromTransferredStartingWindow="
3066 + mHiddenSetFromTransferredStartingWindow);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003067 }
Jorim Jaggi0429f352015-12-22 16:29:16 +01003068 if (!mFrozenBounds.isEmpty()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08003069 pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
Jorim Jaggi26c8c422016-05-09 19:57:25 -07003070 pw.print(prefix); pw.print("mFrozenMergedConfig="); pw.println(mFrozenMergedConfig);
Chong Zhangd78ddb42016-03-02 17:01:14 -08003071 }
3072 if (mPendingRelaunchCount != 0) {
3073 pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount);
Jorim Jaggi0429f352015-12-22 16:29:16 +01003074 }
Riddle Hsub398da32019-01-21 21:48:16 +08003075 if (mSizeCompatScale != 1f || mSizeCompatBounds != null) {
3076 pw.println(prefix + "mSizeCompatScale=" + mSizeCompatScale + " mSizeCompatBounds="
3077 + mSizeCompatBounds);
3078 }
Wale Ogunwalee287e192017-04-21 09:30:12 -07003079 if (mRemovingFromDisplay) {
3080 pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay);
3081 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003082 }
3083
3084 @Override
3085 void setHidden(boolean hidden) {
3086 super.setHidden(hidden);
Winson Chunge55c0192017-08-24 14:50:48 -07003087
3088 if (hidden) {
3089 // Once the app window is hidden, reset the last saved PiP snap fraction
3090 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(this);
3091 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003092 scheduleAnimation();
3093 }
3094
3095 @Override
3096 void prepareSurfaces() {
3097 // isSelfAnimating also returns true when we are about to start a transition, so we need
3098 // to check super here.
3099 final boolean reallyAnimating = super.isSelfAnimating();
3100 final boolean show = !isHidden() || reallyAnimating;
Robert Carrd8e4fb72019-01-31 11:14:30 -08003101
3102 if (mSurfaceControl != null) {
3103 if (show && !mLastSurfaceShowing) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003104 getPendingTransaction().show(mSurfaceControl);
Robert Carrd8e4fb72019-01-31 11:14:30 -08003105 } else if (!show && mLastSurfaceShowing) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003106 getPendingTransaction().hide(mSurfaceControl);
Robert Carrd8e4fb72019-01-31 11:14:30 -08003107 }
Jorim Jaggi4d1835d2017-08-31 17:28:27 +02003108 }
Jorim Jaggi988f6682017-11-17 17:46:43 +01003109 if (mThumbnail != null) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003110 mThumbnail.setShowing(getPendingTransaction(), show);
Jorim Jaggi988f6682017-11-17 17:46:43 +01003111 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003112 mLastSurfaceShowing = show;
3113 super.prepareSurfaces();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003114 }
3115
Jorim Jaggi77d0f36c2018-03-16 17:49:49 +01003116 /**
3117 * @return Whether our {@link #getSurfaceControl} is currently showing.
3118 */
3119 boolean isSurfaceShowing() {
3120 return mLastSurfaceShowing;
3121 }
3122
Jorim Jaggib0fc8172017-11-23 17:04:08 +00003123 boolean isFreezingScreen() {
3124 return mFreezingScreen;
3125 }
3126
3127 @Override
3128 boolean needsZBoost() {
3129 return mNeedsZBoost || super.needsZBoost();
3130 }
3131
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07003132 @CallSuper
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003133 @Override
Nataniel Borges023ecb52019-01-16 14:15:43 -08003134 public void writeToProto(ProtoOutputStream proto, long fieldId,
3135 @WindowTraceLogLevel int logLevel) {
3136 // Critical log level logs only visible elements to mitigate performance overheard
3137 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
3138 return;
3139 }
3140
Steven Timotiusaf03df62017-07-18 16:56:43 -07003141 final long token = proto.start(fieldId);
3142 writeNameToProto(proto, NAME);
Nataniel Borges023ecb52019-01-16 14:15:43 -08003143 super.writeToProto(proto, WINDOW_TOKEN, logLevel);
Vishnu Nair04ab4392018-01-10 11:00:06 -08003144 proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing);
3145 proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart());
3146 proto.write(IS_REALLY_ANIMATING, isReallyAnimating());
3147 if (mThumbnail != null){
3148 mThumbnail.writeToProto(proto, THUMBNAIL);
3149 }
3150 proto.write(FILLS_PARENT, mFillsParent);
3151 proto.write(APP_STOPPED, mAppStopped);
3152 proto.write(HIDDEN_REQUESTED, hiddenRequested);
3153 proto.write(CLIENT_HIDDEN, mClientHidden);
3154 proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient);
3155 proto.write(REPORTED_DRAWN, reportedDrawn);
3156 proto.write(REPORTED_VISIBLE, reportedVisible);
3157 proto.write(NUM_INTERESTING_WINDOWS, mNumInterestingWindows);
3158 proto.write(NUM_DRAWN_WINDOWS, mNumDrawnWindows);
3159 proto.write(ALL_DRAWN, allDrawn);
3160 proto.write(LAST_ALL_DRAWN, mLastAllDrawn);
3161 proto.write(REMOVED, removed);
Nataniel Borges023ecb52019-01-16 14:15:43 -08003162 if (startingWindow != null) {
Vishnu Nair04ab4392018-01-10 11:00:06 -08003163 startingWindow.writeIdentifierToProto(proto, STARTING_WINDOW);
3164 }
3165 proto.write(STARTING_DISPLAYED, startingDisplayed);
3166 proto.write(STARTING_MOVED, startingMoved);
3167 proto.write(HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW,
3168 mHiddenSetFromTransferredStartingWindow);
3169 for (Rect bounds : mFrozenBounds) {
3170 bounds.writeToProto(proto, FROZEN_BOUNDS);
3171 }
Steven Timotiusaf03df62017-07-18 16:56:43 -07003172 proto.end(token);
3173 }
3174
3175 void writeNameToProto(ProtoOutputStream proto, long fieldId) {
3176 if (appToken == null) {
3177 return;
3178 }
3179 try {
3180 proto.write(fieldId, appToken.getName());
3181 } catch (RemoteException e) {
3182 // This shouldn't happen, but in this case fall back to outputting nothing
3183 Slog.e(TAG, e.toString());
3184 }
3185 }
3186
3187 @Override
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003188 public String toString() {
3189 if (stringName == null) {
3190 StringBuilder sb = new StringBuilder();
3191 sb.append("AppWindowToken{");
3192 sb.append(Integer.toHexString(System.identityHashCode(this)));
3193 sb.append(" token="); sb.append(token); sb.append('}');
3194 stringName = sb.toString();
3195 }
Wale Ogunwaleba51ca22016-09-23 06:06:54 -07003196 return stringName + ((mIsExiting) ? " mIsExiting=" : "");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003197 }
Adrian Roos20e07892018-02-23 19:12:01 +01003198
3199 Rect getLetterboxInsets() {
3200 if (mLetterbox != null) {
3201 return mLetterbox.getInsets();
3202 } else {
3203 return new Rect();
3204 }
3205 }
Adrian Roos23df3a32018-03-15 15:41:13 +01003206
Riddle Hsu69de5fb2019-02-23 01:19:50 +08003207 /** Gets the inner bounds of letterbox. The bounds will be empty if there is no letterbox. */
3208 void getLetterboxInnerBounds(Rect outBounds) {
3209 if (mLetterbox != null) {
3210 outBounds.set(mLetterbox.getInnerFrame());
3211 } else {
3212 outBounds.setEmpty();
3213 }
3214 }
3215
Adrian Roos23df3a32018-03-15 15:41:13 +01003216 /**
Riddle Hsu69de5fb2019-02-23 01:19:50 +08003217 * @return {@code true} if there is a letterbox and any part of that letterbox overlaps with
Adrian Roos23df3a32018-03-15 15:41:13 +01003218 * the given {@code rect}.
3219 */
3220 boolean isLetterboxOverlappingWith(Rect rect) {
3221 return mLetterbox != null && mLetterbox.isOverlappingWith(rect);
3222 }
chaviw4ad54912018-05-30 11:05:44 -07003223
3224 /**
3225 * Sets if this AWT is in the process of closing or entering PIP.
3226 * {@link #mWillCloseOrEnterPip}}
3227 */
3228 void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
3229 mWillCloseOrEnterPip = willCloseOrEnterPip;
3230 }
3231
3232 /**
3233 * Returns whether this AWT is considered closing. Conditions are either
3234 * 1. Is this app animating and was requested to be hidden
3235 * 2. App is delayed closing since it might enter PIP.
3236 */
3237 boolean isClosingOrEnteringPip() {
3238 return (isAnimating() && hiddenRequested) || mWillCloseOrEnterPip;
3239 }
Jorim Jaggiaf0d6d22018-06-08 15:25:35 +02003240
3241 /**
3242 * @return Whether we are allowed to show non-starting windows at the moment. We disallow
3243 * showing windows during transitions in case we have windows that have wide-color-gamut
3244 * color mode set to avoid jank in the middle of the transition.
3245 */
3246 boolean canShowWindows() {
3247 return allDrawn && !(isReallyAnimating() && hasNonDefaultColorWindow());
3248 }
3249
3250 /**
3251 * @return true if we have a window that has a non-default color mode set; false otherwise.
3252 */
3253 private boolean hasNonDefaultColorWindow() {
3254 return forAllWindows(ws -> ws.mAttrs.getColorMode() != COLOR_MODE_DEFAULT,
3255 true /* topToBottom */);
3256 }
lumark588a3e82018-07-20 18:53:54 +08003257
chaviwdcf76ec2019-01-11 16:48:46 -08003258 private void updateColorTransform() {
3259 if (mSurfaceControl != null && mLastAppSaturationInfo != null) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003260 getPendingTransaction().setColorTransform(mSurfaceControl,
3261 mLastAppSaturationInfo.mMatrix, mLastAppSaturationInfo.mTranslation);
chaviwdcf76ec2019-01-11 16:48:46 -08003262 mWmService.scheduleAnimationLocked();
3263 }
3264 }
3265
3266 private static class AppSaturationInfo {
3267 float[] mMatrix = new float[9];
3268 float[] mTranslation = new float[3];
3269
3270 void setSaturation(@Size(9) float[] matrix, @Size(3) float[] translation) {
3271 System.arraycopy(matrix, 0, mMatrix, 0, mMatrix.length);
3272 System.arraycopy(translation, 0, mTranslation, 0, mTranslation.length);
3273 }
3274 }
Jeff Browne9bdb312012-04-05 15:30:10 -07003275}