blob: 6c577e150e54d3db3d73b9c8dcb0211fd9f4d736 [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.
chaviwa8f07a72019-05-01 16:25:39 -0700209 StartingData mStartingData;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800210 WindowState startingWindow;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800211 StartingSurface startingSurface;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800212 boolean startingDisplayed;
213 boolean startingMoved;
Jorim Jaggi60f9c972018-02-01 19:21:07 +0100214
Wale Ogunwale6c459212017-05-17 08:56:03 -0700215 // True if the hidden state of this token was forced to false due to a transferred starting
216 // window.
217 private boolean mHiddenSetFromTransferredStartingWindow;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800218 boolean firstWindowDrawn;
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700219 private final WindowState.UpdateReportedVisibilityResults mReportedVisibilityResults =
220 new WindowState.UpdateReportedVisibilityResults();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800221
222 // Input application handle used by the input dispatcher.
Jeff Brown9302c872011-07-13 22:51:29 -0700223 final InputApplicationHandle mInputApplicationHandle;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800224
Wale Ogunwale571771c2016-08-26 13:18:50 -0700225 // TODO: Have a WindowContainer state for tracking exiting/deferred removal.
Craig Mautner799bc1d2015-01-14 10:33:48 -0800226 boolean mIsExiting;
Craig Mautner9ef471f2014-02-07 13:11:47 -0800227
Craig Mautnerbb742462014-07-07 15:28:55 -0700228 boolean mLaunchTaskBehind;
Craig Mautner8746a472014-07-24 15:12:54 -0700229 boolean mEnteringAnimation;
Craig Mautnerbb742462014-07-07 15:28:55 -0700230
Wale Ogunwale72919d22016-12-08 18:58:50 -0800231 private boolean mAlwaysFocusable;
Wale Ogunwale6cae7652015-12-26 07:36:26 -0800232
Robert Carre12aece2016-02-02 22:43:27 -0800233 boolean mAppStopped;
Robert Carrfd10cd12016-06-29 16:41:50 -0700234 int mRotationAnimationHint;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700235 private int mPendingRelaunchCount;
Robert Carre12aece2016-02-02 22:43:27 -0800236
Jorim Jaggife762342016-10-13 14:33:27 +0200237 private boolean mLastContainsShowWhenLockedWindow;
238 private boolean mLastContainsDismissKeyguardWindow;
239
Jorim Jaggi0429f352015-12-22 16:29:16 +0100240 ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
Jorim Jaggi26c8c422016-05-09 19:57:25 -0700241 ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
Jorim Jaggi0429f352015-12-22 16:29:16 +0100242
Riddle Hsub398da32019-01-21 21:48:16 +0800243 /**
244 * The scale to fit at least one side of the activity to its parent. If the activity uses
245 * 1920x1080, and the actually size on the screen is 960x540, then the scale is 0.5.
246 */
247 private float mSizeCompatScale = 1f;
248 /**
249 * The bounds in global coordinates for activity in size compatibility mode.
250 * @see ActivityRecord#inSizeCompatMode
251 */
252 private Rect mSizeCompatBounds;
253
Wale Ogunwale6c459212017-05-17 08:56:03 -0700254 private boolean mDisablePreviewScreenshots;
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +0100255
Wale Ogunwale034a8ec2017-09-02 17:14:40 -0700256 private Task mLastParent;
Robert Carred3e83b2017-04-21 13:26:55 -0700257
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800258 // TODO: Remove after unification
259 ActivityRecord mActivityRecord;
260
chaviwd3bf08d2017-08-01 17:24:59 -0700261 /**
262 * See {@link #canTurnScreenOn()}
263 */
264 private boolean mCanTurnScreenOn = true;
265
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200266 /**
267 * If we are running an animation, this determines the transition type. Must be one of
268 * AppTransition.TRANSIT_* constants.
269 */
270 private int mTransit;
271
272 /**
273 * If we are running an animation, this determines the flags during this animation. Must be a
274 * bitwise combination of AppTransition.TRANSIT_FLAG_* constants.
275 */
276 private int mTransitFlags;
277
278 /** Whether our surface was set to be showing in the last call to {@link #prepareSurfaces} */
Jorim Jaggifd1891462017-12-29 15:41:36 +0100279 private boolean mLastSurfaceShowing = true;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200280
Evan Rosky2289ba12018-11-19 18:28:18 -0800281 /**
282 * This gets used during some open/close transitions as well as during a change transition
283 * where it represents the starting-state snapshot.
284 */
Jorim Jaggi988f6682017-11-17 17:46:43 +0100285 private AppWindowThumbnail mThumbnail;
Evan Rosky2289ba12018-11-19 18:28:18 -0800286 private final Rect mTransitStartRect = new Rect();
287
288 /**
289 * This leash is used to "freeze" the app surface in place after the state change, but before
290 * the animation is ready to start.
291 */
292 private SurfaceControl mTransitChangeLeash = null;
Jorim Jaggi988f6682017-11-17 17:46:43 +0100293
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000294 /** Have we been asked to have this token keep the screen frozen? */
295 private boolean mFreezingScreen;
296
297 /** Whether this token should be boosted at the top of all app window tokens. */
Jorim Jaggi9cd99132019-04-24 17:41:35 +0200298 @VisibleForTesting boolean mNeedsZBoost;
Adrian Roos4d18a2e2017-12-19 19:08:05 +0100299 private Letterbox mLetterbox;
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000300
chaviw23ee71c2017-12-18 11:29:41 -0800301 private final Point mTmpPoint = new Point();
chaviw23012112017-12-20 15:29:04 -0800302 private final Rect mTmpRect = new Rect();
Evan Rosky2289ba12018-11-19 18:28:18 -0800303 private final Rect mTmpPrevBounds = new Rect();
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100304 private RemoteAnimationDefinition mRemoteAnimationDefinition;
Jorim Jaggi6de61012018-03-19 14:53:23 +0100305 private AnimatingAppWindowTokenRegistry mAnimatingAppWindowTokenRegistry;
chaviw23ee71c2017-12-18 11:29:41 -0800306
chaviw4ad54912018-05-30 11:05:44 -0700307 /**
308 * A flag to determine if this AWT is in the process of closing or entering PIP. This is needed
309 * to help AWT know that the app is in the process of closing but hasn't yet started closing on
310 * the WM side.
311 */
312 private boolean mWillCloseOrEnterPip;
313
Vishnu Naira2977262018-07-26 13:31:26 -0700314 /** Layer used to constrain the animation to a token's stack bounds. */
315 SurfaceControl mAnimationBoundsLayer;
316
317 /** Whether this token needs to create mAnimationBoundsLayer for cropping animations. */
318 boolean mNeedsAnimationBoundsLayer;
319
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800320 private static final int STARTING_WINDOW_TYPE_NONE = 0;
321 private static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
322 private static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
323
chaviwdcf76ec2019-01-11 16:48:46 -0800324 private AppSaturationInfo mLastAppSaturationInfo;
325
326 private final ColorDisplayService.ColorTransformController mColorTransformController =
327 (matrix, translation) -> mWmService.mH.post(() -> {
328 synchronized (mWmService.mGlobalLock) {
329 if (mLastAppSaturationInfo == null) {
330 mLastAppSaturationInfo = new AppSaturationInfo();
331 }
332
333 mLastAppSaturationInfo.setSaturation(matrix, translation);
334 updateColorTransform();
335 }
336 });
337
Winson Chung48b25652018-10-22 14:04:30 -0700338 AppWindowToken(WindowManagerService service, IApplicationToken token,
339 ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
340 long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers,
Jorim Jaggi91d382a2019-03-27 17:00:48 +0100341 int targetSdk, int orientation, int rotationAnimationHint,
Winson Chung48b25652018-10-22 14:04:30 -0700342 boolean launchTaskBehind, boolean alwaysFocusable,
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800343 ActivityRecord activityRecord) {
Winson Chung48b25652018-10-22 14:04:30 -0700344 this(service, token, activityComponent, voiceInteraction, dc, fullscreen);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800345 // TODO: remove after unification
346 mActivityRecord = activityRecord;
347 mActivityRecord.registerConfigurationChangeListener(this);
Wale Ogunwale72919d22016-12-08 18:58:50 -0800348 mInputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800349 mShowForAllUsers = showForAllUsers;
350 mTargetSdk = targetSdk;
351 mOrientation = orientation;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800352 mLaunchTaskBehind = launchTaskBehind;
353 mAlwaysFocusable = alwaysFocusable;
354 mRotationAnimationHint = rotationAnimationHint;
355
356 // Application tokens start out hidden.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200357 setHidden(true);
Wale Ogunwale72919d22016-12-08 18:58:50 -0800358 hiddenRequested = true;
chaviwdcf76ec2019-01-11 16:48:46 -0800359
360 ColorDisplayService.ColorDisplayServiceInternal cds = LocalServices.getService(
361 ColorDisplayService.ColorDisplayServiceInternal.class);
362 cds.attachColorTransformController(activityRecord.packageName, activityRecord.mUserId,
363 new WeakReference<>(mColorTransformController));
Wale Ogunwale72919d22016-12-08 18:58:50 -0800364 }
365
Winson Chung48b25652018-10-22 14:04:30 -0700366 AppWindowToken(WindowManagerService service, IApplicationToken token,
367 ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
368 boolean fillsParent) {
Wale Ogunwale5cd907d2017-01-26 14:14:08 -0800369 super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true, dc,
370 false /* ownerCanManageAppTokens */);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700371 appToken = token;
Winson Chung48b25652018-10-22 14:04:30 -0700372 mActivityComponent = activityComponent;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800373 mVoiceInteraction = voiceInteraction;
Wale Ogunwale17f175c2017-02-07 16:54:10 -0800374 mFillsParent = fillsParent;
Robert Carr0bcbe642018-10-11 19:07:43 -0700375 mInputApplicationHandle = new InputApplicationHandle(appToken.asBinder());
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800376 }
377
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800378 void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
379 firstWindowDrawn = true;
380
381 // We now have a good window to show, remove dead placeholders
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700382 removeDeadWindows();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800383
Jorim Jaggi02886a82016-12-06 09:10:06 -0800384 if (startingWindow != null) {
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800385 if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Slog.v(TAG, "Finish starting "
386 + win.mToken + ": first real window is shown, no animation");
387 // If this initial window is animating, stop it -- we will do an animation to reveal
388 // it from behind the starting window, so there is no need for it to also be doing its
389 // own stuff.
Jorim Jaggia5e10572017-11-15 14:36:26 +0100390 win.cancelAnimation();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800391 }
chaviwa8f07a72019-05-01 16:25:39 -0700392 removeStartingWindow();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800393 updateReportedVisibilityLocked();
394 }
395
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800396 void updateReportedVisibilityLocked() {
397 if (appToken == null) {
398 return;
399 }
400
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700401 if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700402 final int count = mChildren.size();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800403
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700404 mReportedVisibilityResults.reset();
405
406 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700407 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700408 win.updateReportedVisibility(mReportedVisibilityResults);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800409 }
410
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700411 int numInteresting = mReportedVisibilityResults.numInteresting;
412 int numVisible = mReportedVisibilityResults.numVisible;
413 int numDrawn = mReportedVisibilityResults.numDrawn;
414 boolean nowGone = mReportedVisibilityResults.nowGone;
415
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700416 boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200417 boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting && !isHidden();
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700418 if (!nowGone) {
419 // If the app is not yet gone, then it can only become visible/drawn.
420 if (!nowDrawn) {
421 nowDrawn = reportedDrawn;
422 }
423 if (!nowVisible) {
424 nowVisible = reportedVisible;
425 }
426 }
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800427 if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800428 + numInteresting + " visible=" + numVisible);
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700429 if (nowDrawn != reportedDrawn) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800430 if (mActivityRecord != null) {
431 mActivityRecord.onWindowsDrawn(nowDrawn, SystemClock.uptimeMillis());
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700432 }
433 reportedDrawn = nowDrawn;
434 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800435 if (nowVisible != reportedVisible) {
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700436 if (DEBUG_VISIBILITY) Slog.v(TAG,
437 "Visibility changed in " + this + ": vis=" + nowVisible);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800438 reportedVisible = nowVisible;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800439 if (mActivityRecord != null) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800440 if (nowVisible) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800441 onWindowsVisible();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800442 } else {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800443 onWindowsGone();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800444 }
445 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800446 }
447 }
448
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800449 private void onWindowsGone() {
450 if (mActivityRecord == null) {
451 return;
452 }
453 if (DEBUG_VISIBILITY) {
454 Slog.v(TAG_WM, "Reporting gone in " + mActivityRecord.appToken);
455 }
456 mActivityRecord.onWindowsGone();
457 }
458
459 private void onWindowsVisible() {
460 if (mActivityRecord == null) {
461 return;
462 }
463 if (DEBUG_VISIBILITY) {
464 Slog.v(TAG_WM, "Reporting visible in " + mActivityRecord.appToken);
465 }
466 mActivityRecord.onWindowsVisible();
467 }
468
Wale Ogunwale89973222017-04-23 18:39:45 -0700469 boolean isClientHidden() {
470 return mClientHidden;
471 }
472
473 void setClientHidden(boolean hideClient) {
474 if (mClientHidden == hideClient || (hideClient && mDeferHidingClient)) {
475 return;
476 }
Jorim Jaggi067b5bf2018-02-23 17:42:39 +0100477 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "setClientHidden: " + this
478 + " clientHidden=" + hideClient + " Callers=" + Debug.getCallers(5));
Wale Ogunwale89973222017-04-23 18:39:45 -0700479 mClientHidden = hideClient;
480 sendAppVisibilityToClients();
481 }
482
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800483 void setVisibility(boolean visible, boolean deferHidingClient) {
484 final AppTransition appTransition = getDisplayContent().mAppTransition;
485
486 // Don't set visibility to false if we were already not visible. This prevents WM from
487 // adding the app to the closing app list which doesn't make sense for something that is
488 // already not visible. However, set visibility to true even if we are already visible.
489 // This makes sure the app is added to the opening apps list so that the right
490 // transition can be selected.
491 // TODO: Probably a good idea to separate the concept of opening/closing apps from the
492 // concept of setting visibility...
493 if (!visible && hiddenRequested) {
494
495 if (!deferHidingClient && mDeferHidingClient) {
496 // We previously deferred telling the client to hide itself when visibility was
497 // initially set to false. Now we would like it to hide, so go ahead and set it.
498 mDeferHidingClient = deferHidingClient;
499 setClientHidden(true);
500 }
501 return;
502 }
503
504 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) {
505 Slog.v(TAG_WM, "setAppVisibility("
506 + appToken + ", visible=" + visible + "): " + appTransition
507 + " hidden=" + isHidden() + " hiddenRequested="
508 + hiddenRequested + " Callers=" + Debug.getCallers(6));
509 }
510
511 final DisplayContent displayContent = getDisplayContent();
512 displayContent.mOpeningApps.remove(this);
513 displayContent.mClosingApps.remove(this);
Evan Roskyb1e75f72019-04-26 20:23:26 -0700514 if (isInChangeTransition()) {
515 clearChangeLeash(getPendingTransaction(), true /* cancel */);
516 }
517 displayContent.mChangingApps.remove(this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800518 waitingToShow = false;
519 hiddenRequested = !visible;
520 mDeferHidingClient = deferHidingClient;
521
522 if (!visible) {
523 // If the app is dead while it was visible, we kept its dead window on screen.
524 // Now that the app is going invisible, we can remove it. It will be restarted
525 // if made visible again.
526 removeDeadWindows();
527 } else {
528 if (!appTransition.isTransitionSet()
529 && appTransition.isReady()) {
530 // Add the app mOpeningApps if transition is unset but ready. This means
531 // we're doing a screen freeze, and the unfreeze will wait for all opening
532 // apps to be ready.
533 displayContent.mOpeningApps.add(this);
534 }
535 startingMoved = false;
536 // If the token is currently hidden (should be the common case), or has been
537 // stopped, then we need to set up to wait for its windows to be ready.
538 if (isHidden() || mAppStopped) {
539 clearAllDrawn();
540
541 // If the app was already visible, don't reset the waitingToShow state.
542 if (isHidden()) {
543 waitingToShow = true;
Jorim Jaggi6ec52d42019-07-03 15:45:59 +0200544
545 // Let's reset the draw state in order to prevent the starting window to be
546 // immediately dismissed when the app still has the surface.
547 forAllWindows(w -> {
548 if (w.mWinAnimator.mDrawState == HAS_DRAWN) {
549 w.mWinAnimator.resetDrawState();
550
551 // Force add to mResizingWindows, so that we are guaranteed to get
552 // another reportDrawn callback.
553 w.resetLastContentInsets();
554 }
555 }, true /* traverseTopToBottom */);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800556 }
557 }
558
559 // In the case where we are making an app visible but holding off for a transition,
560 // we still need to tell the client to make its windows visible so they get drawn.
561 // Otherwise, we will wait on performing the transition until all windows have been
562 // drawn, they never will be, and we are sad.
563 setClientHidden(false);
564
565 requestUpdateWallpaperIfNeeded();
566
567 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "No longer Stopped: " + this);
568 mAppStopped = false;
569
570 transferStartingWindowFromHiddenAboveTokenIfNeeded();
571 }
572
573 // If we are preparing an app transition, then delay changing
574 // the visibility of this token until we execute that transition.
575 if (okToAnimate() && appTransition.isTransitionSet()) {
576 inPendingTransaction = true;
577 if (visible) {
578 displayContent.mOpeningApps.add(this);
579 mEnteringAnimation = true;
580 } else {
581 displayContent.mClosingApps.add(this);
582 mEnteringAnimation = false;
583 }
584 if (appTransition.getAppTransition()
585 == WindowManager.TRANSIT_TASK_OPEN_BEHIND) {
586 // We're launchingBehind, add the launching activity to mOpeningApps.
587 final WindowState win = getDisplayContent().findFocusedWindow();
588 if (win != null) {
589 final AppWindowToken focusedToken = win.mAppToken;
590 if (focusedToken != null) {
591 if (DEBUG_APP_TRANSITIONS) {
592 Slog.d(TAG_WM, "TRANSIT_TASK_OPEN_BEHIND, "
593 + " adding " + focusedToken + " to mOpeningApps");
594 }
595 // Force animation to be loaded.
596 focusedToken.setHidden(true);
597 displayContent.mOpeningApps.add(focusedToken);
598 }
599 }
600 }
Garfield Tanb6776602019-02-20 14:44:26 -0800601 // Changes in opening apps and closing apps may cause orientation change.
602 reportDescendantOrientationChangeIfNeeded();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800603 return;
604 }
605
606 commitVisibility(null, visible, TRANSIT_UNSET, true, mVoiceInteraction);
607 updateReportedVisibilityLocked();
608 }
609
610 boolean commitVisibility(WindowManager.LayoutParams lp,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700611 boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
612
613 boolean delayed = false;
614 inPendingTransaction = false;
Wale Ogunwale9e4721f2017-05-23 19:37:30 -0700615 // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually
616 // been set by the app now.
617 mHiddenSetFromTransferredStartingWindow = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700618
619 // Allow for state changes and animation to be applied if:
620 // * token is transitioning visibility state
621 // * or the token was marked as hidden and is exiting before we had a chance to play the
622 // transition animation
623 // * or this is an opening app and windows are being replaced.
624 boolean visibilityChanged = false;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200625 if (isHidden() == visible || (isHidden() && mIsExiting) || (visible && waitingForReplacement())) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800626 final AccessibilityController accessibilityController =
627 mWmService.mAccessibilityController;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700628 boolean changed = false;
629 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM,
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200630 "Changing app " + this + " hidden=" + isHidden() + " performLayout=" + performLayout);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700631
632 boolean runningAppAnimation = false;
633
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100634 if (transit != WindowManager.TRANSIT_UNSET) {
Tiger Huangc9d0d002019-05-29 22:55:29 +0800635 if (mUseTransferredAnimation) {
636 runningAppAnimation = isReallyAnimating();
637 } else if (applyAnimationLocked(lp, transit, visible, isVoiceInteraction)) {
638 runningAppAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700639 }
Tiger Huangc9d0d002019-05-29 22:55:29 +0800640 delayed = runningAppAnimation;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700641 final WindowState window = findMainWindow();
Rhed Jao02655dc2018-10-30 20:44:52 +0800642 if (window != null && accessibilityController != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700643 accessibilityController.onAppWindowTransitionLocked(window, transit);
644 }
645 changed = true;
646 }
647
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700648 final int windowsCount = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700649 for (int i = 0; i < windowsCount; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700650 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700651 changed |= win.onAppVisibilityChanged(visible, runningAppAnimation);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700652 }
653
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200654 setHidden(!visible);
655 hiddenRequested = !visible;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700656 visibilityChanged = true;
657 if (!visible) {
658 stopFreezingScreen(true, true);
659 } else {
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700660 // If we are being set visible, and the starting window is not yet displayed,
661 // then make sure it doesn't get displayed.
662 if (startingWindow != null && !startingWindow.isDrawnLw()) {
chaviw15ad49f2019-04-24 15:05:39 -0700663 startingWindow.clearPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY);
664 startingWindow.mLegacyPolicyVisibilityAfterAnim = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700665 }
Jorim Jaggi38d44ec2017-06-14 16:04:59 -0700666
667 // We are becoming visible, so better freeze the screen with the windows that are
668 // getting visible so we also wait for them.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800669 forAllWindows(mWmService::makeWindowFreezingScreenIfNeededLocked, true);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700670 }
671
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800672 if (DEBUG_APP_TRANSITIONS) {
673 Slog.v(TAG_WM, "commitVisibility: " + this
674 + ": hidden=" + isHidden() + " hiddenRequested=" + hiddenRequested);
675 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700676
677 if (changed) {
Arthur Hung95b38a92018-07-20 18:56:12 +0800678 getDisplayContent().getInputMonitor().setUpdateInputWindowsNeededLw();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700679 if (performLayout) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800680 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700681 false /*updateInputWindows*/);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800682 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700683 }
Arthur Hung95b38a92018-07-20 18:56:12 +0800684 getDisplayContent().getInputMonitor().updateInputWindowsLw(false /*force*/);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700685 }
686 }
Tiger Huangc9d0d002019-05-29 22:55:29 +0800687 mUseTransferredAnimation = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700688
lumarkd14173e2019-03-27 19:14:33 +0800689 if (isReallyAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700690 delayed = true;
Jorim Jaggiab9fcb22018-03-15 23:46:12 +0100691 } else {
692
693 // We aren't animating anything, but exiting windows rely on the animation finished
694 // callback being called in case the AppWindowToken was pretending to be animating,
695 // which we might have done because we were in closing/opening apps list.
696 onAnimationFinished();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700697 }
698
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700699 for (int i = mChildren.size() - 1; i >= 0 && !delayed; i--) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100700 if ((mChildren.get(i)).isSelfOrChildAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700701 delayed = true;
702 }
703 }
704
705 if (visibilityChanged) {
706 if (visible && !delayed) {
707 // The token was made immediately visible, there will be no entrance animation.
708 // We need to inform the client the enter animation was finished.
709 mEnteringAnimation = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800710 mWmService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(
711 token);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700712 }
Robert Carr61b81112017-07-17 18:08:15 -0700713
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800714 // If we're becoming visible, immediately change client visibility as well. there seem
715 // to be some edge cases where we change our visibility but client visibility never gets
716 // updated.
Jorim Jaggi110839b2018-01-22 12:49:04 +0100717 // If we're becoming invisible, update the client visibility if we are not running an
718 // animation. Otherwise, we'll update client visibility in onAnimationFinished.
Jorim Jaggi3cad57f2018-02-20 18:32:01 +0100719 if (visible || !isReallyAnimating()) {
Jorim Jaggi110839b2018-01-22 12:49:04 +0100720 setClientHidden(!visible);
Jorim Jaggi4876b4a2018-01-11 15:43:49 +0100721 }
722
lumark588a3e82018-07-20 18:53:54 +0800723 if (!getDisplayContent().mClosingApps.contains(this)
724 && !getDisplayContent().mOpeningApps.contains(this)) {
chaviwa953fcf2018-03-01 12:00:39 -0800725 // The token is not closing nor opening, so even if there is an animation set, that
726 // doesn't mean that it goes through the normal app transition cycle so we have
727 // to inform the docked controller about visibility change.
728 // TODO(multi-display): notify docked divider on all displays where visibility was
729 // affected.
lumark588a3e82018-07-20 18:53:54 +0800730 getDisplayContent().getDockedDividerController().notifyAppVisibilityChanged();
chaviwa953fcf2018-03-01 12:00:39 -0800731
732 // Take the screenshot before possibly hiding the WSA, otherwise the screenshot
733 // will not be taken.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800734 mWmService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible);
chaviwa953fcf2018-03-01 12:00:39 -0800735 }
736
Robert Carre7cc44d2017-03-20 19:04:30 -0700737 // If we are hidden but there is no delay needed we immediately
738 // apply the Surface transaction so that the ActivityManager
Robert Carr61b81112017-07-17 18:08:15 -0700739 // can have some guarantee on the Surface state following
740 // setting the visibility. This captures cases like dismissing
741 // the docked or pinned stack where there is no app transition.
742 //
743 // In the case of a "Null" animation, there will be
744 // no animation but there will still be a transition set.
745 // We still need to delay hiding the surface such that it
746 // can be synchronized with showing the next surface in the transition.
lumark588a3e82018-07-20 18:53:54 +0800747 if (isHidden() && !delayed && !getDisplayContent().mAppTransition.isTransitionSet()) {
Robert Carr6914f082017-03-20 19:04:30 -0700748 SurfaceControl.openTransaction();
749 for (int i = mChildren.size() - 1; i >= 0; i--) {
750 mChildren.get(i).mWinAnimator.hide("immediately hidden");
751 }
752 SurfaceControl.closeTransaction();
753 }
Garfield Tanb6776602019-02-20 14:44:26 -0800754
755 // Visibility changes may cause orientation request change.
756 reportDescendantOrientationChangeIfNeeded();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700757 }
758
759 return delayed;
760 }
761
Garfield Tanb6776602019-02-20 14:44:26 -0800762 private void reportDescendantOrientationChangeIfNeeded() {
763 // Orientation request is exposed only when we're visible. Therefore visibility change
764 // will change requested orientation. Notify upward the hierarchy ladder to adjust
765 // configuration. This is important to cases where activities with incompatible
766 // orientations launch, or user goes back from an activity of bi-orientation to an
767 // activity with specified orientation.
768 if (mActivityRecord.getRequestedConfigurationOrientation() == getConfiguration().orientation
769 || getOrientationIgnoreVisibility() == SCREEN_ORIENTATION_UNSET) {
770 return;
771 }
772
773 final IBinder freezeToken =
774 mActivityRecord.mayFreezeScreenLocked(mActivityRecord.app)
775 ? mActivityRecord.appToken : null;
776 onDescendantOrientationChanged(freezeToken, mActivityRecord);
777 }
778
Jorim Jaggi87fdbcb2017-08-17 13:41:11 +0200779 /**
780 * @return The to top most child window for which {@link LayoutParams#isFullscreen()} returns
781 * true.
782 */
783 WindowState getTopFullscreenWindow() {
784 for (int i = mChildren.size() - 1; i >= 0; i--) {
785 final WindowState win = mChildren.get(i);
786 if (win != null && win.mAttrs.isFullscreen()) {
787 return win;
788 }
789 }
790 return null;
791 }
792
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800793 WindowState findMainWindow() {
Matthew Ng53e66b22018-01-12 17:13:13 -0800794 return findMainWindow(true);
795 }
796
797 /**
798 * Finds the main window that either has type base application or application starting if
799 * requested.
800 *
801 * @param includeStartingApp Allow to search application-starting windows to also be returned.
802 * @return The main window of type base application or application starting if requested.
803 */
804 WindowState findMainWindow(boolean includeStartingApp) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700805 WindowState candidate = null;
Matthew Ng53e66b22018-01-12 17:13:13 -0800806 for (int j = mChildren.size() - 1; j >= 0; --j) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700807 final WindowState win = mChildren.get(j);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700808 final int type = win.mAttrs.type;
809 // No need to loop through child window as base application and starting types can't be
810 // child windows.
Matthew Ng53e66b22018-01-12 17:13:13 -0800811 if (type == TYPE_BASE_APPLICATION
812 || (includeStartingApp && type == TYPE_APPLICATION_STARTING)) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700813 // In cases where there are multiple windows, we prefer the non-exiting window. This
Sungsoo Lim0d3d1f82015-12-02 14:47:59 +0900814 // happens for example when replacing windows during an activity relaunch. When
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700815 // constructing the animation, we want the new window, not the exiting one.
Wale Ogunwalec48a3542016-02-19 15:18:45 -0800816 if (win.mAnimatingExit) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700817 candidate = win;
818 } else {
819 return win;
820 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800821 }
822 }
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700823 return candidate;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800824 }
825
Wale Ogunwale6cae7652015-12-26 07:36:26 -0800826 boolean windowsAreFocusable() {
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800827 if (mTargetSdk < Build.VERSION_CODES.Q) {
828 final int pid = mActivityRecord != null
829 ? (mActivityRecord.app != null ? mActivityRecord.app.getPid() : 0) : 0;
830 final AppWindowToken topFocusedAppOfMyProcess =
831 mWmService.mRoot.mTopFocusedAppByProcess.get(pid);
832 if (topFocusedAppOfMyProcess != null && topFocusedAppOfMyProcess != this) {
833 // For the apps below Q, there can be only one app which has the focused window per
834 // process, because legacy apps may not be ready for a multi-focus system.
835 return false;
836 }
837 }
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700838 return getWindowConfiguration().canReceiveKeys() || mAlwaysFocusable;
Wale Ogunwaled045c822015-12-02 09:14:28 -0800839 }
840
Wale Ogunwale571771c2016-08-26 13:18:50 -0700841 @Override
Wale Ogunwale44f21802016-09-02 12:49:48 -0700842 boolean isVisible() {
Wale Ogunwalee471be62016-10-03 07:53:55 -0700843 // If the app token isn't hidden then it is considered visible and there is no need to check
844 // its children windows to see if they are visible.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200845 return !isHidden();
Wale Ogunwale44f21802016-09-02 12:49:48 -0700846 }
847
848 @Override
Wale Ogunwalee287e192017-04-21 09:30:12 -0700849 void removeImmediately() {
850 onRemovedFromDisplay();
Yunfan Chen3a77f282018-12-12 15:47:52 -0800851 if (mActivityRecord != null) {
852 mActivityRecord.unregisterConfigurationChangeListener(this);
853 }
Wale Ogunwalee287e192017-04-21 09:30:12 -0700854 super.removeImmediately();
855 }
856
857 @Override
Wale Ogunwale571771c2016-08-26 13:18:50 -0700858 void removeIfPossible() {
Craig Mautnere3119b72015-01-20 15:02:36 -0800859 mIsExiting = false;
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800860 removeAllWindowsIfPossible();
Bryce Lee6d410262017-02-28 15:30:17 -0800861 removeImmediately();
Craig Mautnere3119b72015-01-20 15:02:36 -0800862 }
863
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700864 @Override
865 boolean checkCompleteDeferredRemoval() {
866 if (mIsExiting) {
867 removeIfPossible();
868 }
869 return super.checkCompleteDeferredRemoval();
870 }
871
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700872 void onRemovedFromDisplay() {
Wale Ogunwalee287e192017-04-21 09:30:12 -0700873 if (mRemovingFromDisplay) {
874 return;
875 }
876 mRemovingFromDisplay = true;
877
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700878 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app token: " + this);
879
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800880 boolean delayed = commitVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700881
lumark588a3e82018-07-20 18:53:54 +0800882 getDisplayContent().mOpeningApps.remove(this);
Evan Rosky2289ba12018-11-19 18:28:18 -0800883 getDisplayContent().mChangingApps.remove(this);
lumark588a3e82018-07-20 18:53:54 +0800884 getDisplayContent().mUnknownAppVisibilityController.appRemovedOrHidden(this);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800885 mWmService.mTaskSnapshotController.onAppRemoved(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700886 waitingToShow = false;
lumark588a3e82018-07-20 18:53:54 +0800887 if (getDisplayContent().mClosingApps.contains(this)) {
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700888 delayed = true;
lumark588a3e82018-07-20 18:53:54 +0800889 } else if (getDisplayContent().mAppTransition.isTransitionSet()) {
890 getDisplayContent().mClosingApps.add(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700891 delayed = true;
892 }
893
894 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app " + this + " delayed=" + delayed
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200895 + " animation=" + getAnimation() + " animating=" + isSelfAnimating());
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700896
897 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: "
898 + this + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
899
chaviwa8f07a72019-05-01 16:25:39 -0700900 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800901 removeStartingWindow();
Jorim Jaggi19be6052017-08-03 18:33:43 +0200902 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800903
Winson Chung87e5d552017-04-05 11:49:38 -0700904 // If this window was animating, then we need to ensure that the app transition notifies
lumark588a3e82018-07-20 18:53:54 +0800905 // that animations have completed in DisplayContent.handleAnimatingStoppedAndTransition(),
906 // so add to that list now
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200907 if (isSelfAnimating()) {
lumark588a3e82018-07-20 18:53:54 +0800908 getDisplayContent().mNoAnimationNotifyOnTransitionFinished.add(token);
Winson Chung87e5d552017-04-05 11:49:38 -0700909 }
910
Wale Ogunwalee287e192017-04-21 09:30:12 -0700911 final TaskStack stack = getStack();
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700912 if (delayed && !isEmpty()) {
913 // set the token aside because it has an active animation to be finished
914 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM,
915 "removeAppToken make exiting: " + this);
Wale Ogunwalee287e192017-04-21 09:30:12 -0700916 if (stack != null) {
917 stack.mExitingAppTokens.add(this);
918 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700919 mIsExiting = true;
920 } else {
921 // Make sure there is no animation running on this token, so any windows associated
922 // with it will be removed as soon as their animations are complete
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200923 cancelAnimation();
Wale Ogunwale3106ae012017-05-16 08:56:37 -0700924 if (stack != null) {
925 stack.mExitingAppTokens.remove(this);
926 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700927 removeIfPossible();
928 }
929
930 removed = true;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700931 stopFreezingScreen(true, true);
Bryce Lee6d410262017-02-28 15:30:17 -0800932
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800933 final DisplayContent dc = getDisplayContent();
934 if (dc.mFocusedApp == this) {
935 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + this
936 + " displayId=" + dc.getDisplayId());
937 dc.setFocusedApp(null);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800938 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700939 }
Riddle Hsu192fe762019-01-15 23:41:57 +0800940 if (mLetterbox != null) {
941 mLetterbox.destroy();
942 mLetterbox = null;
943 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700944
945 if (!delayed) {
946 updateReportedVisibilityLocked();
947 }
Wale Ogunwalee287e192017-04-21 09:30:12 -0700948
949 mRemovingFromDisplay = false;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700950 }
951
Chong Zhange05bcb12016-07-26 17:47:29 -0700952 void clearAnimatingFlags() {
Chong Zhangb0d26702016-08-12 16:03:29 -0700953 boolean wallpaperMightChange = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700954 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700955 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700956 wallpaperMightChange |= win.clearAnimatingFlags();
Chong Zhange05bcb12016-07-26 17:47:29 -0700957 }
Chong Zhangb0d26702016-08-12 16:03:29 -0700958 if (wallpaperMightChange) {
959 requestUpdateWallpaperIfNeeded();
960 }
Chong Zhange05bcb12016-07-26 17:47:29 -0700961 }
962
Robert Carre12aece2016-02-02 22:43:27 -0800963 void destroySurfaces() {
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700964 destroySurfaces(false /*cleanupOnResume*/);
965 }
966
967 /**
968 * Destroy surfaces which have been marked as eligible by the animator, taking care to ensure
969 * the client has finished with them.
970 *
971 * @param cleanupOnResume whether this is done when app is resumed without fully stopped. If
972 * set to true, destroy only surfaces of removed windows, and clear relevant flags of the
973 * others so that they are ready to be reused. If set to false (common case), destroy all
974 * surfaces that's eligible, if the app is already stopped.
975 */
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700976 private void destroySurfaces(boolean cleanupOnResume) {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700977 boolean destroyedSomething = false;
Jorim Jaggia5e10572017-11-15 14:36:26 +0100978
979 // Copying to a different list as multiple children can be removed.
Jorim Jaggi59f3e922018-01-05 15:40:32 +0100980 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
Jorim Jaggia5e10572017-11-15 14:36:26 +0100981 for (int i = children.size() - 1; i >= 0; i--) {
982 final WindowState win = children.get(i);
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700983 destroyedSomething |= win.destroySurface(cleanupOnResume, mAppStopped);
Robert Carre12aece2016-02-02 22:43:27 -0800984 }
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700985 if (destroyedSomething) {
986 final DisplayContent dc = getDisplayContent();
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700987 dc.assignWindowLayers(true /*setLayoutNeeded*/);
Adrian Roos23df3a32018-03-15 15:41:13 +0100988 updateLetterboxSurface(null);
Robert Carre12aece2016-02-02 22:43:27 -0800989 }
990 }
991
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800992 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700993 * Notify that the app is now resumed, and it was not stopped before, perform a clean
994 * up of the surfaces
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800995 */
Jorim Jaggibae01b12017-04-11 16:29:10 -0700996 void notifyAppResumed(boolean wasStopped) {
Chong Zhangad24f962016-08-25 12:12:33 -0700997 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppResumed: wasStopped=" + wasStopped
Jorim Jaggibae01b12017-04-11 16:29:10 -0700998 + " " + this);
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700999 mAppStopped = false;
chaviwd3bf08d2017-08-01 17:24:59 -07001000 // Allow the window to turn the screen on once the app is resumed again.
1001 setCanTurnScreenOn(true);
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001002 if (!wasStopped) {
1003 destroySurfaces(true /*cleanupOnResume*/);
Wale Ogunwale8d5a5422016-03-03 18:28:21 -08001004 }
Robert Carre12aece2016-02-02 22:43:27 -08001005 }
1006
Chong Zhangbef461f2015-10-27 11:38:24 -07001007 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001008 * Notify that the app has stopped, and it is okay to destroy any surfaces which were
1009 * keeping alive in case they were still being used.
1010 */
1011 void notifyAppStopped() {
1012 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: " + this);
1013 mAppStopped = true;
1014 destroySurfaces();
1015 // Remove any starting window that was added for this app if they are still around.
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001016 removeStartingWindow();
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001017 }
1018
Chong Zhang92147042016-05-09 12:47:11 -07001019 void clearAllDrawn() {
1020 allDrawn = false;
1021 deferClearAllDrawn = false;
Chong Zhangbef461f2015-10-27 11:38:24 -07001022 }
1023
Bryce Lee6d410262017-02-28 15:30:17 -08001024 Task getTask() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001025 return (Task) getParent();
Bryce Lee6d410262017-02-28 15:30:17 -08001026 }
1027
Jorim Jaggi3878ca32017-02-02 17:13:05 -08001028 TaskStack getStack() {
1029 final Task task = getTask();
1030 if (task != null) {
1031 return task.mStack;
1032 } else {
1033 return null;
1034 }
1035 }
1036
Bryce Lee6d410262017-02-28 15:30:17 -08001037 @Override
Riddle Hsu3a4bb612019-01-31 00:02:22 +08001038 void onParentChanged() {
1039 super.onParentChanged();
Bryce Lee6d410262017-02-28 15:30:17 -08001040
Robert Carred3e83b2017-04-21 13:26:55 -07001041 final Task task = getTask();
1042
Bryce Lee6d410262017-02-28 15:30:17 -08001043 // When the associated task is {@code null}, the {@link AppWindowToken} can no longer
1044 // access visual elements like the {@link DisplayContent}. We must remove any associations
1045 // such as animations.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001046 if (!mReparenting) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001047 if (task == null) {
1048 // It is possible we have been marked as a closing app earlier. We must remove ourselves
1049 // from this list so we do not participate in any future animations.
lumark588a3e82018-07-20 18:53:54 +08001050 getDisplayContent().mClosingApps.remove(this);
Robert Carred3e83b2017-04-21 13:26:55 -07001051 } else if (mLastParent != null && mLastParent.mStack != null) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001052 task.mStack.mExitingAppTokens.remove(this);
1053 }
Bryce Lee6d410262017-02-28 15:30:17 -08001054 }
Jorim Jaggi6de61012018-03-19 14:53:23 +01001055 final TaskStack stack = getStack();
1056
1057 // If we reparent, make sure to remove ourselves from the old animation registry.
1058 if (mAnimatingAppWindowTokenRegistry != null) {
1059 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
1060 }
1061 mAnimatingAppWindowTokenRegistry = stack != null
1062 ? stack.getAnimatingAppWindowTokenRegistry()
1063 : null;
1064
Robert Carred3e83b2017-04-21 13:26:55 -07001065 mLastParent = task;
chaviwdcf76ec2019-01-11 16:48:46 -08001066
1067 updateColorTransform();
Bryce Lee6d410262017-02-28 15:30:17 -08001068 }
1069
Wale Ogunwalefa854eb2016-09-20 13:43:52 -07001070 void postWindowRemoveStartingWindowCleanup(WindowState win) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001071 // TODO: Something smells about the code below...Is there a better way?
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001072 if (startingWindow == win) {
1073 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Notify removed startingWindow " + win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001074 removeStartingWindow();
Wale Ogunwale6c459212017-05-17 08:56:03 -07001075 } else if (mChildren.size() == 0) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001076 // If this is the last window and we had requested a starting transition window,
1077 // well there is no point now.
Jorim Jaggi02886a82016-12-06 09:10:06 -08001078 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Nulling last startingData");
chaviwa8f07a72019-05-01 16:25:39 -07001079 mStartingData = null;
Wale Ogunwale6c459212017-05-17 08:56:03 -07001080 if (mHiddenSetFromTransferredStartingWindow) {
1081 // We set the hidden state to false for the token from a transferred starting window.
1082 // We now reset it back to true since the starting window was the last window in the
1083 // token.
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001084 setHidden(true);
Wale Ogunwale6c459212017-05-17 08:56:03 -07001085 }
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01001086 } else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001087 // If this is the last window except for a starting transition window,
1088 // we need to get rid of the starting transition.
Jorim Jaggie4b0f282017-05-17 15:10:29 +02001089 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Last window, removing starting window "
1090 + win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001091 removeStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001092 }
1093 }
1094
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001095 void removeDeadWindows() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001096 for (int winNdx = mChildren.size() - 1; winNdx >= 0; --winNdx) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001097 WindowState win = mChildren.get(winNdx);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001098 if (win.mAppDied) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001099 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.w(TAG,
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001100 "removeDeadWindows: " + win);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001101 // Set mDestroying, we don't want any animation or delayed removal here.
1102 win.mDestroying = true;
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001103 // Also removes child windows.
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001104 win.removeIfPossible();
Chong Zhang112eb8c2015-11-02 11:17:00 -08001105 }
1106 }
1107 }
1108
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001109 boolean hasWindowsAlive() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001110 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001111 // No need to loop through child windows as the answer should be the same as that of the
1112 // parent window.
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001113 if (!(mChildren.get(i)).mAppDied) {
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001114 return true;
1115 }
1116 }
1117 return false;
1118 }
1119
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001120 void setWillReplaceWindows(boolean animate) {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001121 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
1122 "Marking app token " + this + " with replacing windows.");
Robert Carra1eb4392015-12-10 12:43:51 -08001123
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001124 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001125 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001126 w.setWillReplaceWindow(animate);
Robert Carra1eb4392015-12-10 12:43:51 -08001127 }
Robert Carra1eb4392015-12-10 12:43:51 -08001128 }
1129
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001130 void setWillReplaceChildWindows() {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001131 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Marking app token " + this
Robert Carr23fa16b2016-01-13 13:19:58 -08001132 + " with replacing child windows.");
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001133 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001134 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001135 w.setWillReplaceChildWindows();
Robert Carr23fa16b2016-01-13 13:19:58 -08001136 }
1137 }
1138
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001139 void clearWillReplaceWindows() {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001140 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
1141 "Resetting app token " + this + " of replacing window marks.");
Chong Zhangf596cd52016-01-05 13:42:44 -08001142
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001143 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001144 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001145 w.clearWillReplaceWindow();
Chong Zhangf596cd52016-01-05 13:42:44 -08001146 }
1147 }
1148
Chong Zhang4d7369a2016-04-25 16:09:14 -07001149 void requestUpdateWallpaperIfNeeded() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001150 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001151 final WindowState w = mChildren.get(i);
Chong Zhang4d7369a2016-04-25 16:09:14 -07001152 w.requestUpdateWallpaperIfNeeded();
1153 }
1154 }
1155
Chong Zhangd78ddb42016-03-02 17:01:14 -08001156 boolean isRelaunching() {
1157 return mPendingRelaunchCount > 0;
1158 }
1159
Robert Carr68375192017-06-13 12:41:53 -07001160 boolean shouldFreezeBounds() {
1161 final Task task = getTask();
1162
1163 // For freeform windows, we can't freeze the bounds at the moment because this would make
1164 // the resizing unresponsive.
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001165 if (task == null || task.inFreeformWindowingMode()) {
Robert Carr68375192017-06-13 12:41:53 -07001166 return false;
1167 }
1168
1169 // We freeze the bounds while drag resizing to deal with the time between
1170 // the divider/drag handle being released, and the handling it's new
1171 // configuration. If we are relaunched outside of the drag resizing state,
1172 // we need to be careful not to do this.
1173 return getTask().isDragResizing();
1174 }
1175
Chong Zhangd78ddb42016-03-02 17:01:14 -08001176 void startRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001177 if (shouldFreezeBounds()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08001178 freezeBounds();
1179 }
Robert Carrd5c7dd62017-03-08 10:39:30 -08001180
1181 // In the process of tearing down before relaunching, the app will
1182 // try and clean up it's child surfaces. We need to prevent this from
1183 // happening, so we sever the children, transfering their ownership
1184 // from the client it-self to the parent surface (owned by us).
Robert Carr29daa922018-04-27 11:56:48 -07001185 detachChildren();
1186
1187 mPendingRelaunchCount++;
1188 }
1189
1190 void detachChildren() {
Robert Carrfd8e93b2018-05-10 13:40:25 -07001191 SurfaceControl.openTransaction();
Robert Carrd5c7dd62017-03-08 10:39:30 -08001192 for (int i = mChildren.size() - 1; i >= 0; i--) {
1193 final WindowState w = mChildren.get(i);
1194 w.mWinAnimator.detachChildren();
1195 }
Robert Carrfd8e93b2018-05-10 13:40:25 -07001196 SurfaceControl.closeTransaction();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001197 }
1198
1199 void finishRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001200 unfreezeBounds();
1201
Chong Zhangd78ddb42016-03-02 17:01:14 -08001202 if (mPendingRelaunchCount > 0) {
1203 mPendingRelaunchCount--;
Bryce Lee081554b2017-05-25 07:52:12 -07001204 } else {
1205 // Update keyguard flags upon finishing relaunch.
1206 checkKeyguardFlagsChanged();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001207 }
1208 }
1209
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001210 void clearRelaunching() {
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001211 if (mPendingRelaunchCount == 0) {
1212 return;
1213 }
Robert Carr68375192017-06-13 12:41:53 -07001214 unfreezeBounds();
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001215 mPendingRelaunchCount = 0;
1216 }
1217
Wale Ogunwale07bcab72016-10-14 15:30:09 -07001218 /**
1219 * Returns true if the new child window we are adding to this token is considered greater than
1220 * the existing child window in this token in terms of z-order.
1221 */
1222 @Override
1223 protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
1224 WindowState existingWindow) {
1225 final int type1 = newWindow.mAttrs.type;
1226 final int type2 = existingWindow.mAttrs.type;
1227
1228 // Base application windows should be z-ordered BELOW all other windows in the app token.
1229 if (type1 == TYPE_BASE_APPLICATION && type2 != TYPE_BASE_APPLICATION) {
1230 return false;
1231 } else if (type1 != TYPE_BASE_APPLICATION && type2 == TYPE_BASE_APPLICATION) {
1232 return true;
1233 }
1234
1235 // Starting windows should be z-ordered ABOVE all other windows in the app token.
1236 if (type1 == TYPE_APPLICATION_STARTING && type2 != TYPE_APPLICATION_STARTING) {
1237 return true;
1238 } else if (type1 != TYPE_APPLICATION_STARTING && type2 == TYPE_APPLICATION_STARTING) {
1239 return false;
1240 }
1241
1242 // Otherwise the new window is greater than the existing window.
1243 return true;
1244 }
1245
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001246 @Override
Robert Carra1eb4392015-12-10 12:43:51 -08001247 void addWindow(WindowState w) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001248 super.addWindow(w);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001249
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001250 boolean gotReplacementWindow = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001251 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001252 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001253 gotReplacementWindow |= candidate.setReplacementWindowIfNeeded(w);
1254 }
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001255
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001256 // if we got a replacement window, reset the timeout to give drawing more time
1257 if (gotReplacementWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001258 mWmService.scheduleWindowReplacementTimeouts(this);
Robert Carra1eb4392015-12-10 12:43:51 -08001259 }
Jorim Jaggife762342016-10-13 14:33:27 +02001260 checkKeyguardFlagsChanged();
1261 }
1262
1263 @Override
1264 void removeChild(WindowState child) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001265 if (!mChildren.contains(child)) {
1266 // This can be true when testing.
1267 return;
1268 }
Jorim Jaggife762342016-10-13 14:33:27 +02001269 super.removeChild(child);
1270 checkKeyguardFlagsChanged();
Adrian Roos23df3a32018-03-15 15:41:13 +01001271 updateLetterboxSurface(child);
Robert Carra1eb4392015-12-10 12:43:51 -08001272 }
1273
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001274 private boolean waitingForReplacement() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001275 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001276 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001277 if (candidate.waitingForReplacement()) {
Robert Carra1eb4392015-12-10 12:43:51 -08001278 return true;
1279 }
1280 }
1281 return false;
1282 }
1283
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001284 void onWindowReplacementTimeout() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001285 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001286 (mChildren.get(i)).onWindowReplacementTimeout();
Robert Carra1eb4392015-12-10 12:43:51 -08001287 }
1288 }
1289
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001290 void reparent(Task task, int position) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001291 if (DEBUG_ADD_REMOVE) {
1292 Slog.i(TAG_WM, "reparent: moving app token=" + this
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001293 + " to task=" + task.mTaskId + " at " + position);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001294 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001295 if (task == null) {
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001296 throw new IllegalArgumentException("reparent: could not find task");
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001297 }
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001298 final Task currentTask = getTask();
1299 if (task == currentTask) {
Winson Chung30480042017-01-26 10:55:34 -08001300 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001301 "window token=" + this + " already child of task=" + currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001302 }
Bryce Lee6d410262017-02-28 15:30:17 -08001303
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001304 if (currentTask.mStack != task.mStack) {
Bryce Lee6d410262017-02-28 15:30:17 -08001305 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001306 "window token=" + this + " current task=" + currentTask
Bryce Lee6d410262017-02-28 15:30:17 -08001307 + " belongs to a different stack than " + task);
1308 }
1309
Winson Chung30480042017-01-26 10:55:34 -08001310 if (DEBUG_ADD_REMOVE) Slog.i(TAG, "reParentWindowToken: removing window token=" + this
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001311 + " from task=" + currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001312 final DisplayContent prevDisplayContent = getDisplayContent();
1313
Bryce Lee6d410262017-02-28 15:30:17 -08001314 mReparenting = true;
1315
Winson Chung30480042017-01-26 10:55:34 -08001316 getParent().removeChild(this);
1317 task.addChild(this, position);
1318
Bryce Lee6d410262017-02-28 15:30:17 -08001319 mReparenting = false;
1320
Winson Chung30480042017-01-26 10:55:34 -08001321 // Relayout display(s).
1322 final DisplayContent displayContent = task.getDisplayContent();
1323 displayContent.setLayoutNeeded();
1324 if (prevDisplayContent != displayContent) {
1325 onDisplayChanged(displayContent);
1326 prevDisplayContent.setLayoutNeeded();
1327 }
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001328 getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
Winson Chung30480042017-01-26 10:55:34 -08001329 }
1330
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001331 @Override
1332 void onDisplayChanged(DisplayContent dc) {
1333 DisplayContent prevDc = mDisplayContent;
1334 super.onDisplayChanged(dc);
Evan Roskyb1e75f72019-04-26 20:23:26 -07001335 if (prevDc == null || prevDc == mDisplayContent) {
Evan Rosky25b56192019-02-06 16:10:56 -08001336 return;
1337 }
Wale Ogunwaleb8e6b632019-06-28 15:19:25 +00001338
1339 if (prevDc.mOpeningApps.remove(this)) {
1340 // Transfer opening transition to new display.
1341 mDisplayContent.mOpeningApps.add(this);
1342 mDisplayContent.prepareAppTransition(prevDc.mAppTransition.getAppTransition(), true);
1343 mDisplayContent.executeAppTransition();
1344 }
1345
1346 if (prevDc.mChangingApps.remove(this)) {
Evan Rosky25b56192019-02-06 16:10:56 -08001347 // This gets called *after* the AppWindowToken has been reparented to the new display.
1348 // That reparenting resulted in this window changing modes (eg. FREEFORM -> FULLSCREEN),
1349 // so this token is now "frozen" while waiting for the animation to start on prevDc
1350 // (which will be cancelled since the window is no-longer a child). However, since this
1351 // is no longer a child of prevDc, this won't be notified of the cancelled animation,
1352 // so we need to cancel the change transition here.
1353 clearChangeLeash(getPendingTransaction(), true /* cancel */);
1354 }
Wale Ogunwaleb8e6b632019-06-28 15:19:25 +00001355 prevDc.mClosingApps.remove(this);
1356
Evan Rosky25b56192019-02-06 16:10:56 -08001357 if (prevDc.mFocusedApp == this) {
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001358 prevDc.setFocusedApp(null);
lumarkbf844642018-11-23 17:11:36 +08001359 final TaskStack stack = dc.getTopStack();
1360 if (stack != null) {
1361 final Task task = stack.getTopChild();
1362 if (task != null && task.getTopChild() == this) {
1363 dc.setFocusedApp(this);
1364 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001365 }
1366 }
Riddle Hsu192fe762019-01-15 23:41:57 +08001367
Evan Roskyb1e75f72019-04-26 20:23:26 -07001368 if (mLetterbox != null) {
Riddle Hsu192fe762019-01-15 23:41:57 +08001369 mLetterbox.onMovedToDisplay(mDisplayContent.getDisplayId());
1370 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001371 }
1372
Jorim Jaggi0429f352015-12-22 16:29:16 +01001373 /**
1374 * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds
1375 * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even
1376 * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen
1377 * with a queue.
1378 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001379 private void freezeBounds() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001380 final Task task = getTask();
1381 mFrozenBounds.offer(new Rect(task.mPreparedFrozenBounds));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001382
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001383 if (task.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001384 // We didn't call prepareFreezingBounds on the task, so use the current value.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001385 mFrozenMergedConfig.offer(new Configuration(task.getConfiguration()));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001386 } else {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001387 mFrozenMergedConfig.offer(new Configuration(task.mPreparedFrozenMergedConfig));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001388 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001389 // Calling unset() to make it equal to Configuration.EMPTY.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001390 task.mPreparedFrozenMergedConfig.unset();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001391 }
1392
1393 /**
1394 * Unfreezes the previously frozen bounds. See {@link #freezeBounds}.
1395 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001396 private void unfreezeBounds() {
Robert Carr68375192017-06-13 12:41:53 -07001397 if (mFrozenBounds.isEmpty()) {
1398 return;
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001399 }
Robert Carr68375192017-06-13 12:41:53 -07001400 mFrozenBounds.remove();
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001401 if (!mFrozenMergedConfig.isEmpty()) {
1402 mFrozenMergedConfig.remove();
1403 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001404 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001405 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001406 win.onUnfreezeBounds();
Jorim Jaggi4846ee32016-01-07 17:39:12 +01001407 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001408 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001409 }
1410
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001411 void setAppLayoutChanges(int changes, String reason) {
1412 if (!mChildren.isEmpty()) {
1413 final DisplayContent dc = getDisplayContent();
1414 dc.pendingLayoutChanges |= changes;
1415 if (DEBUG_LAYOUT_REPEATS) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001416 mWmService.mWindowPlacerLocked.debugLayoutRepeats(reason, dc.pendingLayoutChanges);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001417 }
1418 }
1419 }
1420
1421 void removeReplacedWindowIfNeeded(WindowState replacement) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001422 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001423 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001424 if (win.removeReplacedWindowIfNeeded(replacement)) {
1425 return;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001426 }
1427 }
1428 }
1429
1430 void startFreezingScreen() {
1431 if (DEBUG_ORIENTATION) logWithStack(TAG, "Set freezing of " + appToken + ": hidden="
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001432 + isHidden() + " freezing=" + mFreezingScreen + " hiddenRequested="
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001433 + hiddenRequested);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001434 if (!hiddenRequested) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001435 if (!mFreezingScreen) {
1436 mFreezingScreen = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001437 mWmService.registerAppFreezeListener(this);
1438 mWmService.mAppsFreezingScreen++;
1439 if (mWmService.mAppsFreezingScreen == 1) {
1440 mWmService.startFreezingDisplayLocked(0, 0, getDisplayContent());
1441 mWmService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
1442 mWmService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001443 }
1444 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001445 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001446 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001447 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001448 w.onStartFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001449 }
1450 }
1451 }
1452
1453 void stopFreezingScreen(boolean unfreezeSurfaceNow, boolean force) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001454 if (!mFreezingScreen) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001455 return;
1456 }
1457 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + this + " force=" + force);
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001458 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001459 boolean unfrozeWindows = false;
1460 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001461 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001462 unfrozeWindows |= w.onStopFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001463 }
1464 if (force || unfrozeWindows) {
1465 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "No longer freezing: " + this);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001466 mFreezingScreen = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001467 mWmService.unregisterAppFreezeListener(this);
1468 mWmService.mAppsFreezingScreen--;
1469 mWmService.mLastFinishedFreezeSource = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001470 }
1471 if (unfreezeSurfaceNow) {
1472 if (unfrozeWindows) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001473 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001474 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001475 mWmService.stopFreezingDisplayLocked();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001476 }
1477 }
1478
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001479 @Override
1480 public void onAppFreezeTimeout() {
1481 Slog.w(TAG_WM, "Force clearing freeze: " + this);
1482 stopFreezingScreen(true, true);
1483 }
1484
Jorim Jaggi60f9c972018-02-01 19:21:07 +01001485 /**
1486 * Tries to transfer the starting window from a token that's above ourselves in the task but
1487 * not visible anymore. This is a common scenario apps use: Trampoline activity T start main
1488 * activity M in the same task. Now, when reopening the task, T starts on top of M but then
1489 * immediately finishes after, so we have to transfer T to M.
1490 */
1491 void transferStartingWindowFromHiddenAboveTokenIfNeeded() {
1492 final Task task = getTask();
1493 for (int i = task.mChildren.size() - 1; i >= 0; i--) {
1494 final AppWindowToken fromToken = task.mChildren.get(i);
1495 if (fromToken == this) {
1496 return;
1497 }
1498 if (fromToken.hiddenRequested && transferStartingWindow(fromToken.token)) {
1499 return;
1500 }
1501 }
1502 }
1503
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001504 boolean transferStartingWindow(IBinder transferFrom) {
Wale Ogunwale02319a62016-09-26 15:21:22 -07001505 final AppWindowToken fromToken = getDisplayContent().getAppWindowToken(transferFrom);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001506 if (fromToken == null) {
1507 return false;
1508 }
1509
1510 final WindowState tStartingWindow = fromToken.startingWindow;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08001511 if (tStartingWindow != null && fromToken.startingSurface != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001512 // In this case, the starting icon has already been displayed, so start
1513 // letting windows get shown immediately without any more transitions.
lumark588a3e82018-07-20 18:53:54 +08001514 getDisplayContent().mSkipAppTransitionAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001515
1516 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Moving existing starting " + tStartingWindow
1517 + " from " + fromToken + " to " + this);
1518
1519 final long origId = Binder.clearCallingIdentity();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001520 try {
1521 // Transfer the starting window over to the new token.
chaviwa8f07a72019-05-01 16:25:39 -07001522 mStartingData = fromToken.mStartingData;
Peter Visontay3556a3b2017-11-01 17:23:17 +00001523 startingSurface = fromToken.startingSurface;
1524 startingDisplayed = fromToken.startingDisplayed;
1525 fromToken.startingDisplayed = false;
1526 startingWindow = tStartingWindow;
1527 reportedVisible = fromToken.reportedVisible;
chaviwa8f07a72019-05-01 16:25:39 -07001528 fromToken.mStartingData = null;
Peter Visontay3556a3b2017-11-01 17:23:17 +00001529 fromToken.startingSurface = null;
1530 fromToken.startingWindow = null;
1531 fromToken.startingMoved = true;
1532 tStartingWindow.mToken = this;
1533 tStartingWindow.mAppToken = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001534
Peter Visontay3556a3b2017-11-01 17:23:17 +00001535 if (DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
1536 "Removing starting " + tStartingWindow + " from " + fromToken);
1537 fromToken.removeChild(tStartingWindow);
1538 fromToken.postWindowRemoveStartingWindowCleanup(tStartingWindow);
1539 fromToken.mHiddenSetFromTransferredStartingWindow = false;
1540 addWindow(tStartingWindow);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001541
Peter Visontay3556a3b2017-11-01 17:23:17 +00001542 // Propagate other interesting state between the tokens. If the old token is displayed,
1543 // we should immediately force the new one to be displayed. If it is animating, we need
1544 // to move that animation to the new one.
1545 if (fromToken.allDrawn) {
1546 allDrawn = true;
1547 deferClearAllDrawn = fromToken.deferClearAllDrawn;
1548 }
1549 if (fromToken.firstWindowDrawn) {
1550 firstWindowDrawn = true;
1551 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001552 if (!fromToken.isHidden()) {
1553 setHidden(false);
Peter Visontay3556a3b2017-11-01 17:23:17 +00001554 hiddenRequested = false;
1555 mHiddenSetFromTransferredStartingWindow = true;
1556 }
1557 setClientHidden(fromToken.mClientHidden);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001558
Jorim Jaggi980c9de2017-11-17 01:41:37 +01001559 transferAnimation(fromToken);
1560
1561 // When transferring an animation, we no longer need to apply an animation to the
Tiger Huangc9d0d002019-05-29 22:55:29 +08001562 // the token we transfer the animation over. Thus, set this flag to indicate we've
1563 // transferred the animation.
1564 mUseTransferredAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001565
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001566 mWmService.updateFocusedWindowLocked(
Peter Visontay3556a3b2017-11-01 17:23:17 +00001567 UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/);
1568 getDisplayContent().setLayoutNeeded();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001569 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001570 } finally {
1571 Binder.restoreCallingIdentity(origId);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001572 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001573 return true;
chaviwa8f07a72019-05-01 16:25:39 -07001574 } else if (fromToken.mStartingData != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001575 // The previous app was getting ready to show a
1576 // starting window, but hasn't yet done so. Steal it!
1577 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
1578 "Moving pending starting from " + fromToken + " to " + this);
chaviwa8f07a72019-05-01 16:25:39 -07001579 mStartingData = fromToken.mStartingData;
1580 fromToken.mStartingData = null;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001581 fromToken.startingMoved = true;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001582 scheduleAddStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001583 return true;
1584 }
1585
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001586 // TODO: Transfer thumbnail
1587
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001588 return false;
1589 }
1590
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001591 boolean isLastWindow(WindowState win) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001592 return mChildren.size() == 1 && mChildren.get(0) == win;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001593 }
1594
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001595 @Override
1596 void onAppTransitionDone() {
1597 sendingToBottom = false;
1598 }
1599
Wale Ogunwale51362492016-09-08 17:49:17 -07001600 /**
1601 * We override because this class doesn't want its children affecting its reported orientation
1602 * in anyway.
1603 */
1604 @Override
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001605 int getOrientation(int candidate) {
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001606 if (candidate == SCREEN_ORIENTATION_BEHIND) {
1607 // Allow app to specify orientation regardless of its visibility state if the current
1608 // candidate want us to use orientation behind. I.e. the visible app on-top of this one
1609 // wants us to use the orientation of the app behind it.
1610 return mOrientation;
1611 }
1612
Bryce Lee61fbcbc2017-03-10 14:14:03 -08001613 // The {@link AppWindowToken} should only specify an orientation when it is not closing or
1614 // going to the bottom. Allowing closing {@link AppWindowToken} to participate can lead to
1615 // an Activity in another task being started in the wrong orientation during the transition.
lumark588a3e82018-07-20 18:53:54 +08001616 if (!(sendingToBottom || getDisplayContent().mClosingApps.contains(this))
1617 && (isVisible() || getDisplayContent().mOpeningApps.contains(this))) {
Bryce Leea163b762017-01-24 11:05:01 -08001618 return mOrientation;
Wale Ogunwale51362492016-09-08 17:49:17 -07001619 }
Bryce Leea163b762017-01-24 11:05:01 -08001620
1621 return SCREEN_ORIENTATION_UNSET;
Wale Ogunwale51362492016-09-08 17:49:17 -07001622 }
1623
Wale Ogunwaleb198b742016-12-01 08:44:09 -08001624 /** Returns the app's preferred orientation regardless of its currently visibility state. */
1625 int getOrientationIgnoreVisibility() {
1626 return mOrientation;
1627 }
1628
Riddle Hsub398da32019-01-21 21:48:16 +08001629 /** @return {@code true} if the compatibility bounds is taking effect. */
1630 boolean inSizeCompatMode() {
1631 return mSizeCompatBounds != null;
1632 }
1633
1634 @Override
1635 float getSizeCompatScale() {
1636 return inSizeCompatMode() ? mSizeCompatScale : super.getSizeCompatScale();
1637 }
1638
1639 /**
1640 * @return Non-empty bounds if the activity has override bounds.
1641 * @see ActivityRecord#resolveOverrideConfiguration(Configuration)
1642 */
1643 Rect getResolvedOverrideBounds() {
1644 // Get bounds from resolved override configuration because it is computed with orientation.
1645 return getResolvedOverrideConfiguration().windowConfiguration.getBounds();
1646 }
1647
Craig Mautnerdbb79912012-03-01 18:59:14 -08001648 @Override
Winson Chunge55c0192017-08-24 14:50:48 -07001649 public void onConfigurationChanged(Configuration newParentConfig) {
1650 final int prevWinMode = getWindowingMode();
Evan Rosky2289ba12018-11-19 18:28:18 -08001651 mTmpPrevBounds.set(getBounds());
Winson Chunge55c0192017-08-24 14:50:48 -07001652 super.onConfigurationChanged(newParentConfig);
Riddle Hsub398da32019-01-21 21:48:16 +08001653
1654 final Task task = getTask();
1655 final Rect overrideBounds = getResolvedOverrideBounds();
1656 if (task != null && !overrideBounds.isEmpty()
1657 // If the changes come from change-listener, the incoming parent configuration is
1658 // still the old one. Make sure their orientations are the same to reduce computing
1659 // the compatibility bounds for the intermediate state.
Riddle Hsu04164182019-03-07 18:03:27 +08001660 && (task.mTaskRecord == null || task.mTaskRecord
1661 .getConfiguration().orientation == newParentConfig.orientation)) {
Riddle Hsub398da32019-01-21 21:48:16 +08001662 final Rect taskBounds = task.getBounds();
1663 // Since we only center the activity horizontally, if only the fixed height is smaller
1664 // than its container, the override bounds don't need to take effect.
1665 if ((overrideBounds.width() != taskBounds.width()
1666 || overrideBounds.height() > taskBounds.height())) {
1667 calculateCompatBoundsTransformation(newParentConfig);
1668 updateSurfacePosition();
1669 } else if (mSizeCompatBounds != null) {
1670 mSizeCompatBounds = null;
1671 mSizeCompatScale = 1f;
1672 updateSurfacePosition();
1673 }
1674 }
1675
Winson Chunge55c0192017-08-24 14:50:48 -07001676 final int winMode = getWindowingMode();
1677
1678 if (prevWinMode == winMode) {
1679 return;
1680 }
1681
1682 if (prevWinMode != WINDOWING_MODE_UNDEFINED && winMode == WINDOWING_MODE_PINNED) {
1683 // Entering PiP from fullscreen, reset the snap fraction
1684 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(this);
Winson Chung82267ce2018-04-06 16:38:26 -07001685 } else if (prevWinMode == WINDOWING_MODE_PINNED && winMode != WINDOWING_MODE_UNDEFINED
1686 && !isHidden()) {
Winson Chunge55c0192017-08-24 14:50:48 -07001687 // Leaving PiP to fullscreen, save the snap fraction based on the pre-animation bounds
1688 // for the next re-entry into PiP (assuming the activity is not hidden or destroyed)
1689 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
1690 if (pinnedStack != null) {
Winson Chung8efa1652018-06-06 09:34:23 -07001691 final Rect stackBounds;
1692 if (pinnedStack.lastAnimatingBoundsWasToFullscreen()) {
1693 // We are animating the bounds, use the pre-animation bounds to save the snap
1694 // fraction
1695 stackBounds = pinnedStack.mPreAnimationBounds;
1696 } else {
1697 // We skip the animation if the fullscreen configuration is not compatible, so
1698 // use the current bounds to calculate the saved snap fraction instead
1699 // (see PinnedActivityStack.skipResizeAnimation())
1700 stackBounds = mTmpRect;
1701 pinnedStack.getBounds(stackBounds);
1702 }
Winson Chunge55c0192017-08-24 14:50:48 -07001703 mDisplayContent.mPinnedStackControllerLocked.saveReentrySnapFraction(this,
Winson Chung8efa1652018-06-06 09:34:23 -07001704 stackBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001705 }
Evan Rosky2289ba12018-11-19 18:28:18 -08001706 } else if (shouldStartChangeTransition(prevWinMode, winMode)) {
1707 initializeChangeTransition(mTmpPrevBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001708 }
1709 }
1710
Evan Rosky2289ba12018-11-19 18:28:18 -08001711 private boolean shouldStartChangeTransition(int prevWinMode, int newWinMode) {
Evan Rosky25b56192019-02-06 16:10:56 -08001712 if (mWmService.mDisableTransitionAnimation
1713 || !isVisible()
1714 || getDisplayContent().mAppTransition.isTransitionSet()
1715 || getSurfaceControl() == null) {
Evan Rosky2289ba12018-11-19 18:28:18 -08001716 return false;
1717 }
1718 // Only do an animation into and out-of freeform mode for now. Other mode
1719 // transition animations are currently handled by system-ui.
1720 return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
1721 }
1722
1723 /**
1724 * Initializes a change transition. Because the app is visible already, there is a small period
1725 * of time where the user can see the app content/window update before the transition starts.
1726 * To prevent this, we immediately take a snapshot and place the app/snapshot into a leash which
1727 * "freezes" the location/crop until the transition starts.
1728 * <p>
1729 * Here's a walk-through of the process:
1730 * 1. Create a temporary leash ("interim-change-leash") and reparent the app to it.
1731 * 2. Set the temporary leash's position/crop to the current state.
1732 * 3. Create a snapshot and place that at the top of the leash to cover up content changes.
1733 * 4. Once the transition is ready, it will reparent the app to the animation leash.
1734 * 5. Detach the interim-change-leash.
1735 */
1736 private void initializeChangeTransition(Rect startBounds) {
1737 mDisplayContent.prepareAppTransition(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
1738 false /* alwaysKeepCurrent */, 0, false /* forceOverride */);
1739 mDisplayContent.mChangingApps.add(this);
1740 mTransitStartRect.set(startBounds);
1741
1742 final SurfaceControl.Builder builder = makeAnimationLeash()
1743 .setParent(getAnimationLeashParent())
1744 .setName(getSurfaceControl() + " - interim-change-leash");
1745 mTransitChangeLeash = builder.build();
1746 Transaction t = getPendingTransaction();
1747 t.setWindowCrop(mTransitChangeLeash, startBounds.width(), startBounds.height());
1748 t.setPosition(mTransitChangeLeash, startBounds.left, startBounds.top);
1749 t.show(mTransitChangeLeash);
1750 t.reparent(getSurfaceControl(), mTransitChangeLeash);
1751 onAnimationLeashCreated(t, mTransitChangeLeash);
1752
Evan Rosky966759f2019-01-15 10:33:58 -08001753 // Skip creating snapshot if this transition is controlled by a remote animator which
1754 // doesn't need it.
1755 ArraySet<Integer> activityTypes = new ArraySet<>();
1756 activityTypes.add(getActivityType());
1757 RemoteAnimationAdapter adapter =
1758 mDisplayContent.mAppTransitionController.getRemoteAnimationOverride(
1759 this, TRANSIT_TASK_CHANGE_WINDOWING_MODE, activityTypes);
1760 if (adapter != null && !adapter.getChangeNeedsSnapshot()) {
1761 return;
1762 }
1763
Evan Rosky08e20932019-05-14 10:54:07 -07001764 Task task = getTask();
1765 if (mThumbnail == null && task != null && !hasCommittedReparentToAnimationLeash()) {
1766 SurfaceControl.ScreenshotGraphicBuffer snapshot =
1767 mWmService.mTaskSnapshotController.createTaskSnapshot(
1768 task, 1 /* scaleFraction */);
Yunfan Chendcb1fcf2019-02-07 19:08:41 +09001769 if (snapshot != null) {
Evan Rosky08e20932019-05-14 10:54:07 -07001770 mThumbnail = new AppWindowThumbnail(t, this, snapshot.getGraphicBuffer(),
Yunfan Chendcb1fcf2019-02-07 19:08:41 +09001771 true /* relative */);
1772 }
Evan Rosky2289ba12018-11-19 18:28:18 -08001773 }
1774 }
1775
1776 boolean isInChangeTransition() {
Evan Roskyec9488c2019-03-01 19:32:12 -08001777 return mTransitChangeLeash != null || AppTransition.isChangeTransit(mTransit);
Evan Rosky2289ba12018-11-19 18:28:18 -08001778 }
1779
Evan Rosky966759f2019-01-15 10:33:58 -08001780 @VisibleForTesting
1781 AppWindowThumbnail getThumbnail() {
1782 return mThumbnail;
1783 }
1784
Riddle Hsub398da32019-01-21 21:48:16 +08001785 /**
1786 * Calculates the scale and offset to horizontal center the size compatibility bounds into the
1787 * region which is available to application.
1788 */
1789 private void calculateCompatBoundsTransformation(Configuration newParentConfig) {
1790 final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds();
Riddle Hsu74826262019-04-17 14:57:42 +08001791 final Rect parentBounds = newParentConfig.windowConfiguration.getBounds();
1792 final Rect viewportBounds = parentAppBounds != null ? parentAppBounds : parentBounds;
Riddle Hsu04164182019-03-07 18:03:27 +08001793 final Rect appBounds = getWindowConfiguration().getAppBounds();
1794 final Rect contentBounds = appBounds != null ? appBounds : getResolvedOverrideBounds();
Riddle Hsub398da32019-01-21 21:48:16 +08001795 final float contentW = contentBounds.width();
1796 final float contentH = contentBounds.height();
1797 final float viewportW = viewportBounds.width();
1798 final float viewportH = viewportBounds.height();
1799 // Only allow to scale down.
1800 mSizeCompatScale = (contentW <= viewportW && contentH <= viewportH)
1801 ? 1 : Math.min(viewportW / contentW, viewportH / contentH);
1802 final int offsetX = (int) ((viewportW - contentW * mSizeCompatScale + 1) * 0.5f)
1803 + viewportBounds.left;
1804
1805 if (mSizeCompatBounds == null) {
1806 mSizeCompatBounds = new Rect();
1807 }
1808 mSizeCompatBounds.set(contentBounds);
1809 mSizeCompatBounds.offsetTo(0, 0);
1810 mSizeCompatBounds.scale(mSizeCompatScale);
Riddle Hsu74826262019-04-17 14:57:42 +08001811 // Ensure to align the top with the parent.
1812 mSizeCompatBounds.top = parentBounds.top;
Riddle Hsu04164182019-03-07 18:03:27 +08001813 // The decor inset is included in height.
1814 mSizeCompatBounds.bottom += viewportBounds.top;
Riddle Hsub398da32019-01-21 21:48:16 +08001815 mSizeCompatBounds.left += offsetX;
1816 mSizeCompatBounds.right += offsetX;
1817 }
1818
1819 @Override
1820 public Rect getBounds() {
1821 if (mSizeCompatBounds != null) {
1822 return mSizeCompatBounds;
1823 }
1824 return super.getBounds();
1825 }
1826
1827 @Override
1828 public boolean matchParentBounds() {
1829 if (super.matchParentBounds()) {
1830 return true;
1831 }
1832 // An activity in size compatibility mode may have override bounds which equals to its
1833 // parent bounds, so the exact bounds should also be checked.
1834 final WindowContainer parent = getParent();
1835 return parent == null || parent.getBounds().equals(getResolvedOverrideBounds());
1836 }
1837
Winson Chunge55c0192017-08-24 14:50:48 -07001838 @Override
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001839 void checkAppWindowsReadyToShow() {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001840 if (allDrawn == mLastAllDrawn) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001841 return;
1842 }
1843
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001844 mLastAllDrawn = allDrawn;
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001845 if (!allDrawn) {
1846 return;
1847 }
1848
1849 // The token has now changed state to having all windows shown... what to do, what to do?
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001850 if (mFreezingScreen) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001851 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001852 stopFreezingScreen(false, true);
1853 if (DEBUG_ORIENTATION) Slog.i(TAG,
1854 "Setting mOrientationChangeComplete=true because wtoken " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001855 + " numInteresting=" + mNumInterestingWindows + " numDrawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001856 // This will set mOrientationChangeComplete and cause a pass through layout.
1857 setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001858 "checkAppWindowsReadyToShow: freezingScreen");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001859 } else {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001860 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001861
1862 // We can now show all of the drawn windows!
lumark588a3e82018-07-20 18:53:54 +08001863 if (!getDisplayContent().mOpeningApps.contains(this) && canShowWindows()) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001864 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001865 }
1866 }
1867 }
1868
Matthew Ng5d23afa2017-06-21 16:16:24 -07001869 /**
Bryce Leed390deb2017-06-22 13:14:28 -07001870 * Returns whether the drawn window states of this {@link AppWindowToken} has considered every
1871 * child {@link WindowState}. A child is considered if it has been passed into
1872 * {@link #updateDrawnWindowStates(WindowState)} after being added. This is used to determine
1873 * whether states, such as {@code allDrawn}, can be set, which relies on state variables such as
1874 * {@code mNumInterestingWindows}, which depend on all {@link WindowState}s being considered.
1875 *
1876 * @return {@code true} If all children have been considered, {@code false}.
1877 */
1878 private boolean allDrawnStatesConsidered() {
Bryce Lee6311c4b2017-07-06 14:09:29 -07001879 for (int i = mChildren.size() - 1; i >= 0; --i) {
1880 final WindowState child = mChildren.get(i);
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001881 if (child.mightAffectAllDrawn() && !child.getDrawnStateEvaluated()) {
Bryce Leed390deb2017-06-22 13:14:28 -07001882 return false;
1883 }
1884 }
1885 return true;
1886 }
1887
1888 /**
Matthew Ng5d23afa2017-06-21 16:16:24 -07001889 * Determines if the token has finished drawing. This should only be called from
1890 * {@link DisplayContent#applySurfaceChangesTransaction}
1891 */
Matthew Ng498c71d2017-04-18 13:55:45 -07001892 void updateAllDrawn() {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001893 if (!allDrawn) {
Matthew Ng498c71d2017-04-18 13:55:45 -07001894 // Number of drawn windows can be less when a window is being relaunched, wait for
Bryce Leed390deb2017-06-22 13:14:28 -07001895 // all windows to be launched and drawn for this token be considered all drawn.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001896 final int numInteresting = mNumInterestingWindows;
Bryce Leed390deb2017-06-22 13:14:28 -07001897
1898 // We must make sure that all present children have been considered (determined by
1899 // {@link #allDrawnStatesConsidered}) before evaluating whether everything has been
1900 // drawn.
1901 if (numInteresting > 0 && allDrawnStatesConsidered()
1902 && mNumDrawnWindows >= numInteresting && !isRelaunching()) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001903 if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawn: " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001904 + " interesting=" + numInteresting + " drawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001905 allDrawn = true;
1906 // Force an additional layout pass where
1907 // WindowStateAnimator#commitFinishDrawingLocked() will call performShowLocked().
Matthew Ng498c71d2017-04-18 13:55:45 -07001908 if (mDisplayContent != null) {
1909 mDisplayContent.setLayoutNeeded();
1910 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001911 mWmService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
Robert Carrecc06b32017-04-18 14:25:10 -07001912
Winson Chunge7ba6862017-05-24 12:13:33 -07001913 // Notify the pinned stack upon all windows drawn. If there was an animation in
1914 // progress then this signal will resume that animation.
Wale Ogunwale61911492017-10-11 08:50:50 -07001915 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
Winson Chunge7ba6862017-05-24 12:13:33 -07001916 if (pinnedStack != null) {
1917 pinnedStack.onAllWindowsDrawn();
Robert Carrecc06b32017-04-18 14:25:10 -07001918 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001919 }
1920 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001921 }
1922
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001923 boolean keyDispatchingTimedOut(String reason, int windowPid) {
1924 return mActivityRecord != null && mActivityRecord.keyDispatchingTimedOut(reason, windowPid);
1925 }
1926
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001927 /**
1928 * Updated this app token tracking states for interesting and drawn windows based on the window.
1929 *
1930 * @return Returns true if the input window is considered interesting and drawn while all the
1931 * windows in this app token where not considered drawn as of the last pass.
1932 */
1933 boolean updateDrawnWindowStates(WindowState w) {
Bryce Leed390deb2017-06-22 13:14:28 -07001934 w.setDrawnStateEvaluated(true /*evaluated*/);
1935
Jorim Jaggie4b0f282017-05-17 15:10:29 +02001936 if (DEBUG_STARTING_WINDOW_VERBOSE && w == startingWindow) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001937 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + w.isOnScreen()
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001938 + " allDrawn=" + allDrawn + " freezingScreen=" + mFreezingScreen);
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001939 }
1940
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001941 if (allDrawn && !mFreezingScreen) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001942 return false;
1943 }
1944
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001945 if (mLastTransactionSequence != mWmService.mTransactionSequence) {
1946 mLastTransactionSequence = mWmService.mTransactionSequence;
Matthew Ng53e66b22018-01-12 17:13:13 -08001947 mNumDrawnWindows = 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001948 startingDisplayed = false;
Matthew Ng53e66b22018-01-12 17:13:13 -08001949
1950 // There is the main base application window, even if it is exiting, wait for it
1951 mNumInterestingWindows = findMainWindow(false /* includeStartingApp */) != null ? 1 : 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001952 }
1953
1954 final WindowStateAnimator winAnimator = w.mWinAnimator;
1955
1956 boolean isInterestingAndDrawn = false;
1957
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001958 if (!allDrawn && w.mightAffectAllDrawn()) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001959 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
1960 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001961 + ", isAnimationSet=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001962 if (!w.isDrawnLw()) {
1963 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController
chaviw15ad49f2019-04-24 15:05:39 -07001964 + " pv=" + w.isVisibleByPolicy()
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001965 + " mDrawState=" + winAnimator.drawStateToString()
1966 + " ph=" + w.isParentWindowHidden() + " th=" + hiddenRequested
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001967 + " a=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001968 }
1969 }
1970
1971 if (w != startingWindow) {
1972 if (w.isInteresting()) {
Matthew Ng53e66b22018-01-12 17:13:13 -08001973 // Add non-main window as interesting since the main app has already been added
1974 if (findMainWindow(false /* includeStartingApp */) != w) {
1975 mNumInterestingWindows++;
1976 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001977 if (w.isDrawnLw()) {
1978 mNumDrawnWindows++;
1979
1980 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, "tokenMayBeDrawn: "
1981 + this + " w=" + w + " numInteresting=" + mNumInterestingWindows
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001982 + " freezingScreen=" + mFreezingScreen
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001983 + " mAppFreezing=" + w.mAppFreezing);
1984
1985 isInterestingAndDrawn = true;
1986 }
1987 }
1988 } else if (w.isDrawnLw()) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001989 if (mActivityRecord != null) {
1990 mActivityRecord.onStartingWindowDrawn(SystemClock.uptimeMillis());
Jorim Jaggi3878ca32017-02-02 17:13:05 -08001991 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001992 startingDisplayed = true;
1993 }
1994 }
1995
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001996 return isInterestingAndDrawn;
1997 }
1998
Adrian Roos23df3a32018-03-15 15:41:13 +01001999 void layoutLetterbox(WindowState winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002000 final WindowState w = findMainWindow();
Adrian Roosf93b6d22018-03-21 13:48:26 +01002001 if (w == null || winHint != null && w != winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002002 return;
2003 }
Jorim Jaggia32da382018-03-28 18:01:22 +02002004 final boolean surfaceReady = w.isDrawnLw() // Regular case
Adrian Roosf93b6d22018-03-21 13:48:26 +01002005 || w.mWinAnimator.mSurfaceDestroyDeferred // The preserved surface is still ready.
2006 || w.isDragResizeChanged(); // Waiting for relayoutWindow to call preserveSurface.
Jorim Jaggi4981f152019-03-26 18:58:45 +01002007 final boolean needsLetterbox = surfaceReady && w.isLetterboxedAppWindow() && fillsParent();
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002008 if (needsLetterbox) {
2009 if (mLetterbox == null) {
2010 mLetterbox = new Letterbox(() -> makeChildSurface(null));
Riddle Hsu192fe762019-01-15 23:41:57 +08002011 mLetterbox.attachInput(w);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002012 }
Adrian Roos7af9d972018-11-30 15:26:27 +01002013 getPosition(mTmpPoint);
Evan Rosky67c15642019-04-24 13:17:28 -07002014 // Get the bounds of the "space-to-fill". In multi-window mode, the task-level
2015 // represents this. In fullscreen-mode, the stack does (since the orientation letterbox
2016 // is also applied to the task).
2017 Rect spaceToFill = (inMultiWindowMode() || getStack() == null)
2018 ? getTask().getDisplayedBounds() : getStack().getDisplayedBounds();
Evan Rosky4fb1e912019-03-06 13:54:43 -08002019 mLetterbox.layout(spaceToFill, w.getFrameLw(), mTmpPoint);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002020 } else if (mLetterbox != null) {
Adrian Roos23df3a32018-03-15 15:41:13 +01002021 mLetterbox.hide();
2022 }
2023 }
2024
2025 void updateLetterboxSurface(WindowState winHint) {
2026 final WindowState w = findMainWindow();
2027 if (w != winHint && winHint != null && w != null) {
2028 return;
2029 }
2030 layoutLetterbox(winHint);
2031 if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) {
Tiger Huanged6794e2019-05-07 20:07:59 +08002032 mLetterbox.applySurfaceChanges(getPendingTransaction());
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002033 }
2034 }
2035
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07002036 @Override
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002037 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002038 // For legacy reasons we process the TaskStack.mExitingAppTokens first in DisplayContent
2039 // before the non-exiting app tokens. So, we skip the exiting app tokens here.
2040 // TODO: Investigate if we need to continue to do this or if we can just process them
2041 // in-order.
2042 if (mIsExiting && !waitingForReplacement()) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002043 return false;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002044 }
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002045 return forAllWindowsUnchecked(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002046 }
2047
lumark588a3e82018-07-20 18:53:54 +08002048 @Override
2049 void forAllAppWindows(Consumer<AppWindowToken> callback) {
2050 callback.accept(this);
2051 }
2052
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002053 boolean forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback,
2054 boolean traverseTopToBottom) {
2055 return super.forAllWindows(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002056 }
2057
2058 @Override
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002059 AppWindowToken asAppWindowToken() {
2060 // I am an app window token!
2061 return this;
2062 }
2063
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002064 boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
2065 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
2066 IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
2067 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
2068 // If the display is frozen, we won't do anything until the actual window is
2069 // displayed so there is no reason to put in the starting window.
2070 if (!okToDisplay()) {
2071 return false;
2072 }
2073
chaviwa8f07a72019-05-01 16:25:39 -07002074 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002075 return false;
2076 }
2077
2078 final WindowState mainWin = findMainWindow();
2079 if (mainWin != null && mainWin.mWinAnimator.getShown()) {
2080 // App already has a visible window...why would you want a starting window?
2081 return false;
2082 }
2083
2084 final ActivityManager.TaskSnapshot snapshot =
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002085 mWmService.mTaskSnapshotController.getSnapshot(
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002086 getTask().mTaskId, getTask().mUserId,
2087 false /* restoreFromDisk */, false /* reducedResolution */);
2088 final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
2089 allowTaskSnapshot, activityCreated, fromRecents, snapshot);
2090
2091 if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
2092 return createSnapshot(snapshot);
2093 }
2094
2095 // If this is a translucent window, then don't show a starting window -- the current
2096 // effect (a full-screen opaque starting window that fades away to the real contents
2097 // when it is ready) does not work for this.
2098 if (DEBUG_STARTING_WINDOW) {
2099 Slog.v(TAG, "Checking theme of starting window: 0x" + Integer.toHexString(theme));
2100 }
2101 if (theme != 0) {
2102 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
2103 com.android.internal.R.styleable.Window,
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002104 mWmService.mCurrentUserId);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002105 if (ent == null) {
2106 // Whoops! App doesn't exist. Um. Okay. We'll just pretend like we didn't
2107 // see that.
2108 return false;
2109 }
2110 final boolean windowIsTranslucent = ent.array.getBoolean(
2111 com.android.internal.R.styleable.Window_windowIsTranslucent, false);
2112 final boolean windowIsFloating = ent.array.getBoolean(
2113 com.android.internal.R.styleable.Window_windowIsFloating, false);
2114 final boolean windowShowWallpaper = ent.array.getBoolean(
2115 com.android.internal.R.styleable.Window_windowShowWallpaper, false);
2116 final boolean windowDisableStarting = ent.array.getBoolean(
2117 com.android.internal.R.styleable.Window_windowDisablePreview, false);
2118 if (DEBUG_STARTING_WINDOW) {
2119 Slog.v(TAG, "Translucent=" + windowIsTranslucent
2120 + " Floating=" + windowIsFloating
2121 + " ShowWallpaper=" + windowShowWallpaper);
2122 }
2123 if (windowIsTranslucent) {
2124 return false;
2125 }
2126 if (windowIsFloating || windowDisableStarting) {
2127 return false;
2128 }
2129 if (windowShowWallpaper) {
2130 if (getDisplayContent().mWallpaperController
2131 .getWallpaperTarget() == null) {
2132 // If this theme is requesting a wallpaper, and the wallpaper
2133 // is not currently visible, then this effectively serves as
2134 // an opaque window and our starting window transition animation
2135 // can still work. We just need to make sure the starting window
2136 // is also showing the wallpaper.
2137 windowFlags |= FLAG_SHOW_WALLPAPER;
2138 } else {
2139 return false;
2140 }
2141 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002142 }
Yunfan Chen8a8c0ed2018-12-18 16:46:32 -08002143
2144 if (transferStartingWindow(transferFrom)) {
2145 return true;
2146 }
2147
2148 // There is no existing starting window, and we don't want to create a splash screen, so
2149 // that's it!
2150 if (type != STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
2151 return false;
2152 }
2153
2154 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SplashScreenStartingData");
chaviwa8f07a72019-05-01 16:25:39 -07002155 mStartingData = new SplashScreenStartingData(mWmService, pkg,
Yunfan Chen8a8c0ed2018-12-18 16:46:32 -08002156 theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
2157 getMergedOverrideConfiguration());
2158 scheduleAddStartingWindow();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002159 return true;
2160 }
2161
2162
2163 private boolean createSnapshot(ActivityManager.TaskSnapshot snapshot) {
2164 if (snapshot == null) {
2165 return false;
2166 }
2167
2168 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SnapshotStartingData");
chaviwa8f07a72019-05-01 16:25:39 -07002169 mStartingData = new SnapshotStartingData(mWmService, snapshot);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002170 scheduleAddStartingWindow();
2171 return true;
2172 }
2173
2174 void scheduleAddStartingWindow() {
2175 // Note: we really want to do sendMessageAtFrontOfQueue() because we
2176 // want to process the message ASAP, before any other queued
2177 // messages.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002178 if (!mWmService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002179 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING");
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002180 mWmService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002181 }
2182 }
2183
2184 private final Runnable mAddStartingWindow = new Runnable() {
2185
2186 @Override
2187 public void run() {
chaviwa8f07a72019-05-01 16:25:39 -07002188 // Can be accessed without holding the global lock
2189 final StartingData startingData;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002190 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002191 // There can only be one adding request, silly caller!
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002192 mWmService.mAnimationHandler.removeCallbacks(this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002193
chaviwa8f07a72019-05-01 16:25:39 -07002194 if (mStartingData == null) {
2195 // Animation has been canceled... do nothing.
2196 if (DEBUG_STARTING_WINDOW) {
2197 Slog.v(TAG, "startingData was nulled out before handling"
2198 + " mAddStartingWindow: " + AppWindowToken.this);
2199 }
2200 return;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002201 }
chaviwa8f07a72019-05-01 16:25:39 -07002202 startingData = mStartingData;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002203 }
2204
2205 if (DEBUG_STARTING_WINDOW) {
2206 Slog.v(TAG, "Add starting " + this + ": startingData=" + startingData);
2207 }
2208
2209 WindowManagerPolicy.StartingSurface surface = null;
2210 try {
2211 surface = startingData.createStartingSurface(AppWindowToken.this);
2212 } catch (Exception e) {
2213 Slog.w(TAG, "Exception when adding starting window", e);
2214 }
2215 if (surface != null) {
2216 boolean abort = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002217 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002218 // If the window was successfully added, then
2219 // we need to remove it.
chaviwa8f07a72019-05-01 16:25:39 -07002220 if (removed || mStartingData == null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002221 if (DEBUG_STARTING_WINDOW) {
2222 Slog.v(TAG, "Aborted starting " + AppWindowToken.this
chaviwa8f07a72019-05-01 16:25:39 -07002223 + ": removed=" + removed + " startingData=" + mStartingData);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002224 }
2225 startingWindow = null;
chaviwa8f07a72019-05-01 16:25:39 -07002226 mStartingData = null;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002227 abort = true;
2228 } else {
2229 startingSurface = surface;
2230 }
2231 if (DEBUG_STARTING_WINDOW && !abort) {
chaviwa8f07a72019-05-01 16:25:39 -07002232 Slog.v(TAG,
2233 "Added starting " + AppWindowToken.this + ": startingWindow="
2234 + startingWindow + " startingView=" + startingSurface);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002235 }
2236 }
2237 if (abort) {
2238 surface.remove();
2239 }
2240 } else if (DEBUG_STARTING_WINDOW) {
2241 Slog.v(TAG, "Surface returned was null: " + AppWindowToken.this);
2242 }
2243 }
2244 };
2245
2246 private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
2247 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents,
2248 ActivityManager.TaskSnapshot snapshot) {
2249 if (getDisplayContent().mAppTransition.getAppTransition()
2250 == TRANSIT_DOCK_TASK_FROM_RECENTS) {
2251 // TODO(b/34099271): Remove this statement to add back the starting window and figure
2252 // out why it causes flickering, the starting window appears over the thumbnail while
2253 // the docked from recents transition occurs
2254 return STARTING_WINDOW_TYPE_NONE;
2255 } else if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
2256 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2257 } else if (taskSwitch && allowTaskSnapshot) {
Kevin716a9db2018-12-18 16:53:39 -08002258 if (mWmService.mLowRamTaskSnapshotsAndRecents) {
Kevin58b47f12018-12-17 14:09:01 -08002259 // For low RAM devices, we use the splash screen starting window instead of the
2260 // task snapshot starting window.
2261 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2262 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002263 return snapshot == null ? STARTING_WINDOW_TYPE_NONE
2264 : snapshotOrientationSameAsTask(snapshot) || fromRecents
2265 ? STARTING_WINDOW_TYPE_SNAPSHOT : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2266 } else {
2267 return STARTING_WINDOW_TYPE_NONE;
2268 }
2269 }
2270
2271
2272 private boolean snapshotOrientationSameAsTask(ActivityManager.TaskSnapshot snapshot) {
2273 if (snapshot == null) {
2274 return false;
2275 }
2276 return getTask().getConfiguration().orientation == snapshot.getOrientation();
2277 }
2278
2279 void removeStartingWindow() {
2280 if (startingWindow == null) {
chaviwa8f07a72019-05-01 16:25:39 -07002281 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002282 // Starting window has not been added yet, but it is scheduled to be added.
2283 // Go ahead and cancel the request.
2284 if (DEBUG_STARTING_WINDOW) {
2285 Slog.v(TAG_WM, "Clearing startingData for token=" + this);
2286 }
chaviwa8f07a72019-05-01 16:25:39 -07002287 mStartingData = null;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002288 }
2289 return;
2290 }
2291
2292 final WindowManagerPolicy.StartingSurface surface;
chaviwa8f07a72019-05-01 16:25:39 -07002293 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002294 surface = startingSurface;
chaviwa8f07a72019-05-01 16:25:39 -07002295 mStartingData = null;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002296 startingSurface = null;
2297 startingWindow = null;
2298 startingDisplayed = false;
2299 if (surface == null) {
2300 if (DEBUG_STARTING_WINDOW) {
2301 Slog.v(TAG_WM, "startingWindow was set but startingSurface==null, couldn't "
2302 + "remove");
2303 }
2304 return;
2305 }
2306 } else {
2307 if (DEBUG_STARTING_WINDOW) {
2308 Slog.v(TAG_WM, "Tried to remove starting window but startingWindow was null:"
2309 + this);
2310 }
2311 return;
2312 }
2313
2314 if (DEBUG_STARTING_WINDOW) {
2315 Slog.v(TAG_WM, "Schedule remove starting " + this
2316 + " startingWindow=" + startingWindow
2317 + " startingView=" + startingSurface
2318 + " Callers=" + Debug.getCallers(5));
2319 }
2320
2321 // Use the same thread to remove the window as we used to add it, as otherwise we end up
2322 // with things in the view hierarchy being called from different threads.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002323 mWmService.mAnimationHandler.post(() -> {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002324 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Removing startingView=" + surface);
2325 try {
2326 surface.remove();
2327 } catch (Exception e) {
2328 Slog.w(TAG_WM, "Exception when removing starting window", e);
2329 }
2330 });
2331 }
2332
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002333 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -07002334 boolean fillsParent() {
2335 return mFillsParent;
2336 }
2337
2338 void setFillsParent(boolean fillsParent) {
2339 mFillsParent = fillsParent;
2340 }
2341
Jorim Jaggife762342016-10-13 14:33:27 +02002342 boolean containsDismissKeyguardWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002343 // Window state is transient during relaunch. We are not guaranteed to be frozen during the
2344 // entirety of the relaunch.
2345 if (isRelaunching()) {
2346 return mLastContainsDismissKeyguardWindow;
2347 }
2348
Jorim Jaggife762342016-10-13 14:33:27 +02002349 for (int i = mChildren.size() - 1; i >= 0; i--) {
2350 if ((mChildren.get(i).mAttrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
2351 return true;
2352 }
2353 }
2354 return false;
2355 }
2356
2357 boolean containsShowWhenLockedWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002358 // When we are relaunching, it is possible for us to be unfrozen before our previous
2359 // windows have been added back. Using the cached value ensures that our previous
2360 // showWhenLocked preference is honored until relaunching is complete.
2361 if (isRelaunching()) {
2362 return mLastContainsShowWhenLockedWindow;
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_SHOW_WHEN_LOCKED) != 0) {
2367 return true;
2368 }
2369 }
Bryce Lee081554b2017-05-25 07:52:12 -07002370
Jorim Jaggife762342016-10-13 14:33:27 +02002371 return false;
2372 }
2373
2374 void checkKeyguardFlagsChanged() {
2375 final boolean containsDismissKeyguard = containsDismissKeyguardWindow();
2376 final boolean containsShowWhenLocked = containsShowWhenLockedWindow();
2377 if (containsDismissKeyguard != mLastContainsDismissKeyguardWindow
2378 || containsShowWhenLocked != mLastContainsShowWhenLockedWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002379 mWmService.notifyKeyguardFlagsChanged(null /* callback */,
lumark588a3e82018-07-20 18:53:54 +08002380 getDisplayContent().getDisplayId());
Jorim Jaggife762342016-10-13 14:33:27 +02002381 }
2382 mLastContainsDismissKeyguardWindow = containsDismissKeyguard;
2383 mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
2384 }
2385
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002386 WindowState getImeTargetBelowWindow(WindowState w) {
2387 final int index = mChildren.indexOf(w);
2388 if (index > 0) {
2389 final WindowState target = mChildren.get(index - 1);
2390 if (target.canBeImeTarget()) {
2391 return target;
2392 }
2393 }
2394 return null;
2395 }
2396
2397 WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
2398 WindowState candidate = null;
2399 for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
2400 final WindowState w = mChildren.get(i);
2401 if (w.mRemoved) {
2402 continue;
2403 }
Jorim Jaggi35d328a2018-08-14 17:00:20 +02002404 if (candidate == null) {
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002405 candidate = w;
2406 }
2407 }
2408 return candidate;
2409 }
2410
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002411 /**
2412 * See {@link Activity#setDisablePreviewScreenshots}.
2413 */
2414 void setDisablePreviewScreenshots(boolean disable) {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002415 mDisablePreviewScreenshots = disable;
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002416 }
2417
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002418 /**
chaviwd3bf08d2017-08-01 17:24:59 -07002419 * Sets whether the current launch can turn the screen on. See {@link #canTurnScreenOn()}
2420 */
2421 void setCanTurnScreenOn(boolean canTurnScreenOn) {
2422 mCanTurnScreenOn = canTurnScreenOn;
2423 }
2424
2425 /**
2426 * Indicates whether the current launch can turn the screen on. This is to prevent multiple
2427 * relayouts from turning the screen back on. The screen should only turn on at most
2428 * once per activity resume.
2429 *
2430 * @return true if the screen can be turned on.
2431 */
2432 boolean canTurnScreenOn() {
2433 return mCanTurnScreenOn;
2434 }
2435
2436 /**
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002437 * Retrieves whether we'd like to generate a snapshot that's based solely on the theme. This is
2438 * the case when preview screenshots are disabled {@link #setDisablePreviewScreenshots} or when
2439 * we can't take a snapshot for other reasons, for example, if we have a secure window.
2440 *
2441 * @return True if we need to generate an app theme snapshot, false if we'd like to take a real
2442 * screenshot.
2443 */
2444 boolean shouldUseAppThemeSnapshot() {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002445 return mDisablePreviewScreenshots || forAllWindows(w -> (w.mAttrs.flags & FLAG_SECURE) != 0,
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002446 true /* topToBottom */);
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002447 }
2448
Jorim Jaggibe418292018-03-26 16:14:12 +02002449 SurfaceControl getAppAnimationLayer() {
Jorim Jaggi391790622018-04-18 15:30:44 +02002450 return getAppAnimationLayer(isActivityTypeHome() ? ANIMATION_LAYER_HOME
2451 : needsZBoost() ? ANIMATION_LAYER_BOOSTED
2452 : ANIMATION_LAYER_STANDARD);
Jorim Jaggibe418292018-03-26 16:14:12 +02002453 }
2454
chaviw23ee71c2017-12-18 11:29:41 -08002455 @Override
Jorim Jaggi596a1992017-12-29 14:48:02 +01002456 public SurfaceControl getAnimationLeashParent() {
Robert Carrb9506032018-02-13 13:54:00 -08002457 // All normal app transitions take place in an animation layer which is below the pinned
2458 // stack but may be above the parent stacks of the given animating apps.
2459 // For transitions in the pinned stack (menu activity) we just let them occur as a child
2460 // of the pinned stack.
2461 if (!inPinnedWindowingMode()) {
2462 return getAppAnimationLayer();
2463 } else {
2464 return getStack().getSurfaceControl();
2465 }
chaviw23ee71c2017-12-18 11:29:41 -08002466 }
2467
lumarkb5a78b32019-04-25 20:31:30 +08002468
2469 @VisibleForTesting
2470 boolean shouldAnimate(int transit) {
Jorim Jaggic6976f02018-04-18 16:31:07 +02002471 final boolean isSplitScreenPrimary =
2472 getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
2473 final boolean allowSplitScreenPrimaryAnimation = transit != TRANSIT_WALLPAPER_OPEN;
2474
lumarkb5a78b32019-04-25 20:31:30 +08002475 // Don't animate while the task runs recents animation but only if we are in the mode
2476 // where we cancel with deferred screenshot, which means that the controller has
2477 // transformed the task.
lumark54284462019-03-05 20:44:27 +08002478 final RecentsAnimationController controller = mWmService.getRecentsAnimationController();
lumarkb5a78b32019-04-25 20:31:30 +08002479 if (controller != null && controller.isAnimatingTask(getTask())
Winson Chung7a545ae2019-07-16 14:52:13 -07002480 && controller.shouldDeferCancelUntilNextTransition()) {
lumark54284462019-03-05 20:44:27 +08002481 return false;
2482 }
2483
Jorim Jaggic6976f02018-04-18 16:31:07 +02002484 // We animate always if it's not split screen primary, and only some special cases in split
2485 // screen primary because it causes issues with stack clipping when we run an un-minimize
2486 // animation at the same time.
2487 return !isSplitScreenPrimary || allowSplitScreenPrimaryAnimation;
2488 }
2489
Vishnu Naira2977262018-07-26 13:31:26 -07002490 /**
2491 * Creates a layer to apply crop to an animation.
2492 */
2493 private SurfaceControl createAnimationBoundsLayer(Transaction t) {
2494 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.i(TAG, "Creating animation bounds layer");
2495 final SurfaceControl.Builder builder = makeAnimationLeash()
2496 .setParent(getAnimationLeashParent())
Vishnu Naire86bd982018-11-28 13:23:17 -08002497 .setName(getSurfaceControl() + " - animation-bounds");
Vishnu Naira2977262018-07-26 13:31:26 -07002498 final SurfaceControl boundsLayer = builder.build();
2499 t.show(boundsLayer);
2500 return boundsLayer;
2501 }
2502
Evan Roskyed6767f2018-10-26 17:21:06 -07002503 @Override
2504 Rect getDisplayedBounds() {
2505 final Task task = getTask();
2506 if (task != null) {
2507 final Rect overrideDisplayedBounds = task.getOverrideDisplayedBounds();
2508 if (!overrideDisplayedBounds.isEmpty()) {
2509 return overrideDisplayedBounds;
2510 }
2511 }
2512 return getBounds();
2513 }
2514
Evan Rosky641daea2019-04-24 14:45:24 -07002515 @VisibleForTesting
2516 Rect getAnimationBounds(int appStackClipMode) {
2517 if (appStackClipMode == STACK_CLIP_BEFORE_ANIM && getStack() != null) {
2518 // Using the stack bounds here effectively applies the clipping before animation.
2519 return getStack().getBounds();
2520 }
2521 // Use task-bounds if available so that activity-level letterbox (maxAspectRatio) is
2522 // included in the animation.
2523 return getTask() != null ? getTask().getBounds() : getBounds();
2524 }
2525
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002526 boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter,
2527 boolean isVoiceInteraction) {
2528
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002529 if (mWmService.mDisableTransitionAnimation || !shouldAnimate(transit)) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002530 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
Jorim Jaggic6976f02018-04-18 16:31:07 +02002531 Slog.v(TAG_WM, "applyAnimation: transition animation is disabled or skipped."
2532 + " atoken=" + this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002533 }
2534 cancelAnimation();
2535 return false;
2536 }
2537
2538 // Only apply an animation if the display isn't frozen. If it is frozen, there is no reason
2539 // to animate and it can cause strange artifacts when we unfreeze the display if some
2540 // different animation is running.
2541 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#applyAnimationLocked");
2542 if (okToAnimate()) {
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002543 final AnimationAdapter adapter;
Evan Rosky2289ba12018-11-19 18:28:18 -08002544 AnimationAdapter thumbnailAdapter = null;
Evan Rosky4fb1e912019-03-06 13:54:43 -08002545
Evan Rosky641daea2019-04-24 14:45:24 -07002546 final int appStackClipMode =
2547 getDisplayContent().mAppTransition.getAppStackClipMode();
2548
2549 // Separate position and size for use in animators.
2550 mTmpRect.set(getAnimationBounds(appStackClipMode));
Evan Rosky4fb1e912019-03-06 13:54:43 -08002551 mTmpPoint.set(mTmpRect.left, mTmpRect.top);
2552 mTmpRect.offsetTo(0, 0);
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002553
Evan Roskyec9488c2019-03-01 19:32:12 -08002554 final boolean isChanging = AppTransition.isChangeTransit(transit) && enter
2555 && getDisplayContent().mChangingApps.contains(this);
Evan Rosky2289ba12018-11-19 18:28:18 -08002556
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002557 // Delaying animation start isn't compatible with remote animations at all.
lumark588a3e82018-07-20 18:53:54 +08002558 if (getDisplayContent().mAppTransition.getRemoteAnimationController() != null
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002559 && !mSurfaceAnimator.isAnimationStartDelayed()) {
Evan Rosky2289ba12018-11-19 18:28:18 -08002560 RemoteAnimationRecord adapters =
2561 getDisplayContent().mAppTransition.getRemoteAnimationController()
2562 .createRemoteAnimationRecord(this, mTmpPoint, mTmpRect,
2563 (isChanging ? mTransitStartRect : null));
2564 adapter = adapters.mAdapter;
2565 thumbnailAdapter = adapters.mThumbnailAdapter;
2566 } else if (isChanging) {
Evan Roskycf76bed2019-01-15 10:33:58 -08002567 final float durationScale = mWmService.getTransitionAnimationScaleLocked();
Evan Rosky2289ba12018-11-19 18:28:18 -08002568 mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y);
2569 adapter = new LocalAnimationAdapter(
2570 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
Evan Roskycf76bed2019-01-15 10:33:58 -08002571 getDisplayContent().getDisplayInfo(), durationScale,
Evan Rosky2289ba12018-11-19 18:28:18 -08002572 true /* isAppAnimation */, false /* isThumbnail */),
2573 mWmService.mSurfaceAnimationRunner);
Evan Rosky966759f2019-01-15 10:33:58 -08002574 if (mThumbnail != null) {
2575 thumbnailAdapter = new LocalAnimationAdapter(
2576 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
Evan Roskycf76bed2019-01-15 10:33:58 -08002577 getDisplayContent().getDisplayInfo(), durationScale,
Evan Rosky966759f2019-01-15 10:33:58 -08002578 true /* isAppAnimation */, true /* isThumbnail */),
2579 mWmService.mSurfaceAnimationRunner);
2580 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002581 mTransit = transit;
2582 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002583 } else {
Vishnu Naira2977262018-07-26 13:31:26 -07002584 mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM);
2585
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002586 final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
2587 if (a != null) {
Lucas Dupin95acf432019-04-29 17:55:38 -07002588 // Only apply corner radius to animation if we're not in multi window mode.
2589 // We don't want rounded corners when in pip or split screen.
2590 final float windowCornerRadius = !inMultiWindowMode()
2591 ? getDisplayContent().getWindowCornerRadius()
2592 : 0;
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002593 adapter = new LocalAnimationAdapter(
2594 new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
lumark588a3e82018-07-20 18:53:54 +08002595 getDisplayContent().mAppTransition.canSkipFirstFrame(),
Vishnu Naira2977262018-07-26 13:31:26 -07002596 appStackClipMode,
Lucas Dupin3e1dc202018-12-02 15:14:20 -08002597 true /* isAppAnimation */,
Lucas Dupin95acf432019-04-29 17:55:38 -07002598 windowCornerRadius),
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002599 mWmService.mSurfaceAnimationRunner);
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002600 if (a.getZAdjustment() == Animation.ZORDER_TOP) {
2601 mNeedsZBoost = true;
2602 }
2603 mTransit = transit;
lumark588a3e82018-07-20 18:53:54 +08002604 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002605 } else {
2606 adapter = null;
chaviw23ee71c2017-12-18 11:29:41 -08002607 }
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002608 }
2609 if (adapter != null) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002610 startAnimation(getPendingTransaction(), adapter, !isVisible());
Jorim Jaggi82c17862018-02-21 17:50:18 +01002611 if (adapter.getShowWallpaper()) {
2612 mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2613 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002614 if (thumbnailAdapter != null) {
2615 mThumbnail.startAnimation(
2616 getPendingTransaction(), thumbnailAdapter, !isVisible());
2617 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002618 }
2619 } else {
2620 cancelAnimation();
2621 }
2622 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2623
2624 return isReallyAnimating();
2625 }
2626
2627 private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
2628 boolean isVoiceInteraction) {
2629 final DisplayContent displayContent = getTask().getDisplayContent();
2630 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2631 final int width = displayInfo.appWidth;
2632 final int height = displayInfo.appHeight;
2633 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG_WM,
2634 "applyAnimation: atoken=" + this);
2635
2636 // Determine the visible rect to calculate the thumbnail clip
2637 final WindowState win = findMainWindow();
2638 final Rect frame = new Rect(0, 0, width, height);
2639 final Rect displayFrame = new Rect(0, 0,
2640 displayInfo.logicalWidth, displayInfo.logicalHeight);
2641 final Rect insets = new Rect();
2642 final Rect stableInsets = new Rect();
2643 Rect surfaceInsets = null;
2644 final boolean freeform = win != null && win.inFreeformWindowingMode();
2645 if (win != null) {
2646 // Containing frame will usually cover the whole screen, including dialog windows.
2647 // For freeform workspace windows it will not cover the whole screen and it also
2648 // won't exactly match the final freeform window frame (e.g. when overlapping with
2649 // the status bar). In that case we need to use the final frame.
2650 if (freeform) {
chaviw492139a2018-07-16 16:07:35 -07002651 frame.set(win.getFrameLw());
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002652 } else if (win.isLetterboxedAppWindow()) {
2653 frame.set(getTask().getBounds());
Winson Chungc1674272018-02-21 10:15:17 -08002654 } else if (win.isDockedResizing()) {
2655 // If we are animating while docked resizing, then use the stack bounds as the
2656 // animation target (which will be different than the task bounds)
2657 frame.set(getTask().getParent().getBounds());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002658 } else {
chaviw553b0212018-07-12 13:37:01 -07002659 frame.set(win.getContainingFrame());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002660 }
2661 surfaceInsets = win.getAttrs().surfaceInsets;
Adrian Roos20e07892018-02-23 19:12:01 +01002662 // XXX(b/72757033): These are insets relative to the window frame, but we're really
2663 // interested in the insets relative to the frame we chose in the if-blocks above.
chaviw9c81e632018-07-31 11:17:52 -07002664 win.getContentInsets(insets);
2665 win.getStableInsets(stableInsets);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002666 }
2667
2668 if (mLaunchTaskBehind) {
2669 // Differentiate the two animations. This one which is briefly on the screen
2670 // gets the !enter animation, and the other activity which remains on the
2671 // screen gets the enter animation. Both appear in the mOpeningApps set.
2672 enter = false;
2673 }
2674 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "Loading animation for app transition."
2675 + " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter
2676 + " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets);
2677 final Configuration displayConfig = displayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08002678 final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002679 displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
2680 surfaceInsets, stableInsets, isVoiceInteraction, freeform, getTask().mTaskId);
2681 if (a != null) {
2682 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
2683 final int containingWidth = frame.width();
2684 final int containingHeight = frame.height();
2685 a.initialize(containingWidth, containingHeight, width, height);
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002686 a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002687 }
2688 return a;
2689 }
2690
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002691 @Override
Jorim Jaggi6de61012018-03-19 14:53:23 +01002692 public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
2693 return mAnimatingAppWindowTokenRegistry != null
2694 && mAnimatingAppWindowTokenRegistry.notifyAboutToFinish(
2695 this, endDeferFinishCallback);
2696 }
2697
2698 @Override
lumarkf6f34942019-04-29 16:56:50 +08002699 public void onAnimationLeashLost(Transaction t) {
2700 super.onAnimationLeashLost(t);
Vishnu Naira2977262018-07-26 13:31:26 -07002701 if (mAnimationBoundsLayer != null) {
Robert Carr71200f22019-02-05 09:44:53 -08002702 t.remove(mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002703 mAnimationBoundsLayer = null;
2704 }
2705
Jorim Jaggi6de61012018-03-19 14:53:23 +01002706 if (mAnimatingAppWindowTokenRegistry != null) {
2707 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
2708 }
2709 }
2710
2711 @Override
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002712 protected void setLayer(Transaction t, int layer) {
2713 if (!mSurfaceAnimator.hasLeash()) {
2714 t.setLayer(mSurfaceControl, layer);
2715 }
2716 }
2717
2718 @Override
2719 protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
2720 if (!mSurfaceAnimator.hasLeash()) {
2721 t.setRelativeLayer(mSurfaceControl, relativeTo, layer);
2722 }
2723 }
2724
2725 @Override
2726 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
2727 if (!mSurfaceAnimator.hasLeash()) {
Robert Carr10584fa2019-01-14 15:55:19 -08002728 t.reparent(mSurfaceControl, newParent);
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002729 }
2730 }
2731
2732 @Override
2733 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002734 // The leash is parented to the animation layer. We need to preserve the z-order by using
2735 // the prefix order index, but we boost if necessary.
Robert Carrb9506032018-02-13 13:54:00 -08002736 int layer = 0;
2737 if (!inPinnedWindowingMode()) {
2738 layer = getPrefixOrderIndex();
2739 } else {
2740 // Pinned stacks have animations take place within themselves rather than an animation
2741 // layer so we need to preserve the order relative to the stack (e.g. the order of our
2742 // task/parent).
2743 layer = getParent().getPrefixOrderIndex();
2744 }
2745
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002746 if (mNeedsZBoost) {
2747 layer += Z_BOOST_BASE;
2748 }
Jorim Jaggi9cd99132019-04-24 17:41:35 +02002749 if (!mNeedsAnimationBoundsLayer) {
2750 leash.setLayer(layer);
2751 }
Robert Carr2f8aa392018-01-31 14:46:51 -08002752
2753 final DisplayContent dc = getDisplayContent();
Jorim Jaggibe418292018-03-26 16:14:12 +02002754 dc.assignStackOrdering();
Evan Rosky2289ba12018-11-19 18:28:18 -08002755
2756 if (leash == mTransitChangeLeash) {
2757 // This is a temporary state so skip any animation notifications
2758 return;
2759 } else if (mTransitChangeLeash != null) {
2760 // unparent mTransitChangeLeash for clean-up
Evan Rosky25b56192019-02-06 16:10:56 -08002761 clearChangeLeash(t, false /* cancel */);
Evan Rosky2289ba12018-11-19 18:28:18 -08002762 }
2763
Jorim Jaggi6de61012018-03-19 14:53:23 +01002764 if (mAnimatingAppWindowTokenRegistry != null) {
2765 mAnimatingAppWindowTokenRegistry.notifyStarting(this);
2766 }
Vishnu Naira2977262018-07-26 13:31:26 -07002767
2768 // If the animation needs to be cropped then an animation bounds layer is created as a child
2769 // of the pinned stack or animation layer. The leash is then reparented to this new layer.
2770 if (mNeedsAnimationBoundsLayer) {
Evan Rosky7735d352019-03-18 17:27:27 -07002771 mTmpRect.setEmpty();
2772 final Task task = getTask();
2773 if (getDisplayContent().mAppTransitionController.isTransitWithinTask(
2774 getTransit(), task)) {
2775 task.getBounds(mTmpRect);
2776 } else {
2777 final TaskStack stack = getStack();
2778 if (stack == null) {
2779 return;
2780 }
2781 // Set clip rect to stack bounds.
2782 stack.getBounds(mTmpRect);
Vishnu Naira2977262018-07-26 13:31:26 -07002783 }
2784 mAnimationBoundsLayer = createAnimationBoundsLayer(t);
2785
Vishnu Naira2977262018-07-26 13:31:26 -07002786 // Crop to stack bounds.
2787 t.setWindowCrop(mAnimationBoundsLayer, mTmpRect);
Jorim Jaggi9cd99132019-04-24 17:41:35 +02002788 t.setLayer(mAnimationBoundsLayer, layer);
Vishnu Naira2977262018-07-26 13:31:26 -07002789
2790 // Reparent leash to animation bounds layer.
Robert Carr10584fa2019-01-14 15:55:19 -08002791 t.reparent(leash, mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002792 }
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002793 }
2794
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002795 /**
2796 * This must be called while inside a transaction.
2797 */
2798 void showAllWindowsLocked() {
2799 forAllWindows(windowState -> {
2800 if (DEBUG_VISIBILITY) Slog.v(TAG, "performing show on: " + windowState);
2801 windowState.performShowLocked();
2802 }, false /* traverseTopToBottom */);
Jorim Jaggia5e10572017-11-15 14:36:26 +01002803 }
2804
2805 @Override
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002806 protected void onAnimationFinished() {
2807 super.onAnimationFinished();
2808
Ian8b2822e2019-05-14 11:59:02 -07002809 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#onAnimationFinished");
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002810 mTransit = TRANSIT_UNSET;
2811 mTransitFlags = 0;
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002812 mNeedsZBoost = false;
Vishnu Naira2977262018-07-26 13:31:26 -07002813 mNeedsAnimationBoundsLayer = false;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002814
2815 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER,
2816 "AppWindowToken");
2817
Jorim Jaggi988f6682017-11-17 17:46:43 +01002818 clearThumbnail();
Jorim Jaggi752cd822018-03-29 16:29:18 +02002819 setClientHidden(isHidden() && hiddenRequested);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002820
lumarkff0ab692018-11-05 20:32:30 +08002821 getDisplayContent().computeImeTargetIfNeeded(this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002822
2823 if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + this
2824 + ": reportedVisible=" + reportedVisible
2825 + " okToDisplay=" + okToDisplay()
2826 + " okToAnimate=" + okToAnimate()
2827 + " startingDisplayed=" + startingDisplayed);
2828
Evan Rosky2289ba12018-11-19 18:28:18 -08002829 // clean up thumbnail window
2830 if (mThumbnail != null) {
2831 mThumbnail.destroy();
2832 mThumbnail = null;
2833 }
2834
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002835 // WindowState.onExitAnimationDone might modify the children list, so make a copy and then
2836 // traverse the copy.
2837 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
2838 children.forEach(WindowState::onExitAnimationDone);
2839
lumark588a3e82018-07-20 18:53:54 +08002840 getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002841 scheduleAnimation();
Jorim Jaggi9b5e3312019-03-01 18:08:00 +01002842
2843 mActivityRecord.onAnimationFinished();
Ian8b2822e2019-05-14 11:59:02 -07002844 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002845 }
2846
2847 @Override
2848 boolean isAppAnimating() {
2849 return isSelfAnimating();
2850 }
2851
2852 @Override
2853 boolean isSelfAnimating() {
2854 // If we are about to start a transition, we also need to be considered animating.
2855 return isWaitingForTransitionStart() || isReallyAnimating();
2856 }
2857
2858 /**
2859 * @return True if and only if we are actually running an animation. Note that
2860 * {@link #isSelfAnimating} also returns true if we are waiting for an animation to
2861 * start.
2862 */
2863 private boolean isReallyAnimating() {
2864 return super.isSelfAnimating();
2865 }
2866
Evan Rosky25b56192019-02-06 16:10:56 -08002867 /**
2868 * @param cancel {@code true} if clearing the leash due to cancelling instead of transferring
2869 * to another leash.
2870 */
2871 private void clearChangeLeash(Transaction t, boolean cancel) {
2872 if (mTransitChangeLeash == null) {
2873 return;
2874 }
2875 if (cancel) {
2876 clearThumbnail();
2877 SurfaceControl sc = getSurfaceControl();
2878 SurfaceControl parentSc = getParentSurfaceControl();
2879 // Don't reparent if surface is getting destroyed
2880 if (parentSc != null && sc != null) {
2881 t.reparent(sc, getParentSurfaceControl());
2882 }
2883 }
2884 t.hide(mTransitChangeLeash);
Evan Rosky08e20932019-05-14 10:54:07 -07002885 t.remove(mTransitChangeLeash);
Evan Rosky25b56192019-02-06 16:10:56 -08002886 mTransitChangeLeash = null;
2887 if (cancel) {
lumarkf6f34942019-04-29 16:56:50 +08002888 onAnimationLeashLost(t);
Evan Rosky25b56192019-02-06 16:10:56 -08002889 }
2890 }
2891
Jorim Jaggi988f6682017-11-17 17:46:43 +01002892 @Override
2893 void cancelAnimation() {
Evan Rosky2289ba12018-11-19 18:28:18 -08002894 cancelAnimationOnly();
Jorim Jaggi988f6682017-11-17 17:46:43 +01002895 clearThumbnail();
Evan Rosky25b56192019-02-06 16:10:56 -08002896 clearChangeLeash(getPendingTransaction(), true /* cancel */);
Evan Rosky2289ba12018-11-19 18:28:18 -08002897 }
2898
2899 /**
2900 * This only cancels the animation. It doesn't do other teardown like cleaning-up thumbnail
2901 * or interim leashes.
2902 * <p>
2903 * Used when canceling in preparation for starting a new animation.
2904 */
2905 void cancelAnimationOnly() {
2906 super.cancelAnimation();
Jorim Jaggi988f6682017-11-17 17:46:43 +01002907 }
2908
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002909 boolean isWaitingForTransitionStart() {
lumark588a3e82018-07-20 18:53:54 +08002910 return getDisplayContent().mAppTransition.isTransitionSet()
2911 && (getDisplayContent().mOpeningApps.contains(this)
Evan Rosky2289ba12018-11-19 18:28:18 -08002912 || getDisplayContent().mClosingApps.contains(this)
2913 || getDisplayContent().mChangingApps.contains(this));
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002914 }
2915
2916 public int getTransit() {
2917 return mTransit;
2918 }
2919
2920 int getTransitFlags() {
2921 return mTransitFlags;
2922 }
2923
Jorim Jaggi988f6682017-11-17 17:46:43 +01002924 void attachThumbnailAnimation() {
2925 if (!isReallyAnimating()) {
2926 return;
2927 }
2928 final int taskId = getTask().mTaskId;
2929 final GraphicBuffer thumbnailHeader =
lumark588a3e82018-07-20 18:53:54 +08002930 getDisplayContent().mAppTransition.getAppTransitionThumbnailHeader(taskId);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002931 if (thumbnailHeader == null) {
2932 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG, "No thumbnail header bitmap for: " + taskId);
2933 return;
2934 }
2935 clearThumbnail();
2936 mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnailHeader);
2937 mThumbnail.startAnimation(getPendingTransaction(), loadThumbnailAnimation(thumbnailHeader));
2938 }
2939
Tony Mak64b8d562017-12-28 17:44:02 +00002940 /**
2941 * Attaches a surface with a thumbnail for the
2942 * {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation.
2943 */
2944 void attachCrossProfileAppsThumbnailAnimation() {
2945 if (!isReallyAnimating()) {
2946 return;
2947 }
2948 clearThumbnail();
2949
2950 final WindowState win = findMainWindow();
2951 if (win == null) {
2952 return;
2953 }
chaviw492139a2018-07-16 16:07:35 -07002954 final Rect frame = win.getFrameLw();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002955 final int thumbnailDrawableRes = getTask().mUserId == mWmService.mCurrentUserId
Tony Mak64b8d562017-12-28 17:44:02 +00002956 ? R.drawable.ic_account_circle
Tony Makda4af232018-04-27 11:01:10 +01002957 : R.drawable.ic_corp_badge;
Tony Mak64b8d562017-12-28 17:44:02 +00002958 final GraphicBuffer thumbnail =
lumark588a3e82018-07-20 18:53:54 +08002959 getDisplayContent().mAppTransition
Tony Mak64b8d562017-12-28 17:44:02 +00002960 .createCrossProfileAppsThumbnail(thumbnailDrawableRes, frame);
2961 if (thumbnail == null) {
2962 return;
2963 }
2964 mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnail);
2965 final Animation animation =
lumark588a3e82018-07-20 18:53:54 +08002966 getDisplayContent().mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(
chaviw492139a2018-07-16 16:07:35 -07002967 win.getFrameLw());
Tony Mak64b8d562017-12-28 17:44:02 +00002968 mThumbnail.startAnimation(getPendingTransaction(), animation, new Point(frame.left,
2969 frame.top));
2970 }
2971
Jorim Jaggi988f6682017-11-17 17:46:43 +01002972 private Animation loadThumbnailAnimation(GraphicBuffer thumbnailHeader) {
2973 final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
2974
2975 // If this is a multi-window scenario, we use the windows frame as
2976 // destination of the thumbnail header animation. If this is a full screen
2977 // window scenario, we use the whole display as the target.
2978 WindowState win = findMainWindow();
2979 Rect appRect = win != null ? win.getContentFrameLw() :
2980 new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
chaviw9c81e632018-07-31 11:17:52 -07002981 final Rect insets = win != null ? win.getContentInsets() : null;
Jorim Jaggi988f6682017-11-17 17:46:43 +01002982 final Configuration displayConfig = mDisplayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08002983 return getDisplayContent().mAppTransition.createThumbnailAspectScaleAnimationLocked(
Jorim Jaggi988f6682017-11-17 17:46:43 +01002984 appRect, insets, thumbnailHeader, getTask().mTaskId, displayConfig.uiMode,
2985 displayConfig.orientation);
2986 }
2987
2988 private void clearThumbnail() {
2989 if (mThumbnail == null) {
2990 return;
2991 }
2992 mThumbnail.destroy();
2993 mThumbnail = null;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002994 }
2995
Jorim Jaggif84e2f62018-01-16 14:17:59 +01002996 void registerRemoteAnimations(RemoteAnimationDefinition definition) {
2997 mRemoteAnimationDefinition = definition;
2998 }
2999
3000 RemoteAnimationDefinition getRemoteAnimationDefinition() {
3001 return mRemoteAnimationDefinition;
3002 }
3003
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003004 @Override
3005 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
3006 super.dump(pw, prefix, dumpAll);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003007 if (appToken != null) {
Wale Ogunwale72919d22016-12-08 18:58:50 -08003008 pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003009 }
Winson Chung48b25652018-10-22 14:04:30 -07003010 pw.println(prefix + "component=" + mActivityComponent.flattenToShortString());
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08003011 pw.print(prefix); pw.print("task="); pw.println(getTask());
Wale Ogunwale51362492016-09-08 17:49:17 -07003012 pw.print(prefix); pw.print(" mFillsParent="); pw.print(mFillsParent);
3013 pw.print(" mOrientation="); pw.println(mOrientation);
Wale Ogunwale89973222017-04-23 18:39:45 -07003014 pw.println(prefix + "hiddenRequested=" + hiddenRequested + " mClientHidden=" + mClientHidden
3015 + ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "")
3016 + " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible);
Craig Mautner59431632012-04-04 11:56:44 -07003017 if (paused) {
3018 pw.print(prefix); pw.print("paused="); pw.println(paused);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003019 }
Wale Ogunwale9017ec02016-02-25 08:55:25 -08003020 if (mAppStopped) {
3021 pw.print(prefix); pw.print("mAppStopped="); pw.println(mAppStopped);
3022 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07003023 if (mNumInterestingWindows != 0 || mNumDrawnWindows != 0
Jorim Jaggib0fc8172017-11-23 17:04:08 +00003024 || allDrawn || mLastAllDrawn) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07003025 pw.print(prefix); pw.print("mNumInterestingWindows=");
3026 pw.print(mNumInterestingWindows);
3027 pw.print(" mNumDrawnWindows="); pw.print(mNumDrawnWindows);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003028 pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
Craig Mautner6fbda632012-07-03 09:26:39 -07003029 pw.print(" allDrawn="); pw.print(allDrawn);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00003030 pw.print(" lastAllDrawn="); pw.print(mLastAllDrawn);
Craig Mautner6fbda632012-07-03 09:26:39 -07003031 pw.println(")");
3032 }
3033 if (inPendingTransaction) {
3034 pw.print(prefix); pw.print("inPendingTransaction=");
3035 pw.println(inPendingTransaction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003036 }
chaviwa8f07a72019-05-01 16:25:39 -07003037 if (mStartingData != null || removed || firstWindowDrawn || mIsExiting) {
3038 pw.print(prefix); pw.print("startingData="); pw.print(mStartingData);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003039 pw.print(" removed="); pw.print(removed);
Craig Mautner3d7ca312015-01-08 10:56:00 -08003040 pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
Craig Mautner799bc1d2015-01-14 10:33:48 -08003041 pw.print(" mIsExiting="); pw.println(mIsExiting);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003042 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08003043 if (startingWindow != null || startingSurface != null
Wale Ogunwale6c459212017-05-17 08:56:03 -07003044 || startingDisplayed || startingMoved || mHiddenSetFromTransferredStartingWindow) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003045 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08003046 pw.print(" startingSurface="); pw.print(startingSurface);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003047 pw.print(" startingDisplayed="); pw.print(startingDisplayed);
Wale Ogunwale6c459212017-05-17 08:56:03 -07003048 pw.print(" startingMoved="); pw.print(startingMoved);
3049 pw.println(" mHiddenSetFromTransferredStartingWindow="
3050 + mHiddenSetFromTransferredStartingWindow);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003051 }
Jorim Jaggi0429f352015-12-22 16:29:16 +01003052 if (!mFrozenBounds.isEmpty()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08003053 pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
Jorim Jaggi26c8c422016-05-09 19:57:25 -07003054 pw.print(prefix); pw.print("mFrozenMergedConfig="); pw.println(mFrozenMergedConfig);
Chong Zhangd78ddb42016-03-02 17:01:14 -08003055 }
3056 if (mPendingRelaunchCount != 0) {
3057 pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount);
Jorim Jaggi0429f352015-12-22 16:29:16 +01003058 }
Riddle Hsub398da32019-01-21 21:48:16 +08003059 if (mSizeCompatScale != 1f || mSizeCompatBounds != null) {
3060 pw.println(prefix + "mSizeCompatScale=" + mSizeCompatScale + " mSizeCompatBounds="
3061 + mSizeCompatBounds);
3062 }
Wale Ogunwalee287e192017-04-21 09:30:12 -07003063 if (mRemovingFromDisplay) {
3064 pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay);
3065 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003066 }
3067
3068 @Override
3069 void setHidden(boolean hidden) {
3070 super.setHidden(hidden);
Winson Chunge55c0192017-08-24 14:50:48 -07003071
3072 if (hidden) {
3073 // Once the app window is hidden, reset the last saved PiP snap fraction
3074 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(this);
3075 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003076 scheduleAnimation();
3077 }
3078
3079 @Override
3080 void prepareSurfaces() {
3081 // isSelfAnimating also returns true when we are about to start a transition, so we need
3082 // to check super here.
3083 final boolean reallyAnimating = super.isSelfAnimating();
3084 final boolean show = !isHidden() || reallyAnimating;
Robert Carrd8e4fb72019-01-31 11:14:30 -08003085
3086 if (mSurfaceControl != null) {
3087 if (show && !mLastSurfaceShowing) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003088 getPendingTransaction().show(mSurfaceControl);
Robert Carrd8e4fb72019-01-31 11:14:30 -08003089 } else if (!show && mLastSurfaceShowing) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003090 getPendingTransaction().hide(mSurfaceControl);
Robert Carrd8e4fb72019-01-31 11:14:30 -08003091 }
Jorim Jaggi4d1835d2017-08-31 17:28:27 +02003092 }
Jorim Jaggi988f6682017-11-17 17:46:43 +01003093 if (mThumbnail != null) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003094 mThumbnail.setShowing(getPendingTransaction(), show);
Jorim Jaggi988f6682017-11-17 17:46:43 +01003095 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003096 mLastSurfaceShowing = show;
3097 super.prepareSurfaces();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003098 }
3099
Jorim Jaggi77d0f36c2018-03-16 17:49:49 +01003100 /**
3101 * @return Whether our {@link #getSurfaceControl} is currently showing.
3102 */
3103 boolean isSurfaceShowing() {
3104 return mLastSurfaceShowing;
3105 }
3106
Jorim Jaggib0fc8172017-11-23 17:04:08 +00003107 boolean isFreezingScreen() {
3108 return mFreezingScreen;
3109 }
3110
3111 @Override
3112 boolean needsZBoost() {
3113 return mNeedsZBoost || super.needsZBoost();
3114 }
3115
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07003116 @CallSuper
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003117 @Override
Nataniel Borges023ecb52019-01-16 14:15:43 -08003118 public void writeToProto(ProtoOutputStream proto, long fieldId,
3119 @WindowTraceLogLevel int logLevel) {
3120 // Critical log level logs only visible elements to mitigate performance overheard
3121 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
3122 return;
3123 }
3124
Steven Timotiusaf03df62017-07-18 16:56:43 -07003125 final long token = proto.start(fieldId);
3126 writeNameToProto(proto, NAME);
Nataniel Borges023ecb52019-01-16 14:15:43 -08003127 super.writeToProto(proto, WINDOW_TOKEN, logLevel);
Vishnu Nair04ab4392018-01-10 11:00:06 -08003128 proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing);
3129 proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart());
3130 proto.write(IS_REALLY_ANIMATING, isReallyAnimating());
3131 if (mThumbnail != null){
3132 mThumbnail.writeToProto(proto, THUMBNAIL);
3133 }
3134 proto.write(FILLS_PARENT, mFillsParent);
3135 proto.write(APP_STOPPED, mAppStopped);
3136 proto.write(HIDDEN_REQUESTED, hiddenRequested);
3137 proto.write(CLIENT_HIDDEN, mClientHidden);
3138 proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient);
3139 proto.write(REPORTED_DRAWN, reportedDrawn);
3140 proto.write(REPORTED_VISIBLE, reportedVisible);
3141 proto.write(NUM_INTERESTING_WINDOWS, mNumInterestingWindows);
3142 proto.write(NUM_DRAWN_WINDOWS, mNumDrawnWindows);
3143 proto.write(ALL_DRAWN, allDrawn);
3144 proto.write(LAST_ALL_DRAWN, mLastAllDrawn);
3145 proto.write(REMOVED, removed);
Nataniel Borges023ecb52019-01-16 14:15:43 -08003146 if (startingWindow != null) {
Vishnu Nair04ab4392018-01-10 11:00:06 -08003147 startingWindow.writeIdentifierToProto(proto, STARTING_WINDOW);
3148 }
3149 proto.write(STARTING_DISPLAYED, startingDisplayed);
3150 proto.write(STARTING_MOVED, startingMoved);
3151 proto.write(HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW,
3152 mHiddenSetFromTransferredStartingWindow);
3153 for (Rect bounds : mFrozenBounds) {
3154 bounds.writeToProto(proto, FROZEN_BOUNDS);
3155 }
Steven Timotiusaf03df62017-07-18 16:56:43 -07003156 proto.end(token);
3157 }
3158
3159 void writeNameToProto(ProtoOutputStream proto, long fieldId) {
3160 if (appToken == null) {
3161 return;
3162 }
3163 try {
3164 proto.write(fieldId, appToken.getName());
3165 } catch (RemoteException e) {
3166 // This shouldn't happen, but in this case fall back to outputting nothing
3167 Slog.e(TAG, e.toString());
3168 }
3169 }
3170
3171 @Override
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003172 public String toString() {
3173 if (stringName == null) {
3174 StringBuilder sb = new StringBuilder();
3175 sb.append("AppWindowToken{");
3176 sb.append(Integer.toHexString(System.identityHashCode(this)));
3177 sb.append(" token="); sb.append(token); sb.append('}');
3178 stringName = sb.toString();
3179 }
Wale Ogunwaleba51ca22016-09-23 06:06:54 -07003180 return stringName + ((mIsExiting) ? " mIsExiting=" : "");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003181 }
Adrian Roos20e07892018-02-23 19:12:01 +01003182
3183 Rect getLetterboxInsets() {
3184 if (mLetterbox != null) {
3185 return mLetterbox.getInsets();
3186 } else {
3187 return new Rect();
3188 }
3189 }
Adrian Roos23df3a32018-03-15 15:41:13 +01003190
Riddle Hsu69de5fb2019-02-23 01:19:50 +08003191 /** Gets the inner bounds of letterbox. The bounds will be empty if there is no letterbox. */
3192 void getLetterboxInnerBounds(Rect outBounds) {
3193 if (mLetterbox != null) {
3194 outBounds.set(mLetterbox.getInnerFrame());
3195 } else {
3196 outBounds.setEmpty();
3197 }
3198 }
3199
Adrian Roos23df3a32018-03-15 15:41:13 +01003200 /**
Riddle Hsu69de5fb2019-02-23 01:19:50 +08003201 * @return {@code true} if there is a letterbox and any part of that letterbox overlaps with
Adrian Roos23df3a32018-03-15 15:41:13 +01003202 * the given {@code rect}.
3203 */
3204 boolean isLetterboxOverlappingWith(Rect rect) {
3205 return mLetterbox != null && mLetterbox.isOverlappingWith(rect);
3206 }
chaviw4ad54912018-05-30 11:05:44 -07003207
3208 /**
3209 * Sets if this AWT is in the process of closing or entering PIP.
3210 * {@link #mWillCloseOrEnterPip}}
3211 */
3212 void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
3213 mWillCloseOrEnterPip = willCloseOrEnterPip;
3214 }
3215
3216 /**
3217 * Returns whether this AWT is considered closing. Conditions are either
3218 * 1. Is this app animating and was requested to be hidden
3219 * 2. App is delayed closing since it might enter PIP.
3220 */
3221 boolean isClosingOrEnteringPip() {
3222 return (isAnimating() && hiddenRequested) || mWillCloseOrEnterPip;
3223 }
Jorim Jaggiaf0d6d22018-06-08 15:25:35 +02003224
3225 /**
3226 * @return Whether we are allowed to show non-starting windows at the moment. We disallow
3227 * showing windows during transitions in case we have windows that have wide-color-gamut
3228 * color mode set to avoid jank in the middle of the transition.
3229 */
3230 boolean canShowWindows() {
3231 return allDrawn && !(isReallyAnimating() && hasNonDefaultColorWindow());
3232 }
3233
3234 /**
3235 * @return true if we have a window that has a non-default color mode set; false otherwise.
3236 */
3237 private boolean hasNonDefaultColorWindow() {
3238 return forAllWindows(ws -> ws.mAttrs.getColorMode() != COLOR_MODE_DEFAULT,
3239 true /* topToBottom */);
3240 }
lumark588a3e82018-07-20 18:53:54 +08003241
chaviwdcf76ec2019-01-11 16:48:46 -08003242 private void updateColorTransform() {
3243 if (mSurfaceControl != null && mLastAppSaturationInfo != null) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003244 getPendingTransaction().setColorTransform(mSurfaceControl,
3245 mLastAppSaturationInfo.mMatrix, mLastAppSaturationInfo.mTranslation);
chaviwdcf76ec2019-01-11 16:48:46 -08003246 mWmService.scheduleAnimationLocked();
3247 }
3248 }
3249
3250 private static class AppSaturationInfo {
3251 float[] mMatrix = new float[9];
3252 float[] mTranslation = new float[3];
3253
3254 void setSaturation(@Size(9) float[] matrix, @Size(3) float[] translation) {
3255 System.arraycopy(matrix, 0, mMatrix, 0, mMatrix.length);
3256 System.arraycopy(translation, 0, mTranslation, 0, mTranslation.length);
3257 }
3258 }
Jeff Browne9bdb312012-04-05 15:30:10 -07003259}