blob: ed321835121059abde5ea2c8309b844d3d1f08be [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;
Louis Chang37317152019-05-09 09:53:58 +080036import static android.view.WindowManager.TRANSIT_TASK_OPEN_BEHIND;
chaviw9c81e632018-07-31 11:17:52 -070037import static android.view.WindowManager.TRANSIT_UNSET;
Jorim Jaggic6976f02018-04-18 16:31:07 +020038import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
chaviw9c81e632018-07-31 11:17:52 -070039
Adrian Roose99bc052017-11-20 17:55:31 +010040import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
41import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070042import static com.android.server.wm.AppWindowTokenProto.ALL_DRAWN;
43import static com.android.server.wm.AppWindowTokenProto.APP_STOPPED;
44import static com.android.server.wm.AppWindowTokenProto.CLIENT_HIDDEN;
45import static com.android.server.wm.AppWindowTokenProto.DEFER_HIDING_CLIENT;
46import static com.android.server.wm.AppWindowTokenProto.FILLS_PARENT;
47import static com.android.server.wm.AppWindowTokenProto.FROZEN_BOUNDS;
48import static com.android.server.wm.AppWindowTokenProto.HIDDEN_REQUESTED;
49import static com.android.server.wm.AppWindowTokenProto.HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW;
50import static com.android.server.wm.AppWindowTokenProto.IS_REALLY_ANIMATING;
51import static com.android.server.wm.AppWindowTokenProto.IS_WAITING_FOR_TRANSITION_START;
52import static com.android.server.wm.AppWindowTokenProto.LAST_ALL_DRAWN;
53import static com.android.server.wm.AppWindowTokenProto.LAST_SURFACE_SHOWING;
54import static com.android.server.wm.AppWindowTokenProto.NAME;
55import static com.android.server.wm.AppWindowTokenProto.NUM_DRAWN_WINDOWS;
56import static com.android.server.wm.AppWindowTokenProto.NUM_INTERESTING_WINDOWS;
57import static com.android.server.wm.AppWindowTokenProto.REMOVED;
58import static com.android.server.wm.AppWindowTokenProto.REPORTED_DRAWN;
59import static com.android.server.wm.AppWindowTokenProto.REPORTED_VISIBLE;
60import static com.android.server.wm.AppWindowTokenProto.STARTING_DISPLAYED;
61import static com.android.server.wm.AppWindowTokenProto.STARTING_MOVED;
62import static com.android.server.wm.AppWindowTokenProto.STARTING_WINDOW;
63import static com.android.server.wm.AppWindowTokenProto.THUMBNAIL;
64import static com.android.server.wm.AppWindowTokenProto.WINDOW_TOKEN;
chaviw9c81e632018-07-31 11:17:52 -070065import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
66import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
67import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
68import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
69import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
70import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
71import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
72import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
73import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
74import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
75import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
76import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
77import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
78import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN;
79import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
80import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
81import static com.android.server.wm.WindowManagerService.logWithStack;
chaviw15ad49f2019-04-24 15:05:39 -070082import static com.android.server.wm.WindowState.LEGACY_POLICY_VISIBILITY;
Jorim Jaggi6ec52d42019-07-03 15:45:59 +020083import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
Vishnu Naira2977262018-07-26 13:31:26 -070084import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
Evan Rosky641daea2019-04-24 14:45:24 -070085import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080086
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070087import android.annotation.CallSuper;
chaviwdcf76ec2019-01-11 16:48:46 -080088import android.annotation.Size;
Jorim Jaggid635a4a2017-05-03 15:21:26 +020089import android.app.Activity;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080090import android.app.ActivityManager;
Winson Chung48b25652018-10-22 14:04:30 -070091import android.content.ComponentName;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080092import android.content.res.CompatibilityInfo;
Jorim Jaggi26c8c422016-05-09 19:57:25 -070093import android.content.res.Configuration;
Jorim Jaggi988f6682017-11-17 17:46:43 +010094import android.graphics.GraphicBuffer;
Jorim Jaggif5f9e122017-10-24 18:21:09 +020095import android.graphics.Point;
Jorim Jaggi0429f352015-12-22 16:29:16 +010096import android.graphics.Rect;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -070097import android.os.Binder;
Tiger Huang51c5a1d2018-12-11 20:24:51 +080098import android.os.Build;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -080099import android.os.Debug;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700100import android.os.IBinder;
Steven Timotiusaf03df62017-07-18 16:56:43 -0700101import android.os.RemoteException;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800102import android.os.SystemClock;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200103import android.os.Trace;
Evan Rosky2289ba12018-11-19 18:28:18 -0800104import android.util.ArraySet;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800105import android.util.Slog;
Steven Timotiusaf03df62017-07-18 16:56:43 -0700106import android.util.proto.ProtoOutputStream;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200107import android.view.DisplayInfo;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800108import android.view.IApplicationToken;
Robert Carr788f5742018-07-30 17:46:45 -0700109import android.view.InputApplicationHandle;
Evan Rosky966759f2019-01-15 10:33:58 -0800110import android.view.RemoteAnimationAdapter;
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100111import android.view.RemoteAnimationDefinition;
Robert Carr6914f082017-03-20 19:04:30 -0700112import android.view.SurfaceControl;
Tony Mak64b8d562017-12-28 17:44:02 +0000113import android.view.SurfaceControl.Transaction;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800114import android.view.WindowManager;
Jorim Jaggi87fdbcb2017-08-17 13:41:11 +0200115import android.view.WindowManager.LayoutParams;
Tony Mak64b8d562017-12-28 17:44:02 +0000116import android.view.animation.Animation;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800117
Tony Mak64b8d562017-12-28 17:44:02 +0000118import com.android.internal.R;
Riddle Hsua118b3a2018-10-11 22:05:06 +0800119import com.android.internal.annotations.VisibleForTesting;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800120import com.android.internal.util.ToBooleanFunction;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800121import com.android.server.AttributeCache;
chaviwdcf76ec2019-01-11 16:48:46 -0800122import com.android.server.LocalServices;
Christine Franks0ada2772019-02-25 13:54:57 -0800123import com.android.server.display.color.ColorDisplayService;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800124import com.android.server.policy.WindowManagerPolicy;
Adrian Roose99bc052017-11-20 17:55:31 +0100125import com.android.server.policy.WindowManagerPolicy.StartingSurface;
Evan Rosky2289ba12018-11-19 18:28:18 -0800126import com.android.server.wm.RemoteAnimationController.RemoteAnimationRecord;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800127import com.android.server.wm.WindowManagerService.H;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800128
129import java.io.PrintWriter;
chaviwdcf76ec2019-01-11 16:48:46 -0800130import java.lang.ref.WeakReference;
Jorim Jaggi0429f352015-12-22 16:29:16 +0100131import java.util.ArrayDeque;
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800132import java.util.ArrayList;
lumark588a3e82018-07-20 18:53:54 +0800133import java.util.function.Consumer;
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800134
135class AppTokenList extends ArrayList<AppWindowToken> {
136}
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800137
138/**
139 * Version of WindowToken that is specifically for a particular application (or
140 * really activity) that is displaying windows.
141 */
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800142class AppWindowToken extends WindowToken implements WindowManagerService.AppFreezeListener,
143 ConfigurationContainerListener {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800144 private static final String TAG = TAG_WITH_CLASS_NAME ? "AppWindowToken" : TAG_WM;
145
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100146 /**
147 * Value to increment the z-layer when boosting a layer during animations. BOOST in l33tsp34k.
148 */
Jorim Jaggi9cd99132019-04-24 17:41:35 +0200149 @VisibleForTesting static final int Z_BOOST_BASE = 800570000;
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100150
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800151 // Non-null only for application tokens.
152 final IApplicationToken appToken;
Winson Chung48b25652018-10-22 14:04:30 -0700153 final ComponentName mActivityComponent;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800154 final boolean mVoiceInteraction;
Dianne Hackborne30e02f2014-05-27 18:24:45 -0700155
Wale Ogunwale51362492016-09-08 17:49:17 -0700156 /** @see WindowContainer#fillsParent() */
157 private boolean mFillsParent;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800158 boolean mShowForAllUsers;
159 int mTargetSdk;
Craig Mautnera2c77052012-03-26 12:14:43 -0700160
Bryce Lee6d410262017-02-28 15:30:17 -0800161 // Flag set while reparenting to prevent actions normally triggered by an individual parent
162 // change.
163 private boolean mReparenting;
164
Wale Ogunwalee287e192017-04-21 09:30:12 -0700165 // True if we are current in the process of removing this app token from the display
166 private boolean mRemovingFromDisplay = false;
167
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800168 // The input dispatching timeout for this application token in nanoseconds.
Wale Ogunwale72919d22016-12-08 18:58:50 -0800169 long mInputDispatchingTimeoutNanos;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800170
171 // These are used for determining when all windows associated with
172 // an activity have been drawn, so they can be made visible together
173 // at the same time.
Craig Mautner764983d2012-03-22 11:37:36 -0700174 // initialize so that it doesn't match mTransactionSequence which is an int.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700175 private long mLastTransactionSequence = Long.MIN_VALUE;
176 private int mNumInterestingWindows;
177 private int mNumDrawnWindows;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800178 boolean inPendingTransaction;
179 boolean allDrawn;
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000180 private boolean mLastAllDrawn;
Tiger Huangc9d0d002019-05-29 22:55:29 +0800181 private boolean mUseTransferredAnimation;
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000182
Craig Mautner7636dfb2012-11-16 15:24:11 -0800183 // Set to true when this app creates a surface while in the middle of an animation. In that
184 // case do not clear allDrawn until the animation completes.
185 boolean deferClearAllDrawn;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800186
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800187 // Is this window's surface needed? This is almost like hidden, except
188 // it will sometimes be true a little earlier: when the token has
189 // been shown, but is still waiting for its app transition to execute
190 // before making its windows shown.
191 boolean hiddenRequested;
192
193 // Have we told the window clients to hide themselves?
Wale Ogunwale89973222017-04-23 18:39:45 -0700194 private boolean mClientHidden;
195
196 // If true we will defer setting mClientHidden to true and reporting to the client that it is
197 // hidden.
198 boolean mDeferHidingClient;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800199
200 // Last visibility state we reported to the app token.
201 boolean reportedVisible;
202
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700203 // Last drawn state we reported to the app token.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700204 private boolean reportedDrawn;
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700205
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800206 // Set to true when the token has been removed from the window mgr.
207 boolean removed;
208
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800209 // Information about an application starting window if displayed.
chaviwa8f07a72019-05-01 16:25:39 -0700210 StartingData mStartingData;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800211 WindowState startingWindow;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800212 StartingSurface startingSurface;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800213 boolean startingDisplayed;
214 boolean startingMoved;
Jorim Jaggi60f9c972018-02-01 19:21:07 +0100215
Wale Ogunwale6c459212017-05-17 08:56:03 -0700216 // True if the hidden state of this token was forced to false due to a transferred starting
217 // window.
218 private boolean mHiddenSetFromTransferredStartingWindow;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800219 boolean firstWindowDrawn;
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700220 private final WindowState.UpdateReportedVisibilityResults mReportedVisibilityResults =
221 new WindowState.UpdateReportedVisibilityResults();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800222
223 // Input application handle used by the input dispatcher.
Jeff Brown9302c872011-07-13 22:51:29 -0700224 final InputApplicationHandle mInputApplicationHandle;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800225
Wale Ogunwale571771c2016-08-26 13:18:50 -0700226 // TODO: Have a WindowContainer state for tracking exiting/deferred removal.
Craig Mautner799bc1d2015-01-14 10:33:48 -0800227 boolean mIsExiting;
Craig Mautner9ef471f2014-02-07 13:11:47 -0800228
Craig Mautnerbb742462014-07-07 15:28:55 -0700229 boolean mLaunchTaskBehind;
Craig Mautner8746a472014-07-24 15:12:54 -0700230 boolean mEnteringAnimation;
Craig Mautnerbb742462014-07-07 15:28:55 -0700231
Wale Ogunwale72919d22016-12-08 18:58:50 -0800232 private boolean mAlwaysFocusable;
Wale Ogunwale6cae7652015-12-26 07:36:26 -0800233
Robert Carre12aece2016-02-02 22:43:27 -0800234 boolean mAppStopped;
Robert Carrfd10cd12016-06-29 16:41:50 -0700235 int mRotationAnimationHint;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700236 private int mPendingRelaunchCount;
Robert Carre12aece2016-02-02 22:43:27 -0800237
Jorim Jaggife762342016-10-13 14:33:27 +0200238 private boolean mLastContainsShowWhenLockedWindow;
239 private boolean mLastContainsDismissKeyguardWindow;
240
Jorim Jaggi0429f352015-12-22 16:29:16 +0100241 ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
Jorim Jaggi26c8c422016-05-09 19:57:25 -0700242 ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
Jorim Jaggi0429f352015-12-22 16:29:16 +0100243
Riddle Hsub398da32019-01-21 21:48:16 +0800244 /**
245 * The scale to fit at least one side of the activity to its parent. If the activity uses
246 * 1920x1080, and the actually size on the screen is 960x540, then the scale is 0.5.
247 */
248 private float mSizeCompatScale = 1f;
249 /**
250 * The bounds in global coordinates for activity in size compatibility mode.
251 * @see ActivityRecord#inSizeCompatMode
252 */
253 private Rect mSizeCompatBounds;
254
Wale Ogunwale6c459212017-05-17 08:56:03 -0700255 private boolean mDisablePreviewScreenshots;
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +0100256
Wale Ogunwale034a8ec2017-09-02 17:14:40 -0700257 private Task mLastParent;
Robert Carred3e83b2017-04-21 13:26:55 -0700258
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800259 // TODO: Remove after unification
260 ActivityRecord mActivityRecord;
261
chaviwd3bf08d2017-08-01 17:24:59 -0700262 /**
263 * See {@link #canTurnScreenOn()}
264 */
265 private boolean mCanTurnScreenOn = true;
266
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200267 /**
268 * If we are running an animation, this determines the transition type. Must be one of
269 * AppTransition.TRANSIT_* constants.
270 */
271 private int mTransit;
272
273 /**
274 * If we are running an animation, this determines the flags during this animation. Must be a
275 * bitwise combination of AppTransition.TRANSIT_FLAG_* constants.
276 */
277 private int mTransitFlags;
278
279 /** Whether our surface was set to be showing in the last call to {@link #prepareSurfaces} */
Jorim Jaggifd1891462017-12-29 15:41:36 +0100280 private boolean mLastSurfaceShowing = true;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200281
Evan Rosky2289ba12018-11-19 18:28:18 -0800282 /**
283 * This gets used during some open/close transitions as well as during a change transition
284 * where it represents the starting-state snapshot.
285 */
Jorim Jaggi988f6682017-11-17 17:46:43 +0100286 private AppWindowThumbnail mThumbnail;
Evan Rosky2289ba12018-11-19 18:28:18 -0800287 private final Rect mTransitStartRect = new Rect();
288
289 /**
290 * This leash is used to "freeze" the app surface in place after the state change, but before
291 * the animation is ready to start.
292 */
293 private SurfaceControl mTransitChangeLeash = null;
Jorim Jaggi988f6682017-11-17 17:46:43 +0100294
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000295 /** Have we been asked to have this token keep the screen frozen? */
296 private boolean mFreezingScreen;
297
298 /** Whether this token should be boosted at the top of all app window tokens. */
Jorim Jaggi9cd99132019-04-24 17:41:35 +0200299 @VisibleForTesting boolean mNeedsZBoost;
Adrian Roos4d18a2e2017-12-19 19:08:05 +0100300 private Letterbox mLetterbox;
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000301
chaviw23ee71c2017-12-18 11:29:41 -0800302 private final Point mTmpPoint = new Point();
chaviw23012112017-12-20 15:29:04 -0800303 private final Rect mTmpRect = new Rect();
Evan Rosky2289ba12018-11-19 18:28:18 -0800304 private final Rect mTmpPrevBounds = new Rect();
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100305 private RemoteAnimationDefinition mRemoteAnimationDefinition;
Jorim Jaggi6de61012018-03-19 14:53:23 +0100306 private AnimatingAppWindowTokenRegistry mAnimatingAppWindowTokenRegistry;
chaviw23ee71c2017-12-18 11:29:41 -0800307
chaviw4ad54912018-05-30 11:05:44 -0700308 /**
309 * A flag to determine if this AWT is in the process of closing or entering PIP. This is needed
310 * to help AWT know that the app is in the process of closing but hasn't yet started closing on
311 * the WM side.
312 */
313 private boolean mWillCloseOrEnterPip;
314
Vishnu Naira2977262018-07-26 13:31:26 -0700315 /** Layer used to constrain the animation to a token's stack bounds. */
316 SurfaceControl mAnimationBoundsLayer;
317
318 /** Whether this token needs to create mAnimationBoundsLayer for cropping animations. */
319 boolean mNeedsAnimationBoundsLayer;
320
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800321 private static final int STARTING_WINDOW_TYPE_NONE = 0;
322 private static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
323 private static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
324
chaviwdcf76ec2019-01-11 16:48:46 -0800325 private AppSaturationInfo mLastAppSaturationInfo;
326
327 private final ColorDisplayService.ColorTransformController mColorTransformController =
328 (matrix, translation) -> mWmService.mH.post(() -> {
329 synchronized (mWmService.mGlobalLock) {
330 if (mLastAppSaturationInfo == null) {
331 mLastAppSaturationInfo = new AppSaturationInfo();
332 }
333
334 mLastAppSaturationInfo.setSaturation(matrix, translation);
335 updateColorTransform();
336 }
337 });
338
Winson Chung48b25652018-10-22 14:04:30 -0700339 AppWindowToken(WindowManagerService service, IApplicationToken token,
340 ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
341 long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers,
Jorim Jaggi91d382a2019-03-27 17:00:48 +0100342 int targetSdk, int orientation, int rotationAnimationHint,
Winson Chung48b25652018-10-22 14:04:30 -0700343 boolean launchTaskBehind, boolean alwaysFocusable,
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800344 ActivityRecord activityRecord) {
Winson Chung48b25652018-10-22 14:04:30 -0700345 this(service, token, activityComponent, voiceInteraction, dc, fullscreen);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800346 // TODO: remove after unification
347 mActivityRecord = activityRecord;
348 mActivityRecord.registerConfigurationChangeListener(this);
Wale Ogunwale72919d22016-12-08 18:58:50 -0800349 mInputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800350 mShowForAllUsers = showForAllUsers;
351 mTargetSdk = targetSdk;
352 mOrientation = orientation;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800353 mLaunchTaskBehind = launchTaskBehind;
354 mAlwaysFocusable = alwaysFocusable;
355 mRotationAnimationHint = rotationAnimationHint;
356
357 // Application tokens start out hidden.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200358 setHidden(true);
Wale Ogunwale72919d22016-12-08 18:58:50 -0800359 hiddenRequested = true;
chaviwdcf76ec2019-01-11 16:48:46 -0800360
361 ColorDisplayService.ColorDisplayServiceInternal cds = LocalServices.getService(
362 ColorDisplayService.ColorDisplayServiceInternal.class);
363 cds.attachColorTransformController(activityRecord.packageName, activityRecord.mUserId,
364 new WeakReference<>(mColorTransformController));
Wale Ogunwale72919d22016-12-08 18:58:50 -0800365 }
366
Winson Chung48b25652018-10-22 14:04:30 -0700367 AppWindowToken(WindowManagerService service, IApplicationToken token,
368 ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
369 boolean fillsParent) {
Wale Ogunwale5cd907d2017-01-26 14:14:08 -0800370 super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true, dc,
371 false /* ownerCanManageAppTokens */);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700372 appToken = token;
Winson Chung48b25652018-10-22 14:04:30 -0700373 mActivityComponent = activityComponent;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800374 mVoiceInteraction = voiceInteraction;
Wale Ogunwale17f175c2017-02-07 16:54:10 -0800375 mFillsParent = fillsParent;
Robert Carr0bcbe642018-10-11 19:07:43 -0700376 mInputApplicationHandle = new InputApplicationHandle(appToken.asBinder());
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800377 }
378
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800379 void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
380 firstWindowDrawn = true;
381
382 // We now have a good window to show, remove dead placeholders
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700383 removeDeadWindows();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800384
Jorim Jaggi02886a82016-12-06 09:10:06 -0800385 if (startingWindow != null) {
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800386 if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Slog.v(TAG, "Finish starting "
387 + win.mToken + ": first real window is shown, no animation");
388 // If this initial window is animating, stop it -- we will do an animation to reveal
389 // it from behind the starting window, so there is no need for it to also be doing its
390 // own stuff.
Jorim Jaggia5e10572017-11-15 14:36:26 +0100391 win.cancelAnimation();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800392 }
chaviwa8f07a72019-05-01 16:25:39 -0700393 removeStartingWindow();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800394 updateReportedVisibilityLocked();
395 }
396
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800397 void updateReportedVisibilityLocked() {
398 if (appToken == null) {
399 return;
400 }
401
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700402 if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700403 final int count = mChildren.size();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800404
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700405 mReportedVisibilityResults.reset();
406
407 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700408 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700409 win.updateReportedVisibility(mReportedVisibilityResults);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800410 }
411
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700412 int numInteresting = mReportedVisibilityResults.numInteresting;
413 int numVisible = mReportedVisibilityResults.numVisible;
414 int numDrawn = mReportedVisibilityResults.numDrawn;
415 boolean nowGone = mReportedVisibilityResults.nowGone;
416
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700417 boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200418 boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting && !isHidden();
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700419 if (!nowGone) {
420 // If the app is not yet gone, then it can only become visible/drawn.
421 if (!nowDrawn) {
422 nowDrawn = reportedDrawn;
423 }
424 if (!nowVisible) {
425 nowVisible = reportedVisible;
426 }
427 }
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800428 if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800429 + numInteresting + " visible=" + numVisible);
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700430 if (nowDrawn != reportedDrawn) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800431 if (mActivityRecord != null) {
432 mActivityRecord.onWindowsDrawn(nowDrawn, SystemClock.uptimeMillis());
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700433 }
434 reportedDrawn = nowDrawn;
435 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800436 if (nowVisible != reportedVisible) {
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700437 if (DEBUG_VISIBILITY) Slog.v(TAG,
438 "Visibility changed in " + this + ": vis=" + nowVisible);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800439 reportedVisible = nowVisible;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800440 if (mActivityRecord != null) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800441 if (nowVisible) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800442 onWindowsVisible();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800443 } else {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800444 onWindowsGone();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800445 }
446 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800447 }
448 }
449
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800450 private void onWindowsGone() {
451 if (mActivityRecord == null) {
452 return;
453 }
454 if (DEBUG_VISIBILITY) {
455 Slog.v(TAG_WM, "Reporting gone in " + mActivityRecord.appToken);
456 }
457 mActivityRecord.onWindowsGone();
458 }
459
460 private void onWindowsVisible() {
461 if (mActivityRecord == null) {
462 return;
463 }
464 if (DEBUG_VISIBILITY) {
465 Slog.v(TAG_WM, "Reporting visible in " + mActivityRecord.appToken);
466 }
467 mActivityRecord.onWindowsVisible();
468 }
469
Wale Ogunwale89973222017-04-23 18:39:45 -0700470 boolean isClientHidden() {
471 return mClientHidden;
472 }
473
474 void setClientHidden(boolean hideClient) {
475 if (mClientHidden == hideClient || (hideClient && mDeferHidingClient)) {
476 return;
477 }
Jorim Jaggi067b5bf2018-02-23 17:42:39 +0100478 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "setClientHidden: " + this
479 + " clientHidden=" + hideClient + " Callers=" + Debug.getCallers(5));
Wale Ogunwale89973222017-04-23 18:39:45 -0700480 mClientHidden = hideClient;
481 sendAppVisibilityToClients();
482 }
483
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800484 void setVisibility(boolean visible, boolean deferHidingClient) {
485 final AppTransition appTransition = getDisplayContent().mAppTransition;
486
487 // Don't set visibility to false if we were already not visible. This prevents WM from
488 // adding the app to the closing app list which doesn't make sense for something that is
489 // already not visible. However, set visibility to true even if we are already visible.
490 // This makes sure the app is added to the opening apps list so that the right
491 // transition can be selected.
492 // TODO: Probably a good idea to separate the concept of opening/closing apps from the
493 // concept of setting visibility...
494 if (!visible && hiddenRequested) {
495
496 if (!deferHidingClient && mDeferHidingClient) {
497 // We previously deferred telling the client to hide itself when visibility was
498 // initially set to false. Now we would like it to hide, so go ahead and set it.
499 mDeferHidingClient = deferHidingClient;
500 setClientHidden(true);
501 }
502 return;
503 }
504
505 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) {
506 Slog.v(TAG_WM, "setAppVisibility("
507 + appToken + ", visible=" + visible + "): " + appTransition
508 + " hidden=" + isHidden() + " hiddenRequested="
509 + hiddenRequested + " Callers=" + Debug.getCallers(6));
510 }
511
512 final DisplayContent displayContent = getDisplayContent();
513 displayContent.mOpeningApps.remove(this);
514 displayContent.mClosingApps.remove(this);
Evan Roskyb1e75f72019-04-26 20:23:26 -0700515 if (isInChangeTransition()) {
516 clearChangeLeash(getPendingTransaction(), true /* cancel */);
517 }
518 displayContent.mChangingApps.remove(this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800519 waitingToShow = false;
520 hiddenRequested = !visible;
521 mDeferHidingClient = deferHidingClient;
522
523 if (!visible) {
524 // If the app is dead while it was visible, we kept its dead window on screen.
525 // Now that the app is going invisible, we can remove it. It will be restarted
526 // if made visible again.
527 removeDeadWindows();
528 } else {
529 if (!appTransition.isTransitionSet()
530 && appTransition.isReady()) {
531 // Add the app mOpeningApps if transition is unset but ready. This means
532 // we're doing a screen freeze, and the unfreeze will wait for all opening
533 // apps to be ready.
534 displayContent.mOpeningApps.add(this);
535 }
536 startingMoved = false;
537 // If the token is currently hidden (should be the common case), or has been
538 // stopped, then we need to set up to wait for its windows to be ready.
539 if (isHidden() || mAppStopped) {
540 clearAllDrawn();
541
542 // If the app was already visible, don't reset the waitingToShow state.
543 if (isHidden()) {
544 waitingToShow = true;
Jorim Jaggi6ec52d42019-07-03 15:45:59 +0200545
546 // Let's reset the draw state in order to prevent the starting window to be
547 // immediately dismissed when the app still has the surface.
548 forAllWindows(w -> {
549 if (w.mWinAnimator.mDrawState == HAS_DRAWN) {
550 w.mWinAnimator.resetDrawState();
551
552 // Force add to mResizingWindows, so that we are guaranteed to get
553 // another reportDrawn callback.
554 w.resetLastContentInsets();
555 }
556 }, true /* traverseTopToBottom */);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800557 }
558 }
559
560 // In the case where we are making an app visible but holding off for a transition,
561 // we still need to tell the client to make its windows visible so they get drawn.
562 // Otherwise, we will wait on performing the transition until all windows have been
563 // drawn, they never will be, and we are sad.
564 setClientHidden(false);
565
566 requestUpdateWallpaperIfNeeded();
567
568 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "No longer Stopped: " + this);
569 mAppStopped = false;
570
571 transferStartingWindowFromHiddenAboveTokenIfNeeded();
572 }
573
574 // If we are preparing an app transition, then delay changing
575 // the visibility of this token until we execute that transition.
576 if (okToAnimate() && appTransition.isTransitionSet()) {
577 inPendingTransaction = true;
578 if (visible) {
579 displayContent.mOpeningApps.add(this);
580 mEnteringAnimation = true;
581 } else {
582 displayContent.mClosingApps.add(this);
583 mEnteringAnimation = false;
584 }
Louis Chang37317152019-05-09 09:53:58 +0800585 if (appTransition.getAppTransition() == TRANSIT_TASK_OPEN_BEHIND) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800586 // 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.
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800596 displayContent.mOpeningApps.add(focusedToken);
597 }
598 }
599 }
Garfield Tanb6776602019-02-20 14:44:26 -0800600 // Changes in opening apps and closing apps may cause orientation change.
601 reportDescendantOrientationChangeIfNeeded();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800602 return;
603 }
604
605 commitVisibility(null, visible, TRANSIT_UNSET, true, mVoiceInteraction);
606 updateReportedVisibilityLocked();
607 }
608
609 boolean commitVisibility(WindowManager.LayoutParams lp,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700610 boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
611
612 boolean delayed = false;
613 inPendingTransaction = false;
Wale Ogunwale9e4721f2017-05-23 19:37:30 -0700614 // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually
615 // been set by the app now.
616 mHiddenSetFromTransferredStartingWindow = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700617
618 // Allow for state changes and animation to be applied if:
619 // * token is transitioning visibility state
620 // * or the token was marked as hidden and is exiting before we had a chance to play the
621 // transition animation
Louis Chang37317152019-05-09 09:53:58 +0800622 // * or this is an opening app and windows are being replaced
623 // * or the token is the opening app and visible while opening task behind existing one.
624 final DisplayContent displayContent = getDisplayContent();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700625 boolean visibilityChanged = false;
Louis Chang37317152019-05-09 09:53:58 +0800626 if (isHidden() == visible || (isHidden() && mIsExiting)
627 || (visible && waitingForReplacement())
628 || (visible && displayContent.mOpeningApps.contains(this)
629 && displayContent.mAppTransition.getAppTransition() == TRANSIT_TASK_OPEN_BEHIND)) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800630 final AccessibilityController accessibilityController =
631 mWmService.mAccessibilityController;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700632 boolean changed = false;
633 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM,
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200634 "Changing app " + this + " hidden=" + isHidden() + " performLayout=" + performLayout);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700635
636 boolean runningAppAnimation = false;
637
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100638 if (transit != WindowManager.TRANSIT_UNSET) {
Tiger Huangc9d0d002019-05-29 22:55:29 +0800639 if (mUseTransferredAnimation) {
640 runningAppAnimation = isReallyAnimating();
641 } else if (applyAnimationLocked(lp, transit, visible, isVoiceInteraction)) {
642 runningAppAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700643 }
Tiger Huangc9d0d002019-05-29 22:55:29 +0800644 delayed = runningAppAnimation;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700645 final WindowState window = findMainWindow();
Rhed Jao02655dc2018-10-30 20:44:52 +0800646 if (window != null && accessibilityController != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700647 accessibilityController.onAppWindowTransitionLocked(window, transit);
648 }
649 changed = true;
650 }
651
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700652 final int windowsCount = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700653 for (int i = 0; i < windowsCount; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700654 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700655 changed |= win.onAppVisibilityChanged(visible, runningAppAnimation);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700656 }
657
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200658 setHidden(!visible);
659 hiddenRequested = !visible;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700660 visibilityChanged = true;
661 if (!visible) {
662 stopFreezingScreen(true, true);
663 } else {
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700664 // If we are being set visible, and the starting window is not yet displayed,
665 // then make sure it doesn't get displayed.
666 if (startingWindow != null && !startingWindow.isDrawnLw()) {
chaviw15ad49f2019-04-24 15:05:39 -0700667 startingWindow.clearPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY);
668 startingWindow.mLegacyPolicyVisibilityAfterAnim = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700669 }
Jorim Jaggi38d44ec2017-06-14 16:04:59 -0700670
671 // We are becoming visible, so better freeze the screen with the windows that are
672 // getting visible so we also wait for them.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800673 forAllWindows(mWmService::makeWindowFreezingScreenIfNeededLocked, true);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700674 }
675
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800676 if (DEBUG_APP_TRANSITIONS) {
677 Slog.v(TAG_WM, "commitVisibility: " + this
678 + ": hidden=" + isHidden() + " hiddenRequested=" + hiddenRequested);
679 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700680
681 if (changed) {
Louis Chang37317152019-05-09 09:53:58 +0800682 displayContent.getInputMonitor().setUpdateInputWindowsNeededLw();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700683 if (performLayout) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800684 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700685 false /*updateInputWindows*/);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800686 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700687 }
Louis Chang37317152019-05-09 09:53:58 +0800688 displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700689 }
690 }
Tiger Huangc9d0d002019-05-29 22:55:29 +0800691 mUseTransferredAnimation = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700692
lumarkd14173e2019-03-27 19:14:33 +0800693 if (isReallyAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700694 delayed = true;
Jorim Jaggiab9fcb22018-03-15 23:46:12 +0100695 } else {
696
697 // We aren't animating anything, but exiting windows rely on the animation finished
698 // callback being called in case the AppWindowToken was pretending to be animating,
699 // which we might have done because we were in closing/opening apps list.
700 onAnimationFinished();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700701 }
702
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700703 for (int i = mChildren.size() - 1; i >= 0 && !delayed; i--) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100704 if ((mChildren.get(i)).isSelfOrChildAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700705 delayed = true;
706 }
707 }
708
709 if (visibilityChanged) {
710 if (visible && !delayed) {
711 // The token was made immediately visible, there will be no entrance animation.
712 // We need to inform the client the enter animation was finished.
713 mEnteringAnimation = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800714 mWmService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(
715 token);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700716 }
Robert Carr61b81112017-07-17 18:08:15 -0700717
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800718 // If we're becoming visible, immediately change client visibility as well. there seem
719 // to be some edge cases where we change our visibility but client visibility never gets
720 // updated.
Jorim Jaggi110839b2018-01-22 12:49:04 +0100721 // If we're becoming invisible, update the client visibility if we are not running an
722 // animation. Otherwise, we'll update client visibility in onAnimationFinished.
Jorim Jaggi3cad57f2018-02-20 18:32:01 +0100723 if (visible || !isReallyAnimating()) {
Jorim Jaggi110839b2018-01-22 12:49:04 +0100724 setClientHidden(!visible);
Jorim Jaggi4876b4a2018-01-11 15:43:49 +0100725 }
726
Louis Chang37317152019-05-09 09:53:58 +0800727 if (!displayContent.mClosingApps.contains(this)
728 && !displayContent.mOpeningApps.contains(this)) {
chaviwa953fcf2018-03-01 12:00:39 -0800729 // The token is not closing nor opening, so even if there is an animation set, that
730 // doesn't mean that it goes through the normal app transition cycle so we have
731 // to inform the docked controller about visibility change.
732 // TODO(multi-display): notify docked divider on all displays where visibility was
733 // affected.
Louis Chang37317152019-05-09 09:53:58 +0800734 displayContent.getDockedDividerController().notifyAppVisibilityChanged();
chaviwa953fcf2018-03-01 12:00:39 -0800735
736 // Take the screenshot before possibly hiding the WSA, otherwise the screenshot
737 // will not be taken.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800738 mWmService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible);
chaviwa953fcf2018-03-01 12:00:39 -0800739 }
740
Robert Carre7cc44d2017-03-20 19:04:30 -0700741 // If we are hidden but there is no delay needed we immediately
742 // apply the Surface transaction so that the ActivityManager
Robert Carr61b81112017-07-17 18:08:15 -0700743 // can have some guarantee on the Surface state following
744 // setting the visibility. This captures cases like dismissing
745 // the docked or pinned stack where there is no app transition.
746 //
747 // In the case of a "Null" animation, there will be
748 // no animation but there will still be a transition set.
749 // We still need to delay hiding the surface such that it
750 // can be synchronized with showing the next surface in the transition.
Louis Chang37317152019-05-09 09:53:58 +0800751 if (isHidden() && !delayed && !displayContent.mAppTransition.isTransitionSet()) {
Robert Carr6914f082017-03-20 19:04:30 -0700752 SurfaceControl.openTransaction();
753 for (int i = mChildren.size() - 1; i >= 0; i--) {
754 mChildren.get(i).mWinAnimator.hide("immediately hidden");
755 }
756 SurfaceControl.closeTransaction();
757 }
Garfield Tanb6776602019-02-20 14:44:26 -0800758
759 // Visibility changes may cause orientation request change.
760 reportDescendantOrientationChangeIfNeeded();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700761 }
762
763 return delayed;
764 }
765
Garfield Tanb6776602019-02-20 14:44:26 -0800766 private void reportDescendantOrientationChangeIfNeeded() {
767 // Orientation request is exposed only when we're visible. Therefore visibility change
768 // will change requested orientation. Notify upward the hierarchy ladder to adjust
769 // configuration. This is important to cases where activities with incompatible
770 // orientations launch, or user goes back from an activity of bi-orientation to an
771 // activity with specified orientation.
772 if (mActivityRecord.getRequestedConfigurationOrientation() == getConfiguration().orientation
773 || getOrientationIgnoreVisibility() == SCREEN_ORIENTATION_UNSET) {
774 return;
775 }
776
777 final IBinder freezeToken =
778 mActivityRecord.mayFreezeScreenLocked(mActivityRecord.app)
779 ? mActivityRecord.appToken : null;
780 onDescendantOrientationChanged(freezeToken, mActivityRecord);
781 }
782
Jorim Jaggi87fdbcb2017-08-17 13:41:11 +0200783 /**
784 * @return The to top most child window for which {@link LayoutParams#isFullscreen()} returns
785 * true.
786 */
787 WindowState getTopFullscreenWindow() {
788 for (int i = mChildren.size() - 1; i >= 0; i--) {
789 final WindowState win = mChildren.get(i);
790 if (win != null && win.mAttrs.isFullscreen()) {
791 return win;
792 }
793 }
794 return null;
795 }
796
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800797 WindowState findMainWindow() {
Matthew Ng53e66b22018-01-12 17:13:13 -0800798 return findMainWindow(true);
799 }
800
801 /**
802 * Finds the main window that either has type base application or application starting if
803 * requested.
804 *
805 * @param includeStartingApp Allow to search application-starting windows to also be returned.
806 * @return The main window of type base application or application starting if requested.
807 */
808 WindowState findMainWindow(boolean includeStartingApp) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700809 WindowState candidate = null;
Matthew Ng53e66b22018-01-12 17:13:13 -0800810 for (int j = mChildren.size() - 1; j >= 0; --j) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700811 final WindowState win = mChildren.get(j);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700812 final int type = win.mAttrs.type;
813 // No need to loop through child window as base application and starting types can't be
814 // child windows.
Matthew Ng53e66b22018-01-12 17:13:13 -0800815 if (type == TYPE_BASE_APPLICATION
816 || (includeStartingApp && type == TYPE_APPLICATION_STARTING)) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700817 // In cases where there are multiple windows, we prefer the non-exiting window. This
Sungsoo Lim0d3d1f82015-12-02 14:47:59 +0900818 // happens for example when replacing windows during an activity relaunch. When
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700819 // constructing the animation, we want the new window, not the exiting one.
Wale Ogunwalec48a3542016-02-19 15:18:45 -0800820 if (win.mAnimatingExit) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700821 candidate = win;
822 } else {
823 return win;
824 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800825 }
826 }
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700827 return candidate;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800828 }
829
Wale Ogunwale6cae7652015-12-26 07:36:26 -0800830 boolean windowsAreFocusable() {
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800831 if (mTargetSdk < Build.VERSION_CODES.Q) {
832 final int pid = mActivityRecord != null
833 ? (mActivityRecord.app != null ? mActivityRecord.app.getPid() : 0) : 0;
834 final AppWindowToken topFocusedAppOfMyProcess =
835 mWmService.mRoot.mTopFocusedAppByProcess.get(pid);
836 if (topFocusedAppOfMyProcess != null && topFocusedAppOfMyProcess != this) {
837 // For the apps below Q, there can be only one app which has the focused window per
838 // process, because legacy apps may not be ready for a multi-focus system.
839 return false;
840 }
841 }
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700842 return getWindowConfiguration().canReceiveKeys() || mAlwaysFocusable;
Wale Ogunwaled045c822015-12-02 09:14:28 -0800843 }
844
Wale Ogunwale571771c2016-08-26 13:18:50 -0700845 @Override
Wale Ogunwale44f21802016-09-02 12:49:48 -0700846 boolean isVisible() {
Wale Ogunwalee471be62016-10-03 07:53:55 -0700847 // If the app token isn't hidden then it is considered visible and there is no need to check
848 // its children windows to see if they are visible.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200849 return !isHidden();
Wale Ogunwale44f21802016-09-02 12:49:48 -0700850 }
851
852 @Override
Wale Ogunwalee287e192017-04-21 09:30:12 -0700853 void removeImmediately() {
854 onRemovedFromDisplay();
Yunfan Chen3a77f282018-12-12 15:47:52 -0800855 if (mActivityRecord != null) {
856 mActivityRecord.unregisterConfigurationChangeListener(this);
857 }
Wale Ogunwalee287e192017-04-21 09:30:12 -0700858 super.removeImmediately();
859 }
860
861 @Override
Wale Ogunwale571771c2016-08-26 13:18:50 -0700862 void removeIfPossible() {
Craig Mautnere3119b72015-01-20 15:02:36 -0800863 mIsExiting = false;
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800864 removeAllWindowsIfPossible();
Bryce Lee6d410262017-02-28 15:30:17 -0800865 removeImmediately();
Craig Mautnere3119b72015-01-20 15:02:36 -0800866 }
867
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700868 @Override
869 boolean checkCompleteDeferredRemoval() {
870 if (mIsExiting) {
871 removeIfPossible();
872 }
873 return super.checkCompleteDeferredRemoval();
874 }
875
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700876 void onRemovedFromDisplay() {
Wale Ogunwalee287e192017-04-21 09:30:12 -0700877 if (mRemovingFromDisplay) {
878 return;
879 }
880 mRemovingFromDisplay = true;
881
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700882 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app token: " + this);
883
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800884 boolean delayed = commitVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700885
lumark588a3e82018-07-20 18:53:54 +0800886 getDisplayContent().mOpeningApps.remove(this);
Evan Rosky2289ba12018-11-19 18:28:18 -0800887 getDisplayContent().mChangingApps.remove(this);
lumark588a3e82018-07-20 18:53:54 +0800888 getDisplayContent().mUnknownAppVisibilityController.appRemovedOrHidden(this);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800889 mWmService.mTaskSnapshotController.onAppRemoved(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700890 waitingToShow = false;
lumark588a3e82018-07-20 18:53:54 +0800891 if (getDisplayContent().mClosingApps.contains(this)) {
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700892 delayed = true;
lumark588a3e82018-07-20 18:53:54 +0800893 } else if (getDisplayContent().mAppTransition.isTransitionSet()) {
894 getDisplayContent().mClosingApps.add(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700895 delayed = true;
896 }
897
898 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app " + this + " delayed=" + delayed
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200899 + " animation=" + getAnimation() + " animating=" + isSelfAnimating());
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700900
901 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: "
902 + this + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
903
chaviwa8f07a72019-05-01 16:25:39 -0700904 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800905 removeStartingWindow();
Jorim Jaggi19be6052017-08-03 18:33:43 +0200906 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800907
Winson Chung87e5d552017-04-05 11:49:38 -0700908 // If this window was animating, then we need to ensure that the app transition notifies
lumark588a3e82018-07-20 18:53:54 +0800909 // that animations have completed in DisplayContent.handleAnimatingStoppedAndTransition(),
910 // so add to that list now
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200911 if (isSelfAnimating()) {
lumark588a3e82018-07-20 18:53:54 +0800912 getDisplayContent().mNoAnimationNotifyOnTransitionFinished.add(token);
Winson Chung87e5d552017-04-05 11:49:38 -0700913 }
914
Wale Ogunwalee287e192017-04-21 09:30:12 -0700915 final TaskStack stack = getStack();
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700916 if (delayed && !isEmpty()) {
917 // set the token aside because it has an active animation to be finished
918 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM,
919 "removeAppToken make exiting: " + this);
Wale Ogunwalee287e192017-04-21 09:30:12 -0700920 if (stack != null) {
921 stack.mExitingAppTokens.add(this);
922 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700923 mIsExiting = true;
924 } else {
925 // Make sure there is no animation running on this token, so any windows associated
926 // with it will be removed as soon as their animations are complete
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200927 cancelAnimation();
Wale Ogunwale3106ae012017-05-16 08:56:37 -0700928 if (stack != null) {
929 stack.mExitingAppTokens.remove(this);
930 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700931 removeIfPossible();
932 }
933
934 removed = true;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700935 stopFreezingScreen(true, true);
Bryce Lee6d410262017-02-28 15:30:17 -0800936
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800937 final DisplayContent dc = getDisplayContent();
938 if (dc.mFocusedApp == this) {
939 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + this
940 + " displayId=" + dc.getDisplayId());
941 dc.setFocusedApp(null);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800942 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700943 }
Riddle Hsu192fe762019-01-15 23:41:57 +0800944 if (mLetterbox != null) {
945 mLetterbox.destroy();
946 mLetterbox = null;
947 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700948
949 if (!delayed) {
950 updateReportedVisibilityLocked();
951 }
Wale Ogunwalee287e192017-04-21 09:30:12 -0700952
953 mRemovingFromDisplay = false;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700954 }
955
Chong Zhange05bcb12016-07-26 17:47:29 -0700956 void clearAnimatingFlags() {
Chong Zhangb0d26702016-08-12 16:03:29 -0700957 boolean wallpaperMightChange = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700958 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700959 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700960 wallpaperMightChange |= win.clearAnimatingFlags();
Chong Zhange05bcb12016-07-26 17:47:29 -0700961 }
Chong Zhangb0d26702016-08-12 16:03:29 -0700962 if (wallpaperMightChange) {
963 requestUpdateWallpaperIfNeeded();
964 }
Chong Zhange05bcb12016-07-26 17:47:29 -0700965 }
966
Robert Carre12aece2016-02-02 22:43:27 -0800967 void destroySurfaces() {
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700968 destroySurfaces(false /*cleanupOnResume*/);
969 }
970
971 /**
972 * Destroy surfaces which have been marked as eligible by the animator, taking care to ensure
973 * the client has finished with them.
974 *
975 * @param cleanupOnResume whether this is done when app is resumed without fully stopped. If
976 * set to true, destroy only surfaces of removed windows, and clear relevant flags of the
977 * others so that they are ready to be reused. If set to false (common case), destroy all
978 * surfaces that's eligible, if the app is already stopped.
979 */
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700980 private void destroySurfaces(boolean cleanupOnResume) {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700981 boolean destroyedSomething = false;
Jorim Jaggia5e10572017-11-15 14:36:26 +0100982
983 // Copying to a different list as multiple children can be removed.
Jorim Jaggi59f3e922018-01-05 15:40:32 +0100984 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
Jorim Jaggia5e10572017-11-15 14:36:26 +0100985 for (int i = children.size() - 1; i >= 0; i--) {
986 final WindowState win = children.get(i);
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700987 destroyedSomething |= win.destroySurface(cleanupOnResume, mAppStopped);
Robert Carre12aece2016-02-02 22:43:27 -0800988 }
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700989 if (destroyedSomething) {
990 final DisplayContent dc = getDisplayContent();
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700991 dc.assignWindowLayers(true /*setLayoutNeeded*/);
Adrian Roos23df3a32018-03-15 15:41:13 +0100992 updateLetterboxSurface(null);
Robert Carre12aece2016-02-02 22:43:27 -0800993 }
994 }
995
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800996 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700997 * Notify that the app is now resumed, and it was not stopped before, perform a clean
998 * up of the surfaces
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800999 */
Jorim Jaggibae01b12017-04-11 16:29:10 -07001000 void notifyAppResumed(boolean wasStopped) {
Chong Zhangad24f962016-08-25 12:12:33 -07001001 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppResumed: wasStopped=" + wasStopped
Jorim Jaggibae01b12017-04-11 16:29:10 -07001002 + " " + this);
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001003 mAppStopped = false;
chaviwd3bf08d2017-08-01 17:24:59 -07001004 // Allow the window to turn the screen on once the app is resumed again.
1005 setCanTurnScreenOn(true);
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001006 if (!wasStopped) {
1007 destroySurfaces(true /*cleanupOnResume*/);
Wale Ogunwale8d5a5422016-03-03 18:28:21 -08001008 }
Robert Carre12aece2016-02-02 22:43:27 -08001009 }
1010
Chong Zhangbef461f2015-10-27 11:38:24 -07001011 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001012 * Notify that the app has stopped, and it is okay to destroy any surfaces which were
1013 * keeping alive in case they were still being used.
1014 */
1015 void notifyAppStopped() {
1016 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: " + this);
1017 mAppStopped = true;
Hongwei Wanga5799f82019-07-01 15:52:50 -07001018 // Reset the last saved PiP snap fraction on app stop.
1019 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(this);
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001020 destroySurfaces();
1021 // Remove any starting window that was added for this app if they are still around.
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001022 removeStartingWindow();
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001023 }
1024
Chong Zhang92147042016-05-09 12:47:11 -07001025 void clearAllDrawn() {
1026 allDrawn = false;
1027 deferClearAllDrawn = false;
Chong Zhangbef461f2015-10-27 11:38:24 -07001028 }
1029
Bryce Lee6d410262017-02-28 15:30:17 -08001030 Task getTask() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001031 return (Task) getParent();
Bryce Lee6d410262017-02-28 15:30:17 -08001032 }
1033
Jorim Jaggi3878ca32017-02-02 17:13:05 -08001034 TaskStack getStack() {
1035 final Task task = getTask();
1036 if (task != null) {
1037 return task.mStack;
1038 } else {
1039 return null;
1040 }
1041 }
1042
Bryce Lee6d410262017-02-28 15:30:17 -08001043 @Override
Riddle Hsu3a4bb612019-01-31 00:02:22 +08001044 void onParentChanged() {
1045 super.onParentChanged();
Bryce Lee6d410262017-02-28 15:30:17 -08001046
Robert Carred3e83b2017-04-21 13:26:55 -07001047 final Task task = getTask();
1048
Bryce Lee6d410262017-02-28 15:30:17 -08001049 // When the associated task is {@code null}, the {@link AppWindowToken} can no longer
1050 // access visual elements like the {@link DisplayContent}. We must remove any associations
1051 // such as animations.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001052 if (!mReparenting) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001053 if (task == null) {
1054 // It is possible we have been marked as a closing app earlier. We must remove ourselves
1055 // from this list so we do not participate in any future animations.
lumark588a3e82018-07-20 18:53:54 +08001056 getDisplayContent().mClosingApps.remove(this);
Robert Carred3e83b2017-04-21 13:26:55 -07001057 } else if (mLastParent != null && mLastParent.mStack != null) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001058 task.mStack.mExitingAppTokens.remove(this);
1059 }
Bryce Lee6d410262017-02-28 15:30:17 -08001060 }
Jorim Jaggi6de61012018-03-19 14:53:23 +01001061 final TaskStack stack = getStack();
1062
1063 // If we reparent, make sure to remove ourselves from the old animation registry.
1064 if (mAnimatingAppWindowTokenRegistry != null) {
1065 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
1066 }
1067 mAnimatingAppWindowTokenRegistry = stack != null
1068 ? stack.getAnimatingAppWindowTokenRegistry()
1069 : null;
1070
Robert Carred3e83b2017-04-21 13:26:55 -07001071 mLastParent = task;
chaviwdcf76ec2019-01-11 16:48:46 -08001072
1073 updateColorTransform();
Bryce Lee6d410262017-02-28 15:30:17 -08001074 }
1075
Wale Ogunwalefa854eb2016-09-20 13:43:52 -07001076 void postWindowRemoveStartingWindowCleanup(WindowState win) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001077 // TODO: Something smells about the code below...Is there a better way?
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001078 if (startingWindow == win) {
1079 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Notify removed startingWindow " + win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001080 removeStartingWindow();
Wale Ogunwale6c459212017-05-17 08:56:03 -07001081 } else if (mChildren.size() == 0) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001082 // If this is the last window and we had requested a starting transition window,
1083 // well there is no point now.
Jorim Jaggi02886a82016-12-06 09:10:06 -08001084 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Nulling last startingData");
chaviwa8f07a72019-05-01 16:25:39 -07001085 mStartingData = null;
Wale Ogunwale6c459212017-05-17 08:56:03 -07001086 if (mHiddenSetFromTransferredStartingWindow) {
1087 // We set the hidden state to false for the token from a transferred starting window.
1088 // We now reset it back to true since the starting window was the last window in the
1089 // token.
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001090 setHidden(true);
Wale Ogunwale6c459212017-05-17 08:56:03 -07001091 }
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01001092 } else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001093 // If this is the last window except for a starting transition window,
1094 // we need to get rid of the starting transition.
Jorim Jaggie4b0f282017-05-17 15:10:29 +02001095 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Last window, removing starting window "
1096 + win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001097 removeStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001098 }
1099 }
1100
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001101 void removeDeadWindows() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001102 for (int winNdx = mChildren.size() - 1; winNdx >= 0; --winNdx) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001103 WindowState win = mChildren.get(winNdx);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001104 if (win.mAppDied) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001105 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.w(TAG,
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001106 "removeDeadWindows: " + win);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001107 // Set mDestroying, we don't want any animation or delayed removal here.
1108 win.mDestroying = true;
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001109 // Also removes child windows.
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001110 win.removeIfPossible();
Chong Zhang112eb8c2015-11-02 11:17:00 -08001111 }
1112 }
1113 }
1114
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001115 boolean hasWindowsAlive() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001116 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001117 // No need to loop through child windows as the answer should be the same as that of the
1118 // parent window.
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001119 if (!(mChildren.get(i)).mAppDied) {
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001120 return true;
1121 }
1122 }
1123 return false;
1124 }
1125
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001126 void setWillReplaceWindows(boolean animate) {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001127 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
1128 "Marking app token " + this + " with replacing windows.");
Robert Carra1eb4392015-12-10 12:43:51 -08001129
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001130 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001131 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001132 w.setWillReplaceWindow(animate);
Robert Carra1eb4392015-12-10 12:43:51 -08001133 }
Robert Carra1eb4392015-12-10 12:43:51 -08001134 }
1135
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001136 void setWillReplaceChildWindows() {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001137 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Marking app token " + this
Robert Carr23fa16b2016-01-13 13:19:58 -08001138 + " with replacing child windows.");
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001139 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001140 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001141 w.setWillReplaceChildWindows();
Robert Carr23fa16b2016-01-13 13:19:58 -08001142 }
1143 }
1144
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001145 void clearWillReplaceWindows() {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001146 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
1147 "Resetting app token " + this + " of replacing window marks.");
Chong Zhangf596cd52016-01-05 13:42:44 -08001148
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001149 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001150 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001151 w.clearWillReplaceWindow();
Chong Zhangf596cd52016-01-05 13:42:44 -08001152 }
1153 }
1154
Chong Zhang4d7369a2016-04-25 16:09:14 -07001155 void requestUpdateWallpaperIfNeeded() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001156 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001157 final WindowState w = mChildren.get(i);
Chong Zhang4d7369a2016-04-25 16:09:14 -07001158 w.requestUpdateWallpaperIfNeeded();
1159 }
1160 }
1161
Chong Zhangd78ddb42016-03-02 17:01:14 -08001162 boolean isRelaunching() {
1163 return mPendingRelaunchCount > 0;
1164 }
1165
Robert Carr68375192017-06-13 12:41:53 -07001166 boolean shouldFreezeBounds() {
1167 final Task task = getTask();
1168
1169 // For freeform windows, we can't freeze the bounds at the moment because this would make
1170 // the resizing unresponsive.
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001171 if (task == null || task.inFreeformWindowingMode()) {
Robert Carr68375192017-06-13 12:41:53 -07001172 return false;
1173 }
1174
1175 // We freeze the bounds while drag resizing to deal with the time between
1176 // the divider/drag handle being released, and the handling it's new
1177 // configuration. If we are relaunched outside of the drag resizing state,
1178 // we need to be careful not to do this.
1179 return getTask().isDragResizing();
1180 }
1181
Chong Zhangd78ddb42016-03-02 17:01:14 -08001182 void startRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001183 if (shouldFreezeBounds()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08001184 freezeBounds();
1185 }
Robert Carrd5c7dd62017-03-08 10:39:30 -08001186
1187 // In the process of tearing down before relaunching, the app will
1188 // try and clean up it's child surfaces. We need to prevent this from
1189 // happening, so we sever the children, transfering their ownership
1190 // from the client it-self to the parent surface (owned by us).
Robert Carr29daa922018-04-27 11:56:48 -07001191 detachChildren();
1192
1193 mPendingRelaunchCount++;
1194 }
1195
1196 void detachChildren() {
Robert Carrfd8e93b2018-05-10 13:40:25 -07001197 SurfaceControl.openTransaction();
Robert Carrd5c7dd62017-03-08 10:39:30 -08001198 for (int i = mChildren.size() - 1; i >= 0; i--) {
1199 final WindowState w = mChildren.get(i);
1200 w.mWinAnimator.detachChildren();
1201 }
Robert Carrfd8e93b2018-05-10 13:40:25 -07001202 SurfaceControl.closeTransaction();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001203 }
1204
1205 void finishRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001206 unfreezeBounds();
1207
Chong Zhangd78ddb42016-03-02 17:01:14 -08001208 if (mPendingRelaunchCount > 0) {
1209 mPendingRelaunchCount--;
Bryce Lee081554b2017-05-25 07:52:12 -07001210 } else {
1211 // Update keyguard flags upon finishing relaunch.
1212 checkKeyguardFlagsChanged();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001213 }
1214 }
1215
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001216 void clearRelaunching() {
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001217 if (mPendingRelaunchCount == 0) {
1218 return;
1219 }
Robert Carr68375192017-06-13 12:41:53 -07001220 unfreezeBounds();
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001221 mPendingRelaunchCount = 0;
1222 }
1223
Wale Ogunwale07bcab72016-10-14 15:30:09 -07001224 /**
1225 * Returns true if the new child window we are adding to this token is considered greater than
1226 * the existing child window in this token in terms of z-order.
1227 */
1228 @Override
1229 protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
1230 WindowState existingWindow) {
1231 final int type1 = newWindow.mAttrs.type;
1232 final int type2 = existingWindow.mAttrs.type;
1233
1234 // Base application windows should be z-ordered BELOW all other windows in the app token.
1235 if (type1 == TYPE_BASE_APPLICATION && type2 != TYPE_BASE_APPLICATION) {
1236 return false;
1237 } else if (type1 != TYPE_BASE_APPLICATION && type2 == TYPE_BASE_APPLICATION) {
1238 return true;
1239 }
1240
1241 // Starting windows should be z-ordered ABOVE all other windows in the app token.
1242 if (type1 == TYPE_APPLICATION_STARTING && type2 != TYPE_APPLICATION_STARTING) {
1243 return true;
1244 } else if (type1 != TYPE_APPLICATION_STARTING && type2 == TYPE_APPLICATION_STARTING) {
1245 return false;
1246 }
1247
1248 // Otherwise the new window is greater than the existing window.
1249 return true;
1250 }
1251
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001252 @Override
Robert Carra1eb4392015-12-10 12:43:51 -08001253 void addWindow(WindowState w) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001254 super.addWindow(w);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001255
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001256 boolean gotReplacementWindow = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001257 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001258 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001259 gotReplacementWindow |= candidate.setReplacementWindowIfNeeded(w);
1260 }
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001261
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001262 // if we got a replacement window, reset the timeout to give drawing more time
1263 if (gotReplacementWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001264 mWmService.scheduleWindowReplacementTimeouts(this);
Robert Carra1eb4392015-12-10 12:43:51 -08001265 }
Jorim Jaggife762342016-10-13 14:33:27 +02001266 checkKeyguardFlagsChanged();
1267 }
1268
1269 @Override
1270 void removeChild(WindowState child) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001271 if (!mChildren.contains(child)) {
1272 // This can be true when testing.
1273 return;
1274 }
Jorim Jaggife762342016-10-13 14:33:27 +02001275 super.removeChild(child);
1276 checkKeyguardFlagsChanged();
Adrian Roos23df3a32018-03-15 15:41:13 +01001277 updateLetterboxSurface(child);
Robert Carra1eb4392015-12-10 12:43:51 -08001278 }
1279
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001280 private boolean waitingForReplacement() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001281 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001282 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001283 if (candidate.waitingForReplacement()) {
Robert Carra1eb4392015-12-10 12:43:51 -08001284 return true;
1285 }
1286 }
1287 return false;
1288 }
1289
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001290 void onWindowReplacementTimeout() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001291 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001292 (mChildren.get(i)).onWindowReplacementTimeout();
Robert Carra1eb4392015-12-10 12:43:51 -08001293 }
1294 }
1295
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001296 void reparent(Task task, int position) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001297 if (DEBUG_ADD_REMOVE) {
1298 Slog.i(TAG_WM, "reparent: moving app token=" + this
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001299 + " to task=" + task.mTaskId + " at " + position);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001300 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001301 if (task == null) {
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001302 throw new IllegalArgumentException("reparent: could not find task");
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001303 }
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001304 final Task currentTask = getTask();
1305 if (task == currentTask) {
Winson Chung30480042017-01-26 10:55:34 -08001306 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001307 "window token=" + this + " already child of task=" + currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001308 }
Bryce Lee6d410262017-02-28 15:30:17 -08001309
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001310 if (currentTask.mStack != task.mStack) {
Bryce Lee6d410262017-02-28 15:30:17 -08001311 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001312 "window token=" + this + " current task=" + currentTask
Bryce Lee6d410262017-02-28 15:30:17 -08001313 + " belongs to a different stack than " + task);
1314 }
1315
Winson Chung30480042017-01-26 10:55:34 -08001316 if (DEBUG_ADD_REMOVE) Slog.i(TAG, "reParentWindowToken: removing window token=" + this
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001317 + " from task=" + currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001318 final DisplayContent prevDisplayContent = getDisplayContent();
1319
Bryce Lee6d410262017-02-28 15:30:17 -08001320 mReparenting = true;
1321
Winson Chung30480042017-01-26 10:55:34 -08001322 getParent().removeChild(this);
1323 task.addChild(this, position);
1324
Bryce Lee6d410262017-02-28 15:30:17 -08001325 mReparenting = false;
1326
Winson Chung30480042017-01-26 10:55:34 -08001327 // Relayout display(s).
1328 final DisplayContent displayContent = task.getDisplayContent();
1329 displayContent.setLayoutNeeded();
1330 if (prevDisplayContent != displayContent) {
1331 onDisplayChanged(displayContent);
1332 prevDisplayContent.setLayoutNeeded();
1333 }
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001334 getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
Winson Chung30480042017-01-26 10:55:34 -08001335 }
1336
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001337 @Override
1338 void onDisplayChanged(DisplayContent dc) {
1339 DisplayContent prevDc = mDisplayContent;
1340 super.onDisplayChanged(dc);
Evan Roskyb1e75f72019-04-26 20:23:26 -07001341 if (prevDc == null || prevDc == mDisplayContent) {
Evan Rosky25b56192019-02-06 16:10:56 -08001342 return;
1343 }
Wale Ogunwaleb8e6b632019-06-28 15:19:25 +00001344
1345 if (prevDc.mOpeningApps.remove(this)) {
1346 // Transfer opening transition to new display.
1347 mDisplayContent.mOpeningApps.add(this);
1348 mDisplayContent.prepareAppTransition(prevDc.mAppTransition.getAppTransition(), true);
1349 mDisplayContent.executeAppTransition();
1350 }
1351
1352 if (prevDc.mChangingApps.remove(this)) {
Evan Rosky25b56192019-02-06 16:10:56 -08001353 // This gets called *after* the AppWindowToken has been reparented to the new display.
1354 // That reparenting resulted in this window changing modes (eg. FREEFORM -> FULLSCREEN),
1355 // so this token is now "frozen" while waiting for the animation to start on prevDc
1356 // (which will be cancelled since the window is no-longer a child). However, since this
1357 // is no longer a child of prevDc, this won't be notified of the cancelled animation,
1358 // so we need to cancel the change transition here.
1359 clearChangeLeash(getPendingTransaction(), true /* cancel */);
1360 }
Wale Ogunwaleb8e6b632019-06-28 15:19:25 +00001361 prevDc.mClosingApps.remove(this);
1362
Evan Rosky25b56192019-02-06 16:10:56 -08001363 if (prevDc.mFocusedApp == this) {
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001364 prevDc.setFocusedApp(null);
lumarkbf844642018-11-23 17:11:36 +08001365 final TaskStack stack = dc.getTopStack();
1366 if (stack != null) {
1367 final Task task = stack.getTopChild();
1368 if (task != null && task.getTopChild() == this) {
1369 dc.setFocusedApp(this);
1370 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001371 }
1372 }
Riddle Hsu192fe762019-01-15 23:41:57 +08001373
Evan Roskyb1e75f72019-04-26 20:23:26 -07001374 if (mLetterbox != null) {
Riddle Hsu192fe762019-01-15 23:41:57 +08001375 mLetterbox.onMovedToDisplay(mDisplayContent.getDisplayId());
1376 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001377 }
1378
Jorim Jaggi0429f352015-12-22 16:29:16 +01001379 /**
1380 * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds
1381 * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even
1382 * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen
1383 * with a queue.
1384 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001385 private void freezeBounds() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001386 final Task task = getTask();
1387 mFrozenBounds.offer(new Rect(task.mPreparedFrozenBounds));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001388
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001389 if (task.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001390 // We didn't call prepareFreezingBounds on the task, so use the current value.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001391 mFrozenMergedConfig.offer(new Configuration(task.getConfiguration()));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001392 } else {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001393 mFrozenMergedConfig.offer(new Configuration(task.mPreparedFrozenMergedConfig));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001394 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001395 // Calling unset() to make it equal to Configuration.EMPTY.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001396 task.mPreparedFrozenMergedConfig.unset();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001397 }
1398
1399 /**
1400 * Unfreezes the previously frozen bounds. See {@link #freezeBounds}.
1401 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001402 private void unfreezeBounds() {
Robert Carr68375192017-06-13 12:41:53 -07001403 if (mFrozenBounds.isEmpty()) {
1404 return;
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001405 }
Robert Carr68375192017-06-13 12:41:53 -07001406 mFrozenBounds.remove();
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001407 if (!mFrozenMergedConfig.isEmpty()) {
1408 mFrozenMergedConfig.remove();
1409 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001410 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001411 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001412 win.onUnfreezeBounds();
Jorim Jaggi4846ee32016-01-07 17:39:12 +01001413 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001414 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001415 }
1416
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001417 void setAppLayoutChanges(int changes, String reason) {
1418 if (!mChildren.isEmpty()) {
1419 final DisplayContent dc = getDisplayContent();
1420 dc.pendingLayoutChanges |= changes;
1421 if (DEBUG_LAYOUT_REPEATS) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001422 mWmService.mWindowPlacerLocked.debugLayoutRepeats(reason, dc.pendingLayoutChanges);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001423 }
1424 }
1425 }
1426
1427 void removeReplacedWindowIfNeeded(WindowState replacement) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001428 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001429 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001430 if (win.removeReplacedWindowIfNeeded(replacement)) {
1431 return;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001432 }
1433 }
1434 }
1435
1436 void startFreezingScreen() {
1437 if (DEBUG_ORIENTATION) logWithStack(TAG, "Set freezing of " + appToken + ": hidden="
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001438 + isHidden() + " freezing=" + mFreezingScreen + " hiddenRequested="
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001439 + hiddenRequested);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001440 if (!hiddenRequested) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001441 if (!mFreezingScreen) {
1442 mFreezingScreen = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001443 mWmService.registerAppFreezeListener(this);
1444 mWmService.mAppsFreezingScreen++;
1445 if (mWmService.mAppsFreezingScreen == 1) {
1446 mWmService.startFreezingDisplayLocked(0, 0, getDisplayContent());
1447 mWmService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
1448 mWmService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001449 }
1450 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001451 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001452 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001453 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001454 w.onStartFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001455 }
1456 }
1457 }
1458
1459 void stopFreezingScreen(boolean unfreezeSurfaceNow, boolean force) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001460 if (!mFreezingScreen) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001461 return;
1462 }
1463 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + this + " force=" + force);
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001464 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001465 boolean unfrozeWindows = false;
1466 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001467 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001468 unfrozeWindows |= w.onStopFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001469 }
1470 if (force || unfrozeWindows) {
1471 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "No longer freezing: " + this);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001472 mFreezingScreen = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001473 mWmService.unregisterAppFreezeListener(this);
1474 mWmService.mAppsFreezingScreen--;
1475 mWmService.mLastFinishedFreezeSource = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001476 }
1477 if (unfreezeSurfaceNow) {
1478 if (unfrozeWindows) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001479 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001480 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001481 mWmService.stopFreezingDisplayLocked();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001482 }
1483 }
1484
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001485 @Override
1486 public void onAppFreezeTimeout() {
1487 Slog.w(TAG_WM, "Force clearing freeze: " + this);
1488 stopFreezingScreen(true, true);
1489 }
1490
Jorim Jaggi60f9c972018-02-01 19:21:07 +01001491 /**
1492 * Tries to transfer the starting window from a token that's above ourselves in the task but
1493 * not visible anymore. This is a common scenario apps use: Trampoline activity T start main
1494 * activity M in the same task. Now, when reopening the task, T starts on top of M but then
1495 * immediately finishes after, so we have to transfer T to M.
1496 */
1497 void transferStartingWindowFromHiddenAboveTokenIfNeeded() {
1498 final Task task = getTask();
1499 for (int i = task.mChildren.size() - 1; i >= 0; i--) {
1500 final AppWindowToken fromToken = task.mChildren.get(i);
1501 if (fromToken == this) {
1502 return;
1503 }
1504 if (fromToken.hiddenRequested && transferStartingWindow(fromToken.token)) {
1505 return;
1506 }
1507 }
1508 }
1509
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001510 boolean transferStartingWindow(IBinder transferFrom) {
Wale Ogunwale02319a62016-09-26 15:21:22 -07001511 final AppWindowToken fromToken = getDisplayContent().getAppWindowToken(transferFrom);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001512 if (fromToken == null) {
1513 return false;
1514 }
1515
1516 final WindowState tStartingWindow = fromToken.startingWindow;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08001517 if (tStartingWindow != null && fromToken.startingSurface != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001518 // In this case, the starting icon has already been displayed, so start
1519 // letting windows get shown immediately without any more transitions.
lumark588a3e82018-07-20 18:53:54 +08001520 getDisplayContent().mSkipAppTransitionAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001521
1522 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Moving existing starting " + tStartingWindow
1523 + " from " + fromToken + " to " + this);
1524
1525 final long origId = Binder.clearCallingIdentity();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001526 try {
1527 // Transfer the starting window over to the new token.
chaviwa8f07a72019-05-01 16:25:39 -07001528 mStartingData = fromToken.mStartingData;
Peter Visontay3556a3b2017-11-01 17:23:17 +00001529 startingSurface = fromToken.startingSurface;
1530 startingDisplayed = fromToken.startingDisplayed;
1531 fromToken.startingDisplayed = false;
1532 startingWindow = tStartingWindow;
1533 reportedVisible = fromToken.reportedVisible;
chaviwa8f07a72019-05-01 16:25:39 -07001534 fromToken.mStartingData = null;
Peter Visontay3556a3b2017-11-01 17:23:17 +00001535 fromToken.startingSurface = null;
1536 fromToken.startingWindow = null;
1537 fromToken.startingMoved = true;
1538 tStartingWindow.mToken = this;
1539 tStartingWindow.mAppToken = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001540
Peter Visontay3556a3b2017-11-01 17:23:17 +00001541 if (DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
1542 "Removing starting " + tStartingWindow + " from " + fromToken);
1543 fromToken.removeChild(tStartingWindow);
1544 fromToken.postWindowRemoveStartingWindowCleanup(tStartingWindow);
1545 fromToken.mHiddenSetFromTransferredStartingWindow = false;
1546 addWindow(tStartingWindow);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001547
Peter Visontay3556a3b2017-11-01 17:23:17 +00001548 // Propagate other interesting state between the tokens. If the old token is displayed,
1549 // we should immediately force the new one to be displayed. If it is animating, we need
1550 // to move that animation to the new one.
1551 if (fromToken.allDrawn) {
1552 allDrawn = true;
1553 deferClearAllDrawn = fromToken.deferClearAllDrawn;
1554 }
1555 if (fromToken.firstWindowDrawn) {
1556 firstWindowDrawn = true;
1557 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001558 if (!fromToken.isHidden()) {
1559 setHidden(false);
Peter Visontay3556a3b2017-11-01 17:23:17 +00001560 hiddenRequested = false;
1561 mHiddenSetFromTransferredStartingWindow = true;
1562 }
1563 setClientHidden(fromToken.mClientHidden);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001564
Jorim Jaggi980c9de2017-11-17 01:41:37 +01001565 transferAnimation(fromToken);
1566
1567 // When transferring an animation, we no longer need to apply an animation to the
Tiger Huangc9d0d002019-05-29 22:55:29 +08001568 // the token we transfer the animation over. Thus, set this flag to indicate we've
1569 // transferred the animation.
1570 mUseTransferredAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001571
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001572 mWmService.updateFocusedWindowLocked(
Peter Visontay3556a3b2017-11-01 17:23:17 +00001573 UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/);
1574 getDisplayContent().setLayoutNeeded();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001575 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001576 } finally {
1577 Binder.restoreCallingIdentity(origId);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001578 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001579 return true;
chaviwa8f07a72019-05-01 16:25:39 -07001580 } else if (fromToken.mStartingData != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001581 // The previous app was getting ready to show a
1582 // starting window, but hasn't yet done so. Steal it!
1583 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
1584 "Moving pending starting from " + fromToken + " to " + this);
chaviwa8f07a72019-05-01 16:25:39 -07001585 mStartingData = fromToken.mStartingData;
1586 fromToken.mStartingData = null;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001587 fromToken.startingMoved = true;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001588 scheduleAddStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001589 return true;
1590 }
1591
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001592 // TODO: Transfer thumbnail
1593
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001594 return false;
1595 }
1596
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001597 boolean isLastWindow(WindowState win) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001598 return mChildren.size() == 1 && mChildren.get(0) == win;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001599 }
1600
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001601 @Override
1602 void onAppTransitionDone() {
1603 sendingToBottom = false;
1604 }
1605
Wale Ogunwale51362492016-09-08 17:49:17 -07001606 /**
1607 * We override because this class doesn't want its children affecting its reported orientation
1608 * in anyway.
1609 */
1610 @Override
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001611 int getOrientation(int candidate) {
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001612 if (candidate == SCREEN_ORIENTATION_BEHIND) {
1613 // Allow app to specify orientation regardless of its visibility state if the current
1614 // candidate want us to use orientation behind. I.e. the visible app on-top of this one
1615 // wants us to use the orientation of the app behind it.
1616 return mOrientation;
1617 }
1618
Bryce Lee61fbcbc2017-03-10 14:14:03 -08001619 // The {@link AppWindowToken} should only specify an orientation when it is not closing or
1620 // going to the bottom. Allowing closing {@link AppWindowToken} to participate can lead to
1621 // an Activity in another task being started in the wrong orientation during the transition.
lumark588a3e82018-07-20 18:53:54 +08001622 if (!(sendingToBottom || getDisplayContent().mClosingApps.contains(this))
1623 && (isVisible() || getDisplayContent().mOpeningApps.contains(this))) {
Bryce Leea163b762017-01-24 11:05:01 -08001624 return mOrientation;
Wale Ogunwale51362492016-09-08 17:49:17 -07001625 }
Bryce Leea163b762017-01-24 11:05:01 -08001626
1627 return SCREEN_ORIENTATION_UNSET;
Wale Ogunwale51362492016-09-08 17:49:17 -07001628 }
1629
Wale Ogunwaleb198b742016-12-01 08:44:09 -08001630 /** Returns the app's preferred orientation regardless of its currently visibility state. */
1631 int getOrientationIgnoreVisibility() {
1632 return mOrientation;
1633 }
1634
Riddle Hsub398da32019-01-21 21:48:16 +08001635 /** @return {@code true} if the compatibility bounds is taking effect. */
1636 boolean inSizeCompatMode() {
1637 return mSizeCompatBounds != null;
1638 }
1639
1640 @Override
1641 float getSizeCompatScale() {
1642 return inSizeCompatMode() ? mSizeCompatScale : super.getSizeCompatScale();
1643 }
1644
1645 /**
1646 * @return Non-empty bounds if the activity has override bounds.
1647 * @see ActivityRecord#resolveOverrideConfiguration(Configuration)
1648 */
1649 Rect getResolvedOverrideBounds() {
1650 // Get bounds from resolved override configuration because it is computed with orientation.
1651 return getResolvedOverrideConfiguration().windowConfiguration.getBounds();
1652 }
1653
Craig Mautnerdbb79912012-03-01 18:59:14 -08001654 @Override
Winson Chunge55c0192017-08-24 14:50:48 -07001655 public void onConfigurationChanged(Configuration newParentConfig) {
1656 final int prevWinMode = getWindowingMode();
Evan Rosky2289ba12018-11-19 18:28:18 -08001657 mTmpPrevBounds.set(getBounds());
Winson Chunge55c0192017-08-24 14:50:48 -07001658 super.onConfigurationChanged(newParentConfig);
Riddle Hsub398da32019-01-21 21:48:16 +08001659
1660 final Task task = getTask();
1661 final Rect overrideBounds = getResolvedOverrideBounds();
1662 if (task != null && !overrideBounds.isEmpty()
1663 // If the changes come from change-listener, the incoming parent configuration is
1664 // still the old one. Make sure their orientations are the same to reduce computing
1665 // the compatibility bounds for the intermediate state.
Riddle Hsu04164182019-03-07 18:03:27 +08001666 && (task.mTaskRecord == null || task.mTaskRecord
1667 .getConfiguration().orientation == newParentConfig.orientation)) {
Riddle Hsub398da32019-01-21 21:48:16 +08001668 final Rect taskBounds = task.getBounds();
1669 // Since we only center the activity horizontally, if only the fixed height is smaller
1670 // than its container, the override bounds don't need to take effect.
1671 if ((overrideBounds.width() != taskBounds.width()
1672 || overrideBounds.height() > taskBounds.height())) {
1673 calculateCompatBoundsTransformation(newParentConfig);
1674 updateSurfacePosition();
1675 } else if (mSizeCompatBounds != null) {
1676 mSizeCompatBounds = null;
1677 mSizeCompatScale = 1f;
1678 updateSurfacePosition();
1679 }
1680 }
1681
Winson Chunge55c0192017-08-24 14:50:48 -07001682 final int winMode = getWindowingMode();
1683
1684 if (prevWinMode == winMode) {
1685 return;
1686 }
1687
1688 if (prevWinMode != WINDOWING_MODE_UNDEFINED && winMode == WINDOWING_MODE_PINNED) {
1689 // Entering PiP from fullscreen, reset the snap fraction
1690 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(this);
Winson Chung82267ce2018-04-06 16:38:26 -07001691 } else if (prevWinMode == WINDOWING_MODE_PINNED && winMode != WINDOWING_MODE_UNDEFINED
1692 && !isHidden()) {
Winson Chunge55c0192017-08-24 14:50:48 -07001693 // Leaving PiP to fullscreen, save the snap fraction based on the pre-animation bounds
1694 // for the next re-entry into PiP (assuming the activity is not hidden or destroyed)
1695 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
1696 if (pinnedStack != null) {
Winson Chung8efa1652018-06-06 09:34:23 -07001697 final Rect stackBounds;
1698 if (pinnedStack.lastAnimatingBoundsWasToFullscreen()) {
1699 // We are animating the bounds, use the pre-animation bounds to save the snap
1700 // fraction
1701 stackBounds = pinnedStack.mPreAnimationBounds;
1702 } else {
1703 // We skip the animation if the fullscreen configuration is not compatible, so
1704 // use the current bounds to calculate the saved snap fraction instead
1705 // (see PinnedActivityStack.skipResizeAnimation())
1706 stackBounds = mTmpRect;
1707 pinnedStack.getBounds(stackBounds);
1708 }
Winson Chunge55c0192017-08-24 14:50:48 -07001709 mDisplayContent.mPinnedStackControllerLocked.saveReentrySnapFraction(this,
Winson Chung8efa1652018-06-06 09:34:23 -07001710 stackBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001711 }
Evan Rosky2289ba12018-11-19 18:28:18 -08001712 } else if (shouldStartChangeTransition(prevWinMode, winMode)) {
1713 initializeChangeTransition(mTmpPrevBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001714 }
1715 }
1716
Evan Rosky2289ba12018-11-19 18:28:18 -08001717 private boolean shouldStartChangeTransition(int prevWinMode, int newWinMode) {
Evan Rosky25b56192019-02-06 16:10:56 -08001718 if (mWmService.mDisableTransitionAnimation
1719 || !isVisible()
1720 || getDisplayContent().mAppTransition.isTransitionSet()
1721 || getSurfaceControl() == null) {
Evan Rosky2289ba12018-11-19 18:28:18 -08001722 return false;
1723 }
1724 // Only do an animation into and out-of freeform mode for now. Other mode
1725 // transition animations are currently handled by system-ui.
1726 return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
1727 }
1728
1729 /**
1730 * Initializes a change transition. Because the app is visible already, there is a small period
1731 * of time where the user can see the app content/window update before the transition starts.
1732 * To prevent this, we immediately take a snapshot and place the app/snapshot into a leash which
1733 * "freezes" the location/crop until the transition starts.
1734 * <p>
1735 * Here's a walk-through of the process:
1736 * 1. Create a temporary leash ("interim-change-leash") and reparent the app to it.
1737 * 2. Set the temporary leash's position/crop to the current state.
1738 * 3. Create a snapshot and place that at the top of the leash to cover up content changes.
1739 * 4. Once the transition is ready, it will reparent the app to the animation leash.
1740 * 5. Detach the interim-change-leash.
1741 */
1742 private void initializeChangeTransition(Rect startBounds) {
1743 mDisplayContent.prepareAppTransition(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
1744 false /* alwaysKeepCurrent */, 0, false /* forceOverride */);
1745 mDisplayContent.mChangingApps.add(this);
1746 mTransitStartRect.set(startBounds);
1747
1748 final SurfaceControl.Builder builder = makeAnimationLeash()
1749 .setParent(getAnimationLeashParent())
1750 .setName(getSurfaceControl() + " - interim-change-leash");
1751 mTransitChangeLeash = builder.build();
1752 Transaction t = getPendingTransaction();
1753 t.setWindowCrop(mTransitChangeLeash, startBounds.width(), startBounds.height());
1754 t.setPosition(mTransitChangeLeash, startBounds.left, startBounds.top);
1755 t.show(mTransitChangeLeash);
1756 t.reparent(getSurfaceControl(), mTransitChangeLeash);
1757 onAnimationLeashCreated(t, mTransitChangeLeash);
1758
Evan Rosky966759f2019-01-15 10:33:58 -08001759 // Skip creating snapshot if this transition is controlled by a remote animator which
1760 // doesn't need it.
1761 ArraySet<Integer> activityTypes = new ArraySet<>();
1762 activityTypes.add(getActivityType());
1763 RemoteAnimationAdapter adapter =
1764 mDisplayContent.mAppTransitionController.getRemoteAnimationOverride(
1765 this, TRANSIT_TASK_CHANGE_WINDOWING_MODE, activityTypes);
1766 if (adapter != null && !adapter.getChangeNeedsSnapshot()) {
1767 return;
1768 }
1769
Evan Rosky08e20932019-05-14 10:54:07 -07001770 Task task = getTask();
1771 if (mThumbnail == null && task != null && !hasCommittedReparentToAnimationLeash()) {
1772 SurfaceControl.ScreenshotGraphicBuffer snapshot =
1773 mWmService.mTaskSnapshotController.createTaskSnapshot(
1774 task, 1 /* scaleFraction */);
Yunfan Chendcb1fcf2019-02-07 19:08:41 +09001775 if (snapshot != null) {
Evan Rosky08e20932019-05-14 10:54:07 -07001776 mThumbnail = new AppWindowThumbnail(t, this, snapshot.getGraphicBuffer(),
Yunfan Chendcb1fcf2019-02-07 19:08:41 +09001777 true /* relative */);
1778 }
Evan Rosky2289ba12018-11-19 18:28:18 -08001779 }
1780 }
1781
1782 boolean isInChangeTransition() {
Evan Roskyec9488c2019-03-01 19:32:12 -08001783 return mTransitChangeLeash != null || AppTransition.isChangeTransit(mTransit);
Evan Rosky2289ba12018-11-19 18:28:18 -08001784 }
1785
Evan Rosky966759f2019-01-15 10:33:58 -08001786 @VisibleForTesting
1787 AppWindowThumbnail getThumbnail() {
1788 return mThumbnail;
1789 }
1790
Riddle Hsub398da32019-01-21 21:48:16 +08001791 /**
1792 * Calculates the scale and offset to horizontal center the size compatibility bounds into the
1793 * region which is available to application.
1794 */
1795 private void calculateCompatBoundsTransformation(Configuration newParentConfig) {
1796 final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds();
Riddle Hsu74826262019-04-17 14:57:42 +08001797 final Rect parentBounds = newParentConfig.windowConfiguration.getBounds();
1798 final Rect viewportBounds = parentAppBounds != null ? parentAppBounds : parentBounds;
Riddle Hsu04164182019-03-07 18:03:27 +08001799 final Rect appBounds = getWindowConfiguration().getAppBounds();
1800 final Rect contentBounds = appBounds != null ? appBounds : getResolvedOverrideBounds();
Riddle Hsub398da32019-01-21 21:48:16 +08001801 final float contentW = contentBounds.width();
1802 final float contentH = contentBounds.height();
1803 final float viewportW = viewportBounds.width();
1804 final float viewportH = viewportBounds.height();
1805 // Only allow to scale down.
1806 mSizeCompatScale = (contentW <= viewportW && contentH <= viewportH)
1807 ? 1 : Math.min(viewportW / contentW, viewportH / contentH);
1808 final int offsetX = (int) ((viewportW - contentW * mSizeCompatScale + 1) * 0.5f)
1809 + viewportBounds.left;
1810
1811 if (mSizeCompatBounds == null) {
1812 mSizeCompatBounds = new Rect();
1813 }
1814 mSizeCompatBounds.set(contentBounds);
1815 mSizeCompatBounds.offsetTo(0, 0);
1816 mSizeCompatBounds.scale(mSizeCompatScale);
Riddle Hsu74826262019-04-17 14:57:42 +08001817 // Ensure to align the top with the parent.
1818 mSizeCompatBounds.top = parentBounds.top;
Riddle Hsu04164182019-03-07 18:03:27 +08001819 // The decor inset is included in height.
1820 mSizeCompatBounds.bottom += viewportBounds.top;
Riddle Hsub398da32019-01-21 21:48:16 +08001821 mSizeCompatBounds.left += offsetX;
1822 mSizeCompatBounds.right += offsetX;
1823 }
1824
1825 @Override
1826 public Rect getBounds() {
1827 if (mSizeCompatBounds != null) {
1828 return mSizeCompatBounds;
1829 }
1830 return super.getBounds();
1831 }
1832
1833 @Override
1834 public boolean matchParentBounds() {
1835 if (super.matchParentBounds()) {
1836 return true;
1837 }
1838 // An activity in size compatibility mode may have override bounds which equals to its
1839 // parent bounds, so the exact bounds should also be checked.
1840 final WindowContainer parent = getParent();
1841 return parent == null || parent.getBounds().equals(getResolvedOverrideBounds());
1842 }
1843
Winson Chunge55c0192017-08-24 14:50:48 -07001844 @Override
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001845 void checkAppWindowsReadyToShow() {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001846 if (allDrawn == mLastAllDrawn) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001847 return;
1848 }
1849
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001850 mLastAllDrawn = allDrawn;
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001851 if (!allDrawn) {
1852 return;
1853 }
1854
1855 // The token has now changed state to having all windows shown... what to do, what to do?
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001856 if (mFreezingScreen) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001857 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001858 stopFreezingScreen(false, true);
1859 if (DEBUG_ORIENTATION) Slog.i(TAG,
1860 "Setting mOrientationChangeComplete=true because wtoken " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001861 + " numInteresting=" + mNumInterestingWindows + " numDrawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001862 // This will set mOrientationChangeComplete and cause a pass through layout.
1863 setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001864 "checkAppWindowsReadyToShow: freezingScreen");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001865 } else {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001866 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001867
1868 // We can now show all of the drawn windows!
lumark588a3e82018-07-20 18:53:54 +08001869 if (!getDisplayContent().mOpeningApps.contains(this) && canShowWindows()) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001870 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001871 }
1872 }
1873 }
1874
Matthew Ng5d23afa2017-06-21 16:16:24 -07001875 /**
Bryce Leed390deb2017-06-22 13:14:28 -07001876 * Returns whether the drawn window states of this {@link AppWindowToken} has considered every
1877 * child {@link WindowState}. A child is considered if it has been passed into
1878 * {@link #updateDrawnWindowStates(WindowState)} after being added. This is used to determine
1879 * whether states, such as {@code allDrawn}, can be set, which relies on state variables such as
1880 * {@code mNumInterestingWindows}, which depend on all {@link WindowState}s being considered.
1881 *
1882 * @return {@code true} If all children have been considered, {@code false}.
1883 */
1884 private boolean allDrawnStatesConsidered() {
Bryce Lee6311c4b2017-07-06 14:09:29 -07001885 for (int i = mChildren.size() - 1; i >= 0; --i) {
1886 final WindowState child = mChildren.get(i);
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001887 if (child.mightAffectAllDrawn() && !child.getDrawnStateEvaluated()) {
Bryce Leed390deb2017-06-22 13:14:28 -07001888 return false;
1889 }
1890 }
1891 return true;
1892 }
1893
1894 /**
Matthew Ng5d23afa2017-06-21 16:16:24 -07001895 * Determines if the token has finished drawing. This should only be called from
1896 * {@link DisplayContent#applySurfaceChangesTransaction}
1897 */
Matthew Ng498c71d2017-04-18 13:55:45 -07001898 void updateAllDrawn() {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001899 if (!allDrawn) {
Matthew Ng498c71d2017-04-18 13:55:45 -07001900 // Number of drawn windows can be less when a window is being relaunched, wait for
Bryce Leed390deb2017-06-22 13:14:28 -07001901 // all windows to be launched and drawn for this token be considered all drawn.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001902 final int numInteresting = mNumInterestingWindows;
Bryce Leed390deb2017-06-22 13:14:28 -07001903
1904 // We must make sure that all present children have been considered (determined by
1905 // {@link #allDrawnStatesConsidered}) before evaluating whether everything has been
1906 // drawn.
1907 if (numInteresting > 0 && allDrawnStatesConsidered()
1908 && mNumDrawnWindows >= numInteresting && !isRelaunching()) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001909 if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawn: " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001910 + " interesting=" + numInteresting + " drawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001911 allDrawn = true;
1912 // Force an additional layout pass where
1913 // WindowStateAnimator#commitFinishDrawingLocked() will call performShowLocked().
Matthew Ng498c71d2017-04-18 13:55:45 -07001914 if (mDisplayContent != null) {
1915 mDisplayContent.setLayoutNeeded();
1916 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001917 mWmService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
Robert Carrecc06b32017-04-18 14:25:10 -07001918
Winson Chunge7ba6862017-05-24 12:13:33 -07001919 // Notify the pinned stack upon all windows drawn. If there was an animation in
1920 // progress then this signal will resume that animation.
Wale Ogunwale61911492017-10-11 08:50:50 -07001921 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
Winson Chunge7ba6862017-05-24 12:13:33 -07001922 if (pinnedStack != null) {
1923 pinnedStack.onAllWindowsDrawn();
Robert Carrecc06b32017-04-18 14:25:10 -07001924 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001925 }
1926 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001927 }
1928
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001929 boolean keyDispatchingTimedOut(String reason, int windowPid) {
1930 return mActivityRecord != null && mActivityRecord.keyDispatchingTimedOut(reason, windowPid);
1931 }
1932
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001933 /**
1934 * Updated this app token tracking states for interesting and drawn windows based on the window.
1935 *
1936 * @return Returns true if the input window is considered interesting and drawn while all the
1937 * windows in this app token where not considered drawn as of the last pass.
1938 */
1939 boolean updateDrawnWindowStates(WindowState w) {
Bryce Leed390deb2017-06-22 13:14:28 -07001940 w.setDrawnStateEvaluated(true /*evaluated*/);
1941
Jorim Jaggie4b0f282017-05-17 15:10:29 +02001942 if (DEBUG_STARTING_WINDOW_VERBOSE && w == startingWindow) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001943 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + w.isOnScreen()
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001944 + " allDrawn=" + allDrawn + " freezingScreen=" + mFreezingScreen);
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001945 }
1946
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001947 if (allDrawn && !mFreezingScreen) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001948 return false;
1949 }
1950
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001951 if (mLastTransactionSequence != mWmService.mTransactionSequence) {
1952 mLastTransactionSequence = mWmService.mTransactionSequence;
Matthew Ng53e66b22018-01-12 17:13:13 -08001953 mNumDrawnWindows = 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001954 startingDisplayed = false;
Matthew Ng53e66b22018-01-12 17:13:13 -08001955
1956 // There is the main base application window, even if it is exiting, wait for it
1957 mNumInterestingWindows = findMainWindow(false /* includeStartingApp */) != null ? 1 : 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001958 }
1959
1960 final WindowStateAnimator winAnimator = w.mWinAnimator;
1961
1962 boolean isInterestingAndDrawn = false;
1963
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001964 if (!allDrawn && w.mightAffectAllDrawn()) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001965 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
1966 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001967 + ", isAnimationSet=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001968 if (!w.isDrawnLw()) {
1969 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController
chaviw15ad49f2019-04-24 15:05:39 -07001970 + " pv=" + w.isVisibleByPolicy()
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001971 + " mDrawState=" + winAnimator.drawStateToString()
1972 + " ph=" + w.isParentWindowHidden() + " th=" + hiddenRequested
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001973 + " a=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001974 }
1975 }
1976
1977 if (w != startingWindow) {
1978 if (w.isInteresting()) {
Matthew Ng53e66b22018-01-12 17:13:13 -08001979 // Add non-main window as interesting since the main app has already been added
1980 if (findMainWindow(false /* includeStartingApp */) != w) {
1981 mNumInterestingWindows++;
1982 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001983 if (w.isDrawnLw()) {
1984 mNumDrawnWindows++;
1985
1986 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, "tokenMayBeDrawn: "
1987 + this + " w=" + w + " numInteresting=" + mNumInterestingWindows
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001988 + " freezingScreen=" + mFreezingScreen
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001989 + " mAppFreezing=" + w.mAppFreezing);
1990
1991 isInterestingAndDrawn = true;
1992 }
1993 }
1994 } else if (w.isDrawnLw()) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001995 if (mActivityRecord != null) {
1996 mActivityRecord.onStartingWindowDrawn(SystemClock.uptimeMillis());
Jorim Jaggi3878ca32017-02-02 17:13:05 -08001997 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001998 startingDisplayed = true;
1999 }
2000 }
2001
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002002 return isInterestingAndDrawn;
2003 }
2004
Adrian Roos23df3a32018-03-15 15:41:13 +01002005 void layoutLetterbox(WindowState winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002006 final WindowState w = findMainWindow();
Adrian Roosf93b6d22018-03-21 13:48:26 +01002007 if (w == null || winHint != null && w != winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002008 return;
2009 }
Jorim Jaggia32da382018-03-28 18:01:22 +02002010 final boolean surfaceReady = w.isDrawnLw() // Regular case
Adrian Roosf93b6d22018-03-21 13:48:26 +01002011 || w.mWinAnimator.mSurfaceDestroyDeferred // The preserved surface is still ready.
2012 || w.isDragResizeChanged(); // Waiting for relayoutWindow to call preserveSurface.
Jorim Jaggi4981f152019-03-26 18:58:45 +01002013 final boolean needsLetterbox = surfaceReady && w.isLetterboxedAppWindow() && fillsParent();
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002014 if (needsLetterbox) {
2015 if (mLetterbox == null) {
2016 mLetterbox = new Letterbox(() -> makeChildSurface(null));
Riddle Hsu192fe762019-01-15 23:41:57 +08002017 mLetterbox.attachInput(w);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002018 }
Adrian Roos7af9d972018-11-30 15:26:27 +01002019 getPosition(mTmpPoint);
Evan Rosky67c15642019-04-24 13:17:28 -07002020 // Get the bounds of the "space-to-fill". In multi-window mode, the task-level
2021 // represents this. In fullscreen-mode, the stack does (since the orientation letterbox
2022 // is also applied to the task).
2023 Rect spaceToFill = (inMultiWindowMode() || getStack() == null)
2024 ? getTask().getDisplayedBounds() : getStack().getDisplayedBounds();
Evan Rosky4fb1e912019-03-06 13:54:43 -08002025 mLetterbox.layout(spaceToFill, w.getFrameLw(), mTmpPoint);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002026 } else if (mLetterbox != null) {
Adrian Roos23df3a32018-03-15 15:41:13 +01002027 mLetterbox.hide();
2028 }
2029 }
2030
2031 void updateLetterboxSurface(WindowState winHint) {
2032 final WindowState w = findMainWindow();
2033 if (w != winHint && winHint != null && w != null) {
2034 return;
2035 }
2036 layoutLetterbox(winHint);
2037 if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) {
Tiger Huanged6794e2019-05-07 20:07:59 +08002038 mLetterbox.applySurfaceChanges(getPendingTransaction());
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002039 }
2040 }
2041
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07002042 @Override
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002043 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002044 // For legacy reasons we process the TaskStack.mExitingAppTokens first in DisplayContent
2045 // before the non-exiting app tokens. So, we skip the exiting app tokens here.
2046 // TODO: Investigate if we need to continue to do this or if we can just process them
2047 // in-order.
2048 if (mIsExiting && !waitingForReplacement()) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002049 return false;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002050 }
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002051 return forAllWindowsUnchecked(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002052 }
2053
lumark588a3e82018-07-20 18:53:54 +08002054 @Override
2055 void forAllAppWindows(Consumer<AppWindowToken> callback) {
2056 callback.accept(this);
2057 }
2058
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002059 boolean forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback,
2060 boolean traverseTopToBottom) {
2061 return super.forAllWindows(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002062 }
2063
2064 @Override
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002065 AppWindowToken asAppWindowToken() {
2066 // I am an app window token!
2067 return this;
2068 }
2069
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002070 boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
2071 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
2072 IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
2073 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
2074 // If the display is frozen, we won't do anything until the actual window is
2075 // displayed so there is no reason to put in the starting window.
2076 if (!okToDisplay()) {
2077 return false;
2078 }
2079
chaviwa8f07a72019-05-01 16:25:39 -07002080 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002081 return false;
2082 }
2083
2084 final WindowState mainWin = findMainWindow();
2085 if (mainWin != null && mainWin.mWinAnimator.getShown()) {
2086 // App already has a visible window...why would you want a starting window?
2087 return false;
2088 }
2089
2090 final ActivityManager.TaskSnapshot snapshot =
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002091 mWmService.mTaskSnapshotController.getSnapshot(
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002092 getTask().mTaskId, getTask().mUserId,
2093 false /* restoreFromDisk */, false /* reducedResolution */);
2094 final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
2095 allowTaskSnapshot, activityCreated, fromRecents, snapshot);
2096
2097 if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
2098 return createSnapshot(snapshot);
2099 }
2100
2101 // If this is a translucent window, then don't show a starting window -- the current
2102 // effect (a full-screen opaque starting window that fades away to the real contents
2103 // when it is ready) does not work for this.
2104 if (DEBUG_STARTING_WINDOW) {
2105 Slog.v(TAG, "Checking theme of starting window: 0x" + Integer.toHexString(theme));
2106 }
2107 if (theme != 0) {
2108 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
2109 com.android.internal.R.styleable.Window,
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002110 mWmService.mCurrentUserId);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002111 if (ent == null) {
2112 // Whoops! App doesn't exist. Um. Okay. We'll just pretend like we didn't
2113 // see that.
2114 return false;
2115 }
2116 final boolean windowIsTranslucent = ent.array.getBoolean(
2117 com.android.internal.R.styleable.Window_windowIsTranslucent, false);
2118 final boolean windowIsFloating = ent.array.getBoolean(
2119 com.android.internal.R.styleable.Window_windowIsFloating, false);
2120 final boolean windowShowWallpaper = ent.array.getBoolean(
2121 com.android.internal.R.styleable.Window_windowShowWallpaper, false);
2122 final boolean windowDisableStarting = ent.array.getBoolean(
2123 com.android.internal.R.styleable.Window_windowDisablePreview, false);
2124 if (DEBUG_STARTING_WINDOW) {
2125 Slog.v(TAG, "Translucent=" + windowIsTranslucent
2126 + " Floating=" + windowIsFloating
2127 + " ShowWallpaper=" + windowShowWallpaper);
2128 }
2129 if (windowIsTranslucent) {
2130 return false;
2131 }
2132 if (windowIsFloating || windowDisableStarting) {
2133 return false;
2134 }
2135 if (windowShowWallpaper) {
2136 if (getDisplayContent().mWallpaperController
2137 .getWallpaperTarget() == null) {
2138 // If this theme is requesting a wallpaper, and the wallpaper
2139 // is not currently visible, then this effectively serves as
2140 // an opaque window and our starting window transition animation
2141 // can still work. We just need to make sure the starting window
2142 // is also showing the wallpaper.
2143 windowFlags |= FLAG_SHOW_WALLPAPER;
2144 } else {
2145 return false;
2146 }
2147 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002148 }
Yunfan Chen8a8c0ed2018-12-18 16:46:32 -08002149
2150 if (transferStartingWindow(transferFrom)) {
2151 return true;
2152 }
2153
2154 // There is no existing starting window, and we don't want to create a splash screen, so
2155 // that's it!
2156 if (type != STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
2157 return false;
2158 }
2159
2160 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SplashScreenStartingData");
chaviwa8f07a72019-05-01 16:25:39 -07002161 mStartingData = new SplashScreenStartingData(mWmService, pkg,
Yunfan Chen8a8c0ed2018-12-18 16:46:32 -08002162 theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
2163 getMergedOverrideConfiguration());
2164 scheduleAddStartingWindow();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002165 return true;
2166 }
2167
2168
2169 private boolean createSnapshot(ActivityManager.TaskSnapshot snapshot) {
2170 if (snapshot == null) {
2171 return false;
2172 }
2173
2174 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SnapshotStartingData");
chaviwa8f07a72019-05-01 16:25:39 -07002175 mStartingData = new SnapshotStartingData(mWmService, snapshot);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002176 scheduleAddStartingWindow();
2177 return true;
2178 }
2179
2180 void scheduleAddStartingWindow() {
2181 // Note: we really want to do sendMessageAtFrontOfQueue() because we
2182 // want to process the message ASAP, before any other queued
2183 // messages.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002184 if (!mWmService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002185 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING");
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002186 mWmService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002187 }
2188 }
2189
2190 private final Runnable mAddStartingWindow = new Runnable() {
2191
2192 @Override
2193 public void run() {
chaviwa8f07a72019-05-01 16:25:39 -07002194 // Can be accessed without holding the global lock
2195 final StartingData startingData;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002196 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002197 // There can only be one adding request, silly caller!
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002198 mWmService.mAnimationHandler.removeCallbacks(this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002199
chaviwa8f07a72019-05-01 16:25:39 -07002200 if (mStartingData == null) {
2201 // Animation has been canceled... do nothing.
2202 if (DEBUG_STARTING_WINDOW) {
2203 Slog.v(TAG, "startingData was nulled out before handling"
2204 + " mAddStartingWindow: " + AppWindowToken.this);
2205 }
2206 return;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002207 }
chaviwa8f07a72019-05-01 16:25:39 -07002208 startingData = mStartingData;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002209 }
2210
2211 if (DEBUG_STARTING_WINDOW) {
2212 Slog.v(TAG, "Add starting " + this + ": startingData=" + startingData);
2213 }
2214
2215 WindowManagerPolicy.StartingSurface surface = null;
2216 try {
2217 surface = startingData.createStartingSurface(AppWindowToken.this);
2218 } catch (Exception e) {
2219 Slog.w(TAG, "Exception when adding starting window", e);
2220 }
2221 if (surface != null) {
2222 boolean abort = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002223 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002224 // If the window was successfully added, then
2225 // we need to remove it.
chaviwa8f07a72019-05-01 16:25:39 -07002226 if (removed || mStartingData == null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002227 if (DEBUG_STARTING_WINDOW) {
2228 Slog.v(TAG, "Aborted starting " + AppWindowToken.this
chaviwa8f07a72019-05-01 16:25:39 -07002229 + ": removed=" + removed + " startingData=" + mStartingData);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002230 }
2231 startingWindow = null;
chaviwa8f07a72019-05-01 16:25:39 -07002232 mStartingData = null;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002233 abort = true;
2234 } else {
2235 startingSurface = surface;
2236 }
2237 if (DEBUG_STARTING_WINDOW && !abort) {
chaviwa8f07a72019-05-01 16:25:39 -07002238 Slog.v(TAG,
2239 "Added starting " + AppWindowToken.this + ": startingWindow="
2240 + startingWindow + " startingView=" + startingSurface);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002241 }
2242 }
2243 if (abort) {
2244 surface.remove();
2245 }
2246 } else if (DEBUG_STARTING_WINDOW) {
2247 Slog.v(TAG, "Surface returned was null: " + AppWindowToken.this);
2248 }
2249 }
2250 };
2251
2252 private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
2253 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents,
2254 ActivityManager.TaskSnapshot snapshot) {
2255 if (getDisplayContent().mAppTransition.getAppTransition()
2256 == TRANSIT_DOCK_TASK_FROM_RECENTS) {
2257 // TODO(b/34099271): Remove this statement to add back the starting window and figure
2258 // out why it causes flickering, the starting window appears over the thumbnail while
2259 // the docked from recents transition occurs
2260 return STARTING_WINDOW_TYPE_NONE;
2261 } else if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
2262 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2263 } else if (taskSwitch && allowTaskSnapshot) {
Kevin716a9db2018-12-18 16:53:39 -08002264 if (mWmService.mLowRamTaskSnapshotsAndRecents) {
Kevin58b47f12018-12-17 14:09:01 -08002265 // For low RAM devices, we use the splash screen starting window instead of the
2266 // task snapshot starting window.
2267 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2268 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002269 return snapshot == null ? STARTING_WINDOW_TYPE_NONE
2270 : snapshotOrientationSameAsTask(snapshot) || fromRecents
2271 ? STARTING_WINDOW_TYPE_SNAPSHOT : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2272 } else {
2273 return STARTING_WINDOW_TYPE_NONE;
2274 }
2275 }
2276
2277
2278 private boolean snapshotOrientationSameAsTask(ActivityManager.TaskSnapshot snapshot) {
2279 if (snapshot == null) {
2280 return false;
2281 }
2282 return getTask().getConfiguration().orientation == snapshot.getOrientation();
2283 }
2284
2285 void removeStartingWindow() {
2286 if (startingWindow == null) {
chaviwa8f07a72019-05-01 16:25:39 -07002287 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002288 // Starting window has not been added yet, but it is scheduled to be added.
2289 // Go ahead and cancel the request.
2290 if (DEBUG_STARTING_WINDOW) {
2291 Slog.v(TAG_WM, "Clearing startingData for token=" + this);
2292 }
chaviwa8f07a72019-05-01 16:25:39 -07002293 mStartingData = null;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002294 }
2295 return;
2296 }
2297
2298 final WindowManagerPolicy.StartingSurface surface;
chaviwa8f07a72019-05-01 16:25:39 -07002299 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002300 surface = startingSurface;
chaviwa8f07a72019-05-01 16:25:39 -07002301 mStartingData = null;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002302 startingSurface = null;
2303 startingWindow = null;
2304 startingDisplayed = false;
2305 if (surface == null) {
2306 if (DEBUG_STARTING_WINDOW) {
2307 Slog.v(TAG_WM, "startingWindow was set but startingSurface==null, couldn't "
2308 + "remove");
2309 }
2310 return;
2311 }
2312 } else {
2313 if (DEBUG_STARTING_WINDOW) {
2314 Slog.v(TAG_WM, "Tried to remove starting window but startingWindow was null:"
2315 + this);
2316 }
2317 return;
2318 }
2319
2320 if (DEBUG_STARTING_WINDOW) {
2321 Slog.v(TAG_WM, "Schedule remove starting " + this
2322 + " startingWindow=" + startingWindow
2323 + " startingView=" + startingSurface
2324 + " Callers=" + Debug.getCallers(5));
2325 }
2326
2327 // Use the same thread to remove the window as we used to add it, as otherwise we end up
2328 // with things in the view hierarchy being called from different threads.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002329 mWmService.mAnimationHandler.post(() -> {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002330 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Removing startingView=" + surface);
2331 try {
2332 surface.remove();
2333 } catch (Exception e) {
2334 Slog.w(TAG_WM, "Exception when removing starting window", e);
2335 }
2336 });
2337 }
2338
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002339 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -07002340 boolean fillsParent() {
2341 return mFillsParent;
2342 }
2343
2344 void setFillsParent(boolean fillsParent) {
2345 mFillsParent = fillsParent;
2346 }
2347
Jorim Jaggife762342016-10-13 14:33:27 +02002348 boolean containsDismissKeyguardWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002349 // Window state is transient during relaunch. We are not guaranteed to be frozen during the
2350 // entirety of the relaunch.
2351 if (isRelaunching()) {
2352 return mLastContainsDismissKeyguardWindow;
2353 }
2354
Jorim Jaggife762342016-10-13 14:33:27 +02002355 for (int i = mChildren.size() - 1; i >= 0; i--) {
2356 if ((mChildren.get(i).mAttrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
2357 return true;
2358 }
2359 }
2360 return false;
2361 }
2362
2363 boolean containsShowWhenLockedWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002364 // When we are relaunching, it is possible for us to be unfrozen before our previous
2365 // windows have been added back. Using the cached value ensures that our previous
2366 // showWhenLocked preference is honored until relaunching is complete.
2367 if (isRelaunching()) {
2368 return mLastContainsShowWhenLockedWindow;
2369 }
2370
Jorim Jaggife762342016-10-13 14:33:27 +02002371 for (int i = mChildren.size() - 1; i >= 0; i--) {
2372 if ((mChildren.get(i).mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
2373 return true;
2374 }
2375 }
Bryce Lee081554b2017-05-25 07:52:12 -07002376
Jorim Jaggife762342016-10-13 14:33:27 +02002377 return false;
2378 }
2379
2380 void checkKeyguardFlagsChanged() {
2381 final boolean containsDismissKeyguard = containsDismissKeyguardWindow();
2382 final boolean containsShowWhenLocked = containsShowWhenLockedWindow();
2383 if (containsDismissKeyguard != mLastContainsDismissKeyguardWindow
2384 || containsShowWhenLocked != mLastContainsShowWhenLockedWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002385 mWmService.notifyKeyguardFlagsChanged(null /* callback */,
lumark588a3e82018-07-20 18:53:54 +08002386 getDisplayContent().getDisplayId());
Jorim Jaggife762342016-10-13 14:33:27 +02002387 }
2388 mLastContainsDismissKeyguardWindow = containsDismissKeyguard;
2389 mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
2390 }
2391
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002392 WindowState getImeTargetBelowWindow(WindowState w) {
2393 final int index = mChildren.indexOf(w);
2394 if (index > 0) {
2395 final WindowState target = mChildren.get(index - 1);
2396 if (target.canBeImeTarget()) {
2397 return target;
2398 }
2399 }
2400 return null;
2401 }
2402
2403 WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
2404 WindowState candidate = null;
2405 for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
2406 final WindowState w = mChildren.get(i);
2407 if (w.mRemoved) {
2408 continue;
2409 }
Jorim Jaggi35d328a2018-08-14 17:00:20 +02002410 if (candidate == null) {
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002411 candidate = w;
2412 }
2413 }
2414 return candidate;
2415 }
2416
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002417 /**
2418 * See {@link Activity#setDisablePreviewScreenshots}.
2419 */
2420 void setDisablePreviewScreenshots(boolean disable) {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002421 mDisablePreviewScreenshots = disable;
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002422 }
2423
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002424 /**
chaviwd3bf08d2017-08-01 17:24:59 -07002425 * Sets whether the current launch can turn the screen on. See {@link #canTurnScreenOn()}
2426 */
2427 void setCanTurnScreenOn(boolean canTurnScreenOn) {
2428 mCanTurnScreenOn = canTurnScreenOn;
2429 }
2430
2431 /**
2432 * Indicates whether the current launch can turn the screen on. This is to prevent multiple
2433 * relayouts from turning the screen back on. The screen should only turn on at most
2434 * once per activity resume.
2435 *
2436 * @return true if the screen can be turned on.
2437 */
2438 boolean canTurnScreenOn() {
2439 return mCanTurnScreenOn;
2440 }
2441
2442 /**
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002443 * Retrieves whether we'd like to generate a snapshot that's based solely on the theme. This is
2444 * the case when preview screenshots are disabled {@link #setDisablePreviewScreenshots} or when
2445 * we can't take a snapshot for other reasons, for example, if we have a secure window.
2446 *
2447 * @return True if we need to generate an app theme snapshot, false if we'd like to take a real
2448 * screenshot.
2449 */
2450 boolean shouldUseAppThemeSnapshot() {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002451 return mDisablePreviewScreenshots || forAllWindows(w -> (w.mAttrs.flags & FLAG_SECURE) != 0,
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002452 true /* topToBottom */);
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002453 }
2454
Jorim Jaggibe418292018-03-26 16:14:12 +02002455 SurfaceControl getAppAnimationLayer() {
Jorim Jaggi391790622018-04-18 15:30:44 +02002456 return getAppAnimationLayer(isActivityTypeHome() ? ANIMATION_LAYER_HOME
2457 : needsZBoost() ? ANIMATION_LAYER_BOOSTED
2458 : ANIMATION_LAYER_STANDARD);
Jorim Jaggibe418292018-03-26 16:14:12 +02002459 }
2460
chaviw23ee71c2017-12-18 11:29:41 -08002461 @Override
Jorim Jaggi596a1992017-12-29 14:48:02 +01002462 public SurfaceControl getAnimationLeashParent() {
Robert Carrb9506032018-02-13 13:54:00 -08002463 // All normal app transitions take place in an animation layer which is below the pinned
2464 // stack but may be above the parent stacks of the given animating apps.
2465 // For transitions in the pinned stack (menu activity) we just let them occur as a child
2466 // of the pinned stack.
2467 if (!inPinnedWindowingMode()) {
2468 return getAppAnimationLayer();
2469 } else {
2470 return getStack().getSurfaceControl();
2471 }
chaviw23ee71c2017-12-18 11:29:41 -08002472 }
2473
lumarkb5a78b32019-04-25 20:31:30 +08002474
2475 @VisibleForTesting
2476 boolean shouldAnimate(int transit) {
Jorim Jaggic6976f02018-04-18 16:31:07 +02002477 final boolean isSplitScreenPrimary =
2478 getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
2479 final boolean allowSplitScreenPrimaryAnimation = transit != TRANSIT_WALLPAPER_OPEN;
2480
lumarkb5a78b32019-04-25 20:31:30 +08002481 // Don't animate while the task runs recents animation but only if we are in the mode
2482 // where we cancel with deferred screenshot, which means that the controller has
2483 // transformed the task.
lumark54284462019-03-05 20:44:27 +08002484 final RecentsAnimationController controller = mWmService.getRecentsAnimationController();
lumarkb5a78b32019-04-25 20:31:30 +08002485 if (controller != null && controller.isAnimatingTask(getTask())
2486 && controller.shouldCancelWithDeferredScreenshot()) {
lumark54284462019-03-05 20:44:27 +08002487 return false;
2488 }
2489
Jorim Jaggic6976f02018-04-18 16:31:07 +02002490 // We animate always if it's not split screen primary, and only some special cases in split
2491 // screen primary because it causes issues with stack clipping when we run an un-minimize
2492 // animation at the same time.
2493 return !isSplitScreenPrimary || allowSplitScreenPrimaryAnimation;
2494 }
2495
Vishnu Naira2977262018-07-26 13:31:26 -07002496 /**
2497 * Creates a layer to apply crop to an animation.
2498 */
2499 private SurfaceControl createAnimationBoundsLayer(Transaction t) {
2500 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.i(TAG, "Creating animation bounds layer");
2501 final SurfaceControl.Builder builder = makeAnimationLeash()
2502 .setParent(getAnimationLeashParent())
Vishnu Naire86bd982018-11-28 13:23:17 -08002503 .setName(getSurfaceControl() + " - animation-bounds");
Vishnu Naira2977262018-07-26 13:31:26 -07002504 final SurfaceControl boundsLayer = builder.build();
2505 t.show(boundsLayer);
2506 return boundsLayer;
2507 }
2508
Evan Roskyed6767f2018-10-26 17:21:06 -07002509 @Override
2510 Rect getDisplayedBounds() {
2511 final Task task = getTask();
2512 if (task != null) {
2513 final Rect overrideDisplayedBounds = task.getOverrideDisplayedBounds();
2514 if (!overrideDisplayedBounds.isEmpty()) {
2515 return overrideDisplayedBounds;
2516 }
2517 }
2518 return getBounds();
2519 }
2520
Evan Rosky641daea2019-04-24 14:45:24 -07002521 @VisibleForTesting
2522 Rect getAnimationBounds(int appStackClipMode) {
2523 if (appStackClipMode == STACK_CLIP_BEFORE_ANIM && getStack() != null) {
2524 // Using the stack bounds here effectively applies the clipping before animation.
2525 return getStack().getBounds();
2526 }
2527 // Use task-bounds if available so that activity-level letterbox (maxAspectRatio) is
2528 // included in the animation.
2529 return getTask() != null ? getTask().getBounds() : getBounds();
2530 }
2531
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002532 boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter,
2533 boolean isVoiceInteraction) {
2534
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002535 if (mWmService.mDisableTransitionAnimation || !shouldAnimate(transit)) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002536 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
Jorim Jaggic6976f02018-04-18 16:31:07 +02002537 Slog.v(TAG_WM, "applyAnimation: transition animation is disabled or skipped."
2538 + " atoken=" + this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002539 }
2540 cancelAnimation();
2541 return false;
2542 }
2543
2544 // Only apply an animation if the display isn't frozen. If it is frozen, there is no reason
2545 // to animate and it can cause strange artifacts when we unfreeze the display if some
2546 // different animation is running.
2547 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#applyAnimationLocked");
2548 if (okToAnimate()) {
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002549 final AnimationAdapter adapter;
Evan Rosky2289ba12018-11-19 18:28:18 -08002550 AnimationAdapter thumbnailAdapter = null;
Evan Rosky4fb1e912019-03-06 13:54:43 -08002551
Evan Rosky641daea2019-04-24 14:45:24 -07002552 final int appStackClipMode =
2553 getDisplayContent().mAppTransition.getAppStackClipMode();
2554
2555 // Separate position and size for use in animators.
2556 mTmpRect.set(getAnimationBounds(appStackClipMode));
Evan Rosky4fb1e912019-03-06 13:54:43 -08002557 mTmpPoint.set(mTmpRect.left, mTmpRect.top);
2558 mTmpRect.offsetTo(0, 0);
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002559
Evan Roskyec9488c2019-03-01 19:32:12 -08002560 final boolean isChanging = AppTransition.isChangeTransit(transit) && enter
2561 && getDisplayContent().mChangingApps.contains(this);
Evan Rosky2289ba12018-11-19 18:28:18 -08002562
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002563 // Delaying animation start isn't compatible with remote animations at all.
lumark588a3e82018-07-20 18:53:54 +08002564 if (getDisplayContent().mAppTransition.getRemoteAnimationController() != null
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002565 && !mSurfaceAnimator.isAnimationStartDelayed()) {
Evan Rosky2289ba12018-11-19 18:28:18 -08002566 RemoteAnimationRecord adapters =
2567 getDisplayContent().mAppTransition.getRemoteAnimationController()
2568 .createRemoteAnimationRecord(this, mTmpPoint, mTmpRect,
2569 (isChanging ? mTransitStartRect : null));
2570 adapter = adapters.mAdapter;
2571 thumbnailAdapter = adapters.mThumbnailAdapter;
2572 } else if (isChanging) {
Evan Roskycf76bed2019-01-15 10:33:58 -08002573 final float durationScale = mWmService.getTransitionAnimationScaleLocked();
Evan Rosky2289ba12018-11-19 18:28:18 -08002574 mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y);
2575 adapter = new LocalAnimationAdapter(
2576 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
Evan Roskycf76bed2019-01-15 10:33:58 -08002577 getDisplayContent().getDisplayInfo(), durationScale,
Evan Rosky2289ba12018-11-19 18:28:18 -08002578 true /* isAppAnimation */, false /* isThumbnail */),
2579 mWmService.mSurfaceAnimationRunner);
Evan Rosky966759f2019-01-15 10:33:58 -08002580 if (mThumbnail != null) {
2581 thumbnailAdapter = new LocalAnimationAdapter(
2582 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
Evan Roskycf76bed2019-01-15 10:33:58 -08002583 getDisplayContent().getDisplayInfo(), durationScale,
Evan Rosky966759f2019-01-15 10:33:58 -08002584 true /* isAppAnimation */, true /* isThumbnail */),
2585 mWmService.mSurfaceAnimationRunner);
2586 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002587 mTransit = transit;
2588 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002589 } else {
Vishnu Naira2977262018-07-26 13:31:26 -07002590 mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM);
2591
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002592 final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
2593 if (a != null) {
Lucas Dupin95acf432019-04-29 17:55:38 -07002594 // Only apply corner radius to animation if we're not in multi window mode.
2595 // We don't want rounded corners when in pip or split screen.
2596 final float windowCornerRadius = !inMultiWindowMode()
2597 ? getDisplayContent().getWindowCornerRadius()
2598 : 0;
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002599 adapter = new LocalAnimationAdapter(
2600 new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
lumark588a3e82018-07-20 18:53:54 +08002601 getDisplayContent().mAppTransition.canSkipFirstFrame(),
Vishnu Naira2977262018-07-26 13:31:26 -07002602 appStackClipMode,
Lucas Dupin3e1dc202018-12-02 15:14:20 -08002603 true /* isAppAnimation */,
Lucas Dupin95acf432019-04-29 17:55:38 -07002604 windowCornerRadius),
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002605 mWmService.mSurfaceAnimationRunner);
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002606 if (a.getZAdjustment() == Animation.ZORDER_TOP) {
2607 mNeedsZBoost = true;
2608 }
2609 mTransit = transit;
lumark588a3e82018-07-20 18:53:54 +08002610 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002611 } else {
2612 adapter = null;
chaviw23ee71c2017-12-18 11:29:41 -08002613 }
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002614 }
2615 if (adapter != null) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002616 startAnimation(getPendingTransaction(), adapter, !isVisible());
Jorim Jaggi82c17862018-02-21 17:50:18 +01002617 if (adapter.getShowWallpaper()) {
2618 mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2619 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002620 if (thumbnailAdapter != null) {
2621 mThumbnail.startAnimation(
2622 getPendingTransaction(), thumbnailAdapter, !isVisible());
2623 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002624 }
2625 } else {
2626 cancelAnimation();
2627 }
2628 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2629
2630 return isReallyAnimating();
2631 }
2632
2633 private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
2634 boolean isVoiceInteraction) {
2635 final DisplayContent displayContent = getTask().getDisplayContent();
2636 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2637 final int width = displayInfo.appWidth;
2638 final int height = displayInfo.appHeight;
2639 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG_WM,
2640 "applyAnimation: atoken=" + this);
2641
2642 // Determine the visible rect to calculate the thumbnail clip
2643 final WindowState win = findMainWindow();
2644 final Rect frame = new Rect(0, 0, width, height);
2645 final Rect displayFrame = new Rect(0, 0,
2646 displayInfo.logicalWidth, displayInfo.logicalHeight);
2647 final Rect insets = new Rect();
2648 final Rect stableInsets = new Rect();
2649 Rect surfaceInsets = null;
2650 final boolean freeform = win != null && win.inFreeformWindowingMode();
2651 if (win != null) {
2652 // Containing frame will usually cover the whole screen, including dialog windows.
2653 // For freeform workspace windows it will not cover the whole screen and it also
2654 // won't exactly match the final freeform window frame (e.g. when overlapping with
2655 // the status bar). In that case we need to use the final frame.
2656 if (freeform) {
chaviw492139a2018-07-16 16:07:35 -07002657 frame.set(win.getFrameLw());
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002658 } else if (win.isLetterboxedAppWindow()) {
2659 frame.set(getTask().getBounds());
Winson Chungc1674272018-02-21 10:15:17 -08002660 } else if (win.isDockedResizing()) {
2661 // If we are animating while docked resizing, then use the stack bounds as the
2662 // animation target (which will be different than the task bounds)
2663 frame.set(getTask().getParent().getBounds());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002664 } else {
chaviw553b0212018-07-12 13:37:01 -07002665 frame.set(win.getContainingFrame());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002666 }
2667 surfaceInsets = win.getAttrs().surfaceInsets;
Adrian Roos20e07892018-02-23 19:12:01 +01002668 // XXX(b/72757033): These are insets relative to the window frame, but we're really
2669 // interested in the insets relative to the frame we chose in the if-blocks above.
chaviw9c81e632018-07-31 11:17:52 -07002670 win.getContentInsets(insets);
2671 win.getStableInsets(stableInsets);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002672 }
2673
2674 if (mLaunchTaskBehind) {
2675 // Differentiate the two animations. This one which is briefly on the screen
2676 // gets the !enter animation, and the other activity which remains on the
2677 // screen gets the enter animation. Both appear in the mOpeningApps set.
2678 enter = false;
2679 }
2680 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "Loading animation for app transition."
2681 + " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter
2682 + " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets);
2683 final Configuration displayConfig = displayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08002684 final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002685 displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
2686 surfaceInsets, stableInsets, isVoiceInteraction, freeform, getTask().mTaskId);
2687 if (a != null) {
2688 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
2689 final int containingWidth = frame.width();
2690 final int containingHeight = frame.height();
2691 a.initialize(containingWidth, containingHeight, width, height);
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002692 a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002693 }
2694 return a;
2695 }
2696
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002697 @Override
Jorim Jaggi6de61012018-03-19 14:53:23 +01002698 public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
2699 return mAnimatingAppWindowTokenRegistry != null
2700 && mAnimatingAppWindowTokenRegistry.notifyAboutToFinish(
2701 this, endDeferFinishCallback);
2702 }
2703
2704 @Override
lumarkf6f34942019-04-29 16:56:50 +08002705 public void onAnimationLeashLost(Transaction t) {
2706 super.onAnimationLeashLost(t);
Vishnu Naira2977262018-07-26 13:31:26 -07002707 if (mAnimationBoundsLayer != null) {
Robert Carr71200f22019-02-05 09:44:53 -08002708 t.remove(mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002709 mAnimationBoundsLayer = null;
2710 }
2711
Jorim Jaggi6de61012018-03-19 14:53:23 +01002712 if (mAnimatingAppWindowTokenRegistry != null) {
2713 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
2714 }
2715 }
2716
2717 @Override
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002718 protected void setLayer(Transaction t, int layer) {
2719 if (!mSurfaceAnimator.hasLeash()) {
2720 t.setLayer(mSurfaceControl, layer);
2721 }
2722 }
2723
2724 @Override
2725 protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
2726 if (!mSurfaceAnimator.hasLeash()) {
2727 t.setRelativeLayer(mSurfaceControl, relativeTo, layer);
2728 }
2729 }
2730
2731 @Override
2732 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
2733 if (!mSurfaceAnimator.hasLeash()) {
Robert Carr10584fa2019-01-14 15:55:19 -08002734 t.reparent(mSurfaceControl, newParent);
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002735 }
2736 }
2737
2738 @Override
2739 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002740 // The leash is parented to the animation layer. We need to preserve the z-order by using
2741 // the prefix order index, but we boost if necessary.
Robert Carrb9506032018-02-13 13:54:00 -08002742 int layer = 0;
2743 if (!inPinnedWindowingMode()) {
2744 layer = getPrefixOrderIndex();
2745 } else {
2746 // Pinned stacks have animations take place within themselves rather than an animation
2747 // layer so we need to preserve the order relative to the stack (e.g. the order of our
2748 // task/parent).
2749 layer = getParent().getPrefixOrderIndex();
2750 }
2751
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002752 if (mNeedsZBoost) {
2753 layer += Z_BOOST_BASE;
2754 }
Jorim Jaggi9cd99132019-04-24 17:41:35 +02002755 if (!mNeedsAnimationBoundsLayer) {
2756 leash.setLayer(layer);
2757 }
Robert Carr2f8aa392018-01-31 14:46:51 -08002758
2759 final DisplayContent dc = getDisplayContent();
Jorim Jaggibe418292018-03-26 16:14:12 +02002760 dc.assignStackOrdering();
Evan Rosky2289ba12018-11-19 18:28:18 -08002761
2762 if (leash == mTransitChangeLeash) {
2763 // This is a temporary state so skip any animation notifications
2764 return;
2765 } else if (mTransitChangeLeash != null) {
2766 // unparent mTransitChangeLeash for clean-up
Evan Rosky25b56192019-02-06 16:10:56 -08002767 clearChangeLeash(t, false /* cancel */);
Evan Rosky2289ba12018-11-19 18:28:18 -08002768 }
2769
Jorim Jaggi6de61012018-03-19 14:53:23 +01002770 if (mAnimatingAppWindowTokenRegistry != null) {
2771 mAnimatingAppWindowTokenRegistry.notifyStarting(this);
2772 }
Vishnu Naira2977262018-07-26 13:31:26 -07002773
2774 // If the animation needs to be cropped then an animation bounds layer is created as a child
2775 // of the pinned stack or animation layer. The leash is then reparented to this new layer.
2776 if (mNeedsAnimationBoundsLayer) {
Evan Rosky7735d352019-03-18 17:27:27 -07002777 mTmpRect.setEmpty();
2778 final Task task = getTask();
2779 if (getDisplayContent().mAppTransitionController.isTransitWithinTask(
2780 getTransit(), task)) {
2781 task.getBounds(mTmpRect);
2782 } else {
2783 final TaskStack stack = getStack();
2784 if (stack == null) {
2785 return;
2786 }
2787 // Set clip rect to stack bounds.
2788 stack.getBounds(mTmpRect);
Vishnu Naira2977262018-07-26 13:31:26 -07002789 }
2790 mAnimationBoundsLayer = createAnimationBoundsLayer(t);
2791
Vishnu Naira2977262018-07-26 13:31:26 -07002792 // Crop to stack bounds.
2793 t.setWindowCrop(mAnimationBoundsLayer, mTmpRect);
Jorim Jaggi9cd99132019-04-24 17:41:35 +02002794 t.setLayer(mAnimationBoundsLayer, layer);
Vishnu Naira2977262018-07-26 13:31:26 -07002795
2796 // Reparent leash to animation bounds layer.
Robert Carr10584fa2019-01-14 15:55:19 -08002797 t.reparent(leash, mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002798 }
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002799 }
2800
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002801 /**
2802 * This must be called while inside a transaction.
2803 */
2804 void showAllWindowsLocked() {
2805 forAllWindows(windowState -> {
2806 if (DEBUG_VISIBILITY) Slog.v(TAG, "performing show on: " + windowState);
2807 windowState.performShowLocked();
2808 }, false /* traverseTopToBottom */);
Jorim Jaggia5e10572017-11-15 14:36:26 +01002809 }
2810
2811 @Override
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002812 protected void onAnimationFinished() {
2813 super.onAnimationFinished();
2814
Ian8b2822e2019-05-14 11:59:02 -07002815 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#onAnimationFinished");
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002816 mTransit = TRANSIT_UNSET;
2817 mTransitFlags = 0;
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002818 mNeedsZBoost = false;
Vishnu Naira2977262018-07-26 13:31:26 -07002819 mNeedsAnimationBoundsLayer = false;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002820
2821 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER,
2822 "AppWindowToken");
2823
Jorim Jaggi988f6682017-11-17 17:46:43 +01002824 clearThumbnail();
Jorim Jaggi752cd822018-03-29 16:29:18 +02002825 setClientHidden(isHidden() && hiddenRequested);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002826
lumarkff0ab692018-11-05 20:32:30 +08002827 getDisplayContent().computeImeTargetIfNeeded(this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002828
2829 if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + this
2830 + ": reportedVisible=" + reportedVisible
2831 + " okToDisplay=" + okToDisplay()
2832 + " okToAnimate=" + okToAnimate()
2833 + " startingDisplayed=" + startingDisplayed);
2834
Evan Rosky2289ba12018-11-19 18:28:18 -08002835 // clean up thumbnail window
2836 if (mThumbnail != null) {
2837 mThumbnail.destroy();
2838 mThumbnail = null;
2839 }
2840
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002841 // WindowState.onExitAnimationDone might modify the children list, so make a copy and then
2842 // traverse the copy.
2843 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
2844 children.forEach(WindowState::onExitAnimationDone);
2845
lumark588a3e82018-07-20 18:53:54 +08002846 getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002847 scheduleAnimation();
Jorim Jaggi9b5e3312019-03-01 18:08:00 +01002848
2849 mActivityRecord.onAnimationFinished();
Ian8b2822e2019-05-14 11:59:02 -07002850 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002851 }
2852
2853 @Override
2854 boolean isAppAnimating() {
2855 return isSelfAnimating();
2856 }
2857
2858 @Override
2859 boolean isSelfAnimating() {
2860 // If we are about to start a transition, we also need to be considered animating.
2861 return isWaitingForTransitionStart() || isReallyAnimating();
2862 }
2863
2864 /**
2865 * @return True if and only if we are actually running an animation. Note that
2866 * {@link #isSelfAnimating} also returns true if we are waiting for an animation to
2867 * start.
2868 */
2869 private boolean isReallyAnimating() {
2870 return super.isSelfAnimating();
2871 }
2872
Evan Rosky25b56192019-02-06 16:10:56 -08002873 /**
2874 * @param cancel {@code true} if clearing the leash due to cancelling instead of transferring
2875 * to another leash.
2876 */
2877 private void clearChangeLeash(Transaction t, boolean cancel) {
2878 if (mTransitChangeLeash == null) {
2879 return;
2880 }
2881 if (cancel) {
2882 clearThumbnail();
2883 SurfaceControl sc = getSurfaceControl();
2884 SurfaceControl parentSc = getParentSurfaceControl();
2885 // Don't reparent if surface is getting destroyed
2886 if (parentSc != null && sc != null) {
2887 t.reparent(sc, getParentSurfaceControl());
2888 }
2889 }
2890 t.hide(mTransitChangeLeash);
Evan Rosky08e20932019-05-14 10:54:07 -07002891 t.remove(mTransitChangeLeash);
Evan Rosky25b56192019-02-06 16:10:56 -08002892 mTransitChangeLeash = null;
2893 if (cancel) {
lumarkf6f34942019-04-29 16:56:50 +08002894 onAnimationLeashLost(t);
Evan Rosky25b56192019-02-06 16:10:56 -08002895 }
2896 }
2897
Jorim Jaggi988f6682017-11-17 17:46:43 +01002898 @Override
2899 void cancelAnimation() {
Evan Rosky2289ba12018-11-19 18:28:18 -08002900 cancelAnimationOnly();
Jorim Jaggi988f6682017-11-17 17:46:43 +01002901 clearThumbnail();
Evan Rosky25b56192019-02-06 16:10:56 -08002902 clearChangeLeash(getPendingTransaction(), true /* cancel */);
Evan Rosky2289ba12018-11-19 18:28:18 -08002903 }
2904
2905 /**
2906 * This only cancels the animation. It doesn't do other teardown like cleaning-up thumbnail
2907 * or interim leashes.
2908 * <p>
2909 * Used when canceling in preparation for starting a new animation.
2910 */
2911 void cancelAnimationOnly() {
2912 super.cancelAnimation();
Jorim Jaggi988f6682017-11-17 17:46:43 +01002913 }
2914
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002915 boolean isWaitingForTransitionStart() {
lumark588a3e82018-07-20 18:53:54 +08002916 return getDisplayContent().mAppTransition.isTransitionSet()
2917 && (getDisplayContent().mOpeningApps.contains(this)
Evan Rosky2289ba12018-11-19 18:28:18 -08002918 || getDisplayContent().mClosingApps.contains(this)
2919 || getDisplayContent().mChangingApps.contains(this));
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002920 }
2921
2922 public int getTransit() {
2923 return mTransit;
2924 }
2925
2926 int getTransitFlags() {
2927 return mTransitFlags;
2928 }
2929
Jorim Jaggi988f6682017-11-17 17:46:43 +01002930 void attachThumbnailAnimation() {
2931 if (!isReallyAnimating()) {
2932 return;
2933 }
2934 final int taskId = getTask().mTaskId;
2935 final GraphicBuffer thumbnailHeader =
lumark588a3e82018-07-20 18:53:54 +08002936 getDisplayContent().mAppTransition.getAppTransitionThumbnailHeader(taskId);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002937 if (thumbnailHeader == null) {
2938 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG, "No thumbnail header bitmap for: " + taskId);
2939 return;
2940 }
2941 clearThumbnail();
2942 mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnailHeader);
2943 mThumbnail.startAnimation(getPendingTransaction(), loadThumbnailAnimation(thumbnailHeader));
2944 }
2945
Tony Mak64b8d562017-12-28 17:44:02 +00002946 /**
2947 * Attaches a surface with a thumbnail for the
2948 * {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation.
2949 */
2950 void attachCrossProfileAppsThumbnailAnimation() {
2951 if (!isReallyAnimating()) {
2952 return;
2953 }
2954 clearThumbnail();
2955
2956 final WindowState win = findMainWindow();
2957 if (win == null) {
2958 return;
2959 }
chaviw492139a2018-07-16 16:07:35 -07002960 final Rect frame = win.getFrameLw();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002961 final int thumbnailDrawableRes = getTask().mUserId == mWmService.mCurrentUserId
Tony Mak64b8d562017-12-28 17:44:02 +00002962 ? R.drawable.ic_account_circle
Tony Makda4af232018-04-27 11:01:10 +01002963 : R.drawable.ic_corp_badge;
Tony Mak64b8d562017-12-28 17:44:02 +00002964 final GraphicBuffer thumbnail =
lumark588a3e82018-07-20 18:53:54 +08002965 getDisplayContent().mAppTransition
Tony Mak64b8d562017-12-28 17:44:02 +00002966 .createCrossProfileAppsThumbnail(thumbnailDrawableRes, frame);
2967 if (thumbnail == null) {
2968 return;
2969 }
2970 mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnail);
2971 final Animation animation =
lumark588a3e82018-07-20 18:53:54 +08002972 getDisplayContent().mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(
chaviw492139a2018-07-16 16:07:35 -07002973 win.getFrameLw());
Tony Mak64b8d562017-12-28 17:44:02 +00002974 mThumbnail.startAnimation(getPendingTransaction(), animation, new Point(frame.left,
2975 frame.top));
2976 }
2977
Jorim Jaggi988f6682017-11-17 17:46:43 +01002978 private Animation loadThumbnailAnimation(GraphicBuffer thumbnailHeader) {
2979 final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
2980
2981 // If this is a multi-window scenario, we use the windows frame as
2982 // destination of the thumbnail header animation. If this is a full screen
2983 // window scenario, we use the whole display as the target.
2984 WindowState win = findMainWindow();
2985 Rect appRect = win != null ? win.getContentFrameLw() :
2986 new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
chaviw9c81e632018-07-31 11:17:52 -07002987 final Rect insets = win != null ? win.getContentInsets() : null;
Jorim Jaggi988f6682017-11-17 17:46:43 +01002988 final Configuration displayConfig = mDisplayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08002989 return getDisplayContent().mAppTransition.createThumbnailAspectScaleAnimationLocked(
Jorim Jaggi988f6682017-11-17 17:46:43 +01002990 appRect, insets, thumbnailHeader, getTask().mTaskId, displayConfig.uiMode,
2991 displayConfig.orientation);
2992 }
2993
2994 private void clearThumbnail() {
2995 if (mThumbnail == null) {
2996 return;
2997 }
2998 mThumbnail.destroy();
2999 mThumbnail = null;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003000 }
3001
Jorim Jaggif84e2f62018-01-16 14:17:59 +01003002 void registerRemoteAnimations(RemoteAnimationDefinition definition) {
3003 mRemoteAnimationDefinition = definition;
3004 }
3005
3006 RemoteAnimationDefinition getRemoteAnimationDefinition() {
3007 return mRemoteAnimationDefinition;
3008 }
3009
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003010 @Override
3011 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
3012 super.dump(pw, prefix, dumpAll);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003013 if (appToken != null) {
Wale Ogunwale72919d22016-12-08 18:58:50 -08003014 pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003015 }
Winson Chung48b25652018-10-22 14:04:30 -07003016 pw.println(prefix + "component=" + mActivityComponent.flattenToShortString());
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08003017 pw.print(prefix); pw.print("task="); pw.println(getTask());
Wale Ogunwale51362492016-09-08 17:49:17 -07003018 pw.print(prefix); pw.print(" mFillsParent="); pw.print(mFillsParent);
3019 pw.print(" mOrientation="); pw.println(mOrientation);
Wale Ogunwale89973222017-04-23 18:39:45 -07003020 pw.println(prefix + "hiddenRequested=" + hiddenRequested + " mClientHidden=" + mClientHidden
3021 + ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "")
3022 + " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible);
Craig Mautner59431632012-04-04 11:56:44 -07003023 if (paused) {
3024 pw.print(prefix); pw.print("paused="); pw.println(paused);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003025 }
Wale Ogunwale9017ec02016-02-25 08:55:25 -08003026 if (mAppStopped) {
3027 pw.print(prefix); pw.print("mAppStopped="); pw.println(mAppStopped);
3028 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07003029 if (mNumInterestingWindows != 0 || mNumDrawnWindows != 0
Jorim Jaggib0fc8172017-11-23 17:04:08 +00003030 || allDrawn || mLastAllDrawn) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07003031 pw.print(prefix); pw.print("mNumInterestingWindows=");
3032 pw.print(mNumInterestingWindows);
3033 pw.print(" mNumDrawnWindows="); pw.print(mNumDrawnWindows);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003034 pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
Craig Mautner6fbda632012-07-03 09:26:39 -07003035 pw.print(" allDrawn="); pw.print(allDrawn);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00003036 pw.print(" lastAllDrawn="); pw.print(mLastAllDrawn);
Craig Mautner6fbda632012-07-03 09:26:39 -07003037 pw.println(")");
3038 }
3039 if (inPendingTransaction) {
3040 pw.print(prefix); pw.print("inPendingTransaction=");
3041 pw.println(inPendingTransaction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003042 }
chaviwa8f07a72019-05-01 16:25:39 -07003043 if (mStartingData != null || removed || firstWindowDrawn || mIsExiting) {
3044 pw.print(prefix); pw.print("startingData="); pw.print(mStartingData);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003045 pw.print(" removed="); pw.print(removed);
Craig Mautner3d7ca312015-01-08 10:56:00 -08003046 pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
Craig Mautner799bc1d2015-01-14 10:33:48 -08003047 pw.print(" mIsExiting="); pw.println(mIsExiting);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003048 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08003049 if (startingWindow != null || startingSurface != null
Wale Ogunwale6c459212017-05-17 08:56:03 -07003050 || startingDisplayed || startingMoved || mHiddenSetFromTransferredStartingWindow) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003051 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08003052 pw.print(" startingSurface="); pw.print(startingSurface);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003053 pw.print(" startingDisplayed="); pw.print(startingDisplayed);
Wale Ogunwale6c459212017-05-17 08:56:03 -07003054 pw.print(" startingMoved="); pw.print(startingMoved);
3055 pw.println(" mHiddenSetFromTransferredStartingWindow="
3056 + mHiddenSetFromTransferredStartingWindow);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003057 }
Jorim Jaggi0429f352015-12-22 16:29:16 +01003058 if (!mFrozenBounds.isEmpty()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08003059 pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
Jorim Jaggi26c8c422016-05-09 19:57:25 -07003060 pw.print(prefix); pw.print("mFrozenMergedConfig="); pw.println(mFrozenMergedConfig);
Chong Zhangd78ddb42016-03-02 17:01:14 -08003061 }
3062 if (mPendingRelaunchCount != 0) {
3063 pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount);
Jorim Jaggi0429f352015-12-22 16:29:16 +01003064 }
Riddle Hsub398da32019-01-21 21:48:16 +08003065 if (mSizeCompatScale != 1f || mSizeCompatBounds != null) {
3066 pw.println(prefix + "mSizeCompatScale=" + mSizeCompatScale + " mSizeCompatBounds="
3067 + mSizeCompatBounds);
3068 }
Wale Ogunwalee287e192017-04-21 09:30:12 -07003069 if (mRemovingFromDisplay) {
3070 pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay);
3071 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003072 }
3073
3074 @Override
3075 void setHidden(boolean hidden) {
3076 super.setHidden(hidden);
3077 scheduleAnimation();
3078 }
3079
3080 @Override
3081 void prepareSurfaces() {
3082 // isSelfAnimating also returns true when we are about to start a transition, so we need
3083 // to check super here.
3084 final boolean reallyAnimating = super.isSelfAnimating();
3085 final boolean show = !isHidden() || reallyAnimating;
Robert Carrd8e4fb72019-01-31 11:14:30 -08003086
3087 if (mSurfaceControl != null) {
3088 if (show && !mLastSurfaceShowing) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003089 getPendingTransaction().show(mSurfaceControl);
Robert Carrd8e4fb72019-01-31 11:14:30 -08003090 } else if (!show && mLastSurfaceShowing) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003091 getPendingTransaction().hide(mSurfaceControl);
Robert Carrd8e4fb72019-01-31 11:14:30 -08003092 }
Jorim Jaggi4d1835d2017-08-31 17:28:27 +02003093 }
Jorim Jaggi988f6682017-11-17 17:46:43 +01003094 if (mThumbnail != null) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003095 mThumbnail.setShowing(getPendingTransaction(), show);
Jorim Jaggi988f6682017-11-17 17:46:43 +01003096 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003097 mLastSurfaceShowing = show;
3098 super.prepareSurfaces();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003099 }
3100
Jorim Jaggi77d0f36c2018-03-16 17:49:49 +01003101 /**
3102 * @return Whether our {@link #getSurfaceControl} is currently showing.
3103 */
3104 boolean isSurfaceShowing() {
3105 return mLastSurfaceShowing;
3106 }
3107
Jorim Jaggib0fc8172017-11-23 17:04:08 +00003108 boolean isFreezingScreen() {
3109 return mFreezingScreen;
3110 }
3111
3112 @Override
3113 boolean needsZBoost() {
3114 return mNeedsZBoost || super.needsZBoost();
3115 }
3116
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07003117 @CallSuper
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003118 @Override
Nataniel Borges023ecb52019-01-16 14:15:43 -08003119 public void writeToProto(ProtoOutputStream proto, long fieldId,
3120 @WindowTraceLogLevel int logLevel) {
3121 // Critical log level logs only visible elements to mitigate performance overheard
3122 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
3123 return;
3124 }
3125
Steven Timotiusaf03df62017-07-18 16:56:43 -07003126 final long token = proto.start(fieldId);
3127 writeNameToProto(proto, NAME);
Nataniel Borges023ecb52019-01-16 14:15:43 -08003128 super.writeToProto(proto, WINDOW_TOKEN, logLevel);
Vishnu Nair04ab4392018-01-10 11:00:06 -08003129 proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing);
3130 proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart());
3131 proto.write(IS_REALLY_ANIMATING, isReallyAnimating());
3132 if (mThumbnail != null){
3133 mThumbnail.writeToProto(proto, THUMBNAIL);
3134 }
3135 proto.write(FILLS_PARENT, mFillsParent);
3136 proto.write(APP_STOPPED, mAppStopped);
3137 proto.write(HIDDEN_REQUESTED, hiddenRequested);
3138 proto.write(CLIENT_HIDDEN, mClientHidden);
3139 proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient);
3140 proto.write(REPORTED_DRAWN, reportedDrawn);
3141 proto.write(REPORTED_VISIBLE, reportedVisible);
3142 proto.write(NUM_INTERESTING_WINDOWS, mNumInterestingWindows);
3143 proto.write(NUM_DRAWN_WINDOWS, mNumDrawnWindows);
3144 proto.write(ALL_DRAWN, allDrawn);
3145 proto.write(LAST_ALL_DRAWN, mLastAllDrawn);
3146 proto.write(REMOVED, removed);
Nataniel Borges023ecb52019-01-16 14:15:43 -08003147 if (startingWindow != null) {
Vishnu Nair04ab4392018-01-10 11:00:06 -08003148 startingWindow.writeIdentifierToProto(proto, STARTING_WINDOW);
3149 }
3150 proto.write(STARTING_DISPLAYED, startingDisplayed);
3151 proto.write(STARTING_MOVED, startingMoved);
3152 proto.write(HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW,
3153 mHiddenSetFromTransferredStartingWindow);
3154 for (Rect bounds : mFrozenBounds) {
3155 bounds.writeToProto(proto, FROZEN_BOUNDS);
3156 }
Steven Timotiusaf03df62017-07-18 16:56:43 -07003157 proto.end(token);
3158 }
3159
3160 void writeNameToProto(ProtoOutputStream proto, long fieldId) {
3161 if (appToken == null) {
3162 return;
3163 }
3164 try {
3165 proto.write(fieldId, appToken.getName());
3166 } catch (RemoteException e) {
3167 // This shouldn't happen, but in this case fall back to outputting nothing
3168 Slog.e(TAG, e.toString());
3169 }
3170 }
3171
3172 @Override
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003173 public String toString() {
3174 if (stringName == null) {
3175 StringBuilder sb = new StringBuilder();
3176 sb.append("AppWindowToken{");
3177 sb.append(Integer.toHexString(System.identityHashCode(this)));
3178 sb.append(" token="); sb.append(token); sb.append('}');
3179 stringName = sb.toString();
3180 }
Wale Ogunwaleba51ca22016-09-23 06:06:54 -07003181 return stringName + ((mIsExiting) ? " mIsExiting=" : "");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003182 }
Adrian Roos20e07892018-02-23 19:12:01 +01003183
3184 Rect getLetterboxInsets() {
3185 if (mLetterbox != null) {
3186 return mLetterbox.getInsets();
3187 } else {
3188 return new Rect();
3189 }
3190 }
Adrian Roos23df3a32018-03-15 15:41:13 +01003191
Riddle Hsu69de5fb2019-02-23 01:19:50 +08003192 /** Gets the inner bounds of letterbox. The bounds will be empty if there is no letterbox. */
3193 void getLetterboxInnerBounds(Rect outBounds) {
3194 if (mLetterbox != null) {
3195 outBounds.set(mLetterbox.getInnerFrame());
3196 } else {
3197 outBounds.setEmpty();
3198 }
3199 }
3200
Adrian Roos23df3a32018-03-15 15:41:13 +01003201 /**
Riddle Hsu69de5fb2019-02-23 01:19:50 +08003202 * @return {@code true} if there is a letterbox and any part of that letterbox overlaps with
Adrian Roos23df3a32018-03-15 15:41:13 +01003203 * the given {@code rect}.
3204 */
3205 boolean isLetterboxOverlappingWith(Rect rect) {
3206 return mLetterbox != null && mLetterbox.isOverlappingWith(rect);
3207 }
chaviw4ad54912018-05-30 11:05:44 -07003208
3209 /**
3210 * Sets if this AWT is in the process of closing or entering PIP.
3211 * {@link #mWillCloseOrEnterPip}}
3212 */
3213 void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
3214 mWillCloseOrEnterPip = willCloseOrEnterPip;
3215 }
3216
3217 /**
3218 * Returns whether this AWT is considered closing. Conditions are either
3219 * 1. Is this app animating and was requested to be hidden
3220 * 2. App is delayed closing since it might enter PIP.
3221 */
3222 boolean isClosingOrEnteringPip() {
3223 return (isAnimating() && hiddenRequested) || mWillCloseOrEnterPip;
3224 }
Jorim Jaggiaf0d6d22018-06-08 15:25:35 +02003225
3226 /**
3227 * @return Whether we are allowed to show non-starting windows at the moment. We disallow
3228 * showing windows during transitions in case we have windows that have wide-color-gamut
3229 * color mode set to avoid jank in the middle of the transition.
3230 */
3231 boolean canShowWindows() {
3232 return allDrawn && !(isReallyAnimating() && hasNonDefaultColorWindow());
3233 }
3234
3235 /**
3236 * @return true if we have a window that has a non-default color mode set; false otherwise.
3237 */
3238 private boolean hasNonDefaultColorWindow() {
3239 return forAllWindows(ws -> ws.mAttrs.getColorMode() != COLOR_MODE_DEFAULT,
3240 true /* topToBottom */);
3241 }
lumark588a3e82018-07-20 18:53:54 +08003242
chaviwdcf76ec2019-01-11 16:48:46 -08003243 private void updateColorTransform() {
3244 if (mSurfaceControl != null && mLastAppSaturationInfo != null) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003245 getPendingTransaction().setColorTransform(mSurfaceControl,
3246 mLastAppSaturationInfo.mMatrix, mLastAppSaturationInfo.mTranslation);
chaviwdcf76ec2019-01-11 16:48:46 -08003247 mWmService.scheduleAnimationLocked();
3248 }
3249 }
3250
3251 private static class AppSaturationInfo {
3252 float[] mMatrix = new float[9];
3253 float[] mTranslation = new float[3];
3254
3255 void setSaturation(@Size(9) float[] matrix, @Size(3) float[] translation) {
3256 System.arraycopy(matrix, 0, mMatrix, 0, mMatrix.length);
3257 System.arraycopy(translation, 0, mTranslation, 0, mTranslation.length);
3258 }
3259 }
Jeff Browne9bdb312012-04-05 15:30:10 -07003260}