blob: f5592e057df6b23f3012bf66afed89cab3fcf2f8 [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 Ogunwale72919d22016-12-08 18:58:50 -080024import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
25import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -070026import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
Wale Ogunwale51362492016-09-08 17:49:17 -070027import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
Jorim Jaggif5f9e122017-10-24 18:21:09 +020028import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
Jorim Jaggife762342016-10-13 14:33:27 +020029import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
Jorim Jaggid635a4a2017-05-03 15:21:26 +020030import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080031import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
Jorim Jaggife762342016-10-13 14:33:27 +020032import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
Wale Ogunwaled1c37912016-08-16 03:19:39 -070033import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080034import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -070035import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080036import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
Evan Rosky2289ba12018-11-19 18:28:18 -080037import static android.view.WindowManager.TRANSIT_TASK_CHANGE_WINDOWING_MODE;
chaviw9c81e632018-07-31 11:17:52 -070038import static android.view.WindowManager.TRANSIT_UNSET;
Jorim Jaggic6976f02018-04-18 16:31:07 +020039import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
chaviw9c81e632018-07-31 11:17:52 -070040
Adrian Roose99bc052017-11-20 17:55:31 +010041import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
42import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070043import static com.android.server.wm.AppWindowTokenProto.ALL_DRAWN;
44import static com.android.server.wm.AppWindowTokenProto.APP_STOPPED;
45import static com.android.server.wm.AppWindowTokenProto.CLIENT_HIDDEN;
46import static com.android.server.wm.AppWindowTokenProto.DEFER_HIDING_CLIENT;
47import static com.android.server.wm.AppWindowTokenProto.FILLS_PARENT;
48import static com.android.server.wm.AppWindowTokenProto.FROZEN_BOUNDS;
49import static com.android.server.wm.AppWindowTokenProto.HIDDEN_REQUESTED;
50import static com.android.server.wm.AppWindowTokenProto.HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW;
51import static com.android.server.wm.AppWindowTokenProto.IS_REALLY_ANIMATING;
52import static com.android.server.wm.AppWindowTokenProto.IS_WAITING_FOR_TRANSITION_START;
53import static com.android.server.wm.AppWindowTokenProto.LAST_ALL_DRAWN;
54import static com.android.server.wm.AppWindowTokenProto.LAST_SURFACE_SHOWING;
55import static com.android.server.wm.AppWindowTokenProto.NAME;
56import static com.android.server.wm.AppWindowTokenProto.NUM_DRAWN_WINDOWS;
57import static com.android.server.wm.AppWindowTokenProto.NUM_INTERESTING_WINDOWS;
58import static com.android.server.wm.AppWindowTokenProto.REMOVED;
59import static com.android.server.wm.AppWindowTokenProto.REPORTED_DRAWN;
60import static com.android.server.wm.AppWindowTokenProto.REPORTED_VISIBLE;
61import static com.android.server.wm.AppWindowTokenProto.STARTING_DISPLAYED;
62import static com.android.server.wm.AppWindowTokenProto.STARTING_MOVED;
63import static com.android.server.wm.AppWindowTokenProto.STARTING_WINDOW;
64import static com.android.server.wm.AppWindowTokenProto.THUMBNAIL;
65import static com.android.server.wm.AppWindowTokenProto.WINDOW_TOKEN;
chaviw9c81e632018-07-31 11:17:52 -070066import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
67import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
68import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
69import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
70import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
71import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
72import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
73import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
74import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
75import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
76import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
77import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
78import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
79import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN;
80import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
81import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
82import static com.android.server.wm.WindowManagerService.logWithStack;
Vishnu Naira2977262018-07-26 13:31:26 -070083import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080084
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070085import android.annotation.CallSuper;
chaviwdcf76ec2019-01-11 16:48:46 -080086import android.annotation.Size;
Jorim Jaggid635a4a2017-05-03 15:21:26 +020087import android.app.Activity;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080088import android.app.ActivityManager;
Winson Chung48b25652018-10-22 14:04:30 -070089import android.content.ComponentName;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080090import android.content.res.CompatibilityInfo;
Jorim Jaggi26c8c422016-05-09 19:57:25 -070091import android.content.res.Configuration;
Jorim Jaggi988f6682017-11-17 17:46:43 +010092import android.graphics.GraphicBuffer;
Jorim Jaggif5f9e122017-10-24 18:21:09 +020093import android.graphics.Point;
Jorim Jaggi0429f352015-12-22 16:29:16 +010094import android.graphics.Rect;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -070095import android.os.Binder;
Tiger Huang51c5a1d2018-12-11 20:24:51 +080096import android.os.Build;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -080097import android.os.Debug;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -070098import android.os.IBinder;
Steven Timotiusaf03df62017-07-18 16:56:43 -070099import android.os.RemoteException;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800100import android.os.SystemClock;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200101import android.os.Trace;
Evan Rosky2289ba12018-11-19 18:28:18 -0800102import android.util.ArraySet;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800103import android.util.Slog;
Steven Timotiusaf03df62017-07-18 16:56:43 -0700104import android.util.proto.ProtoOutputStream;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200105import android.view.DisplayInfo;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800106import android.view.IApplicationToken;
Robert Carr788f5742018-07-30 17:46:45 -0700107import android.view.InputApplicationHandle;
Evan Rosky966759f2019-01-15 10:33:58 -0800108import android.view.RemoteAnimationAdapter;
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100109import android.view.RemoteAnimationDefinition;
Robert Carr6914f082017-03-20 19:04:30 -0700110import android.view.SurfaceControl;
Tony Mak64b8d562017-12-28 17:44:02 +0000111import android.view.SurfaceControl.Transaction;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800112import android.view.WindowManager;
Jorim Jaggi87fdbcb2017-08-17 13:41:11 +0200113import android.view.WindowManager.LayoutParams;
Tony Mak64b8d562017-12-28 17:44:02 +0000114import android.view.animation.Animation;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800115
Tony Mak64b8d562017-12-28 17:44:02 +0000116import com.android.internal.R;
Riddle Hsua118b3a2018-10-11 22:05:06 +0800117import com.android.internal.annotations.VisibleForTesting;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800118import com.android.internal.util.ToBooleanFunction;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800119import com.android.server.AttributeCache;
chaviwdcf76ec2019-01-11 16:48:46 -0800120import com.android.server.LocalServices;
121import com.android.server.display.ColorDisplayService;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800122import com.android.server.policy.WindowManagerPolicy;
Adrian Roose99bc052017-11-20 17:55:31 +0100123import com.android.server.policy.WindowManagerPolicy.StartingSurface;
Evan Rosky2289ba12018-11-19 18:28:18 -0800124import com.android.server.wm.RemoteAnimationController.RemoteAnimationRecord;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800125import com.android.server.wm.WindowManagerService.H;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800126
127import java.io.PrintWriter;
chaviwdcf76ec2019-01-11 16:48:46 -0800128import java.lang.ref.WeakReference;
Jorim Jaggi0429f352015-12-22 16:29:16 +0100129import java.util.ArrayDeque;
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800130import java.util.ArrayList;
lumark588a3e82018-07-20 18:53:54 +0800131import java.util.function.Consumer;
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800132
133class AppTokenList extends ArrayList<AppWindowToken> {
134}
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800135
136/**
137 * Version of WindowToken that is specifically for a particular application (or
138 * really activity) that is displaying windows.
139 */
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800140class AppWindowToken extends WindowToken implements WindowManagerService.AppFreezeListener,
141 ConfigurationContainerListener {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800142 private static final String TAG = TAG_WITH_CLASS_NAME ? "AppWindowToken" : TAG_WM;
143
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100144 /**
145 * Value to increment the z-layer when boosting a layer during animations. BOOST in l33tsp34k.
146 */
147 private static final int Z_BOOST_BASE = 800570000;
148
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800149 // Non-null only for application tokens.
150 final IApplicationToken appToken;
Winson Chung48b25652018-10-22 14:04:30 -0700151 final ComponentName mActivityComponent;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800152 final boolean mVoiceInteraction;
Dianne Hackborne30e02f2014-05-27 18:24:45 -0700153
Wale Ogunwale51362492016-09-08 17:49:17 -0700154 /** @see WindowContainer#fillsParent() */
155 private boolean mFillsParent;
Craig Mautner4c5eb222013-11-18 12:59:05 -0800156 boolean layoutConfigChanges;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800157 boolean mShowForAllUsers;
158 int mTargetSdk;
Craig Mautnera2c77052012-03-26 12:14:43 -0700159
Bryce Lee6d410262017-02-28 15:30:17 -0800160 // Flag set while reparenting to prevent actions normally triggered by an individual parent
161 // change.
162 private boolean mReparenting;
163
Wale Ogunwalee287e192017-04-21 09:30:12 -0700164 // True if we are current in the process of removing this app token from the display
165 private boolean mRemovingFromDisplay = false;
166
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800167 // The input dispatching timeout for this application token in nanoseconds.
Wale Ogunwale72919d22016-12-08 18:58:50 -0800168 long mInputDispatchingTimeoutNanos;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800169
170 // These are used for determining when all windows associated with
171 // an activity have been drawn, so they can be made visible together
172 // at the same time.
Craig Mautner764983d2012-03-22 11:37:36 -0700173 // initialize so that it doesn't match mTransactionSequence which is an int.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700174 private long mLastTransactionSequence = Long.MIN_VALUE;
175 private int mNumInterestingWindows;
176 private int mNumDrawnWindows;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800177 boolean inPendingTransaction;
178 boolean allDrawn;
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000179 private boolean mLastAllDrawn;
180
Craig Mautner7636dfb2012-11-16 15:24:11 -0800181 // Set to true when this app creates a surface while in the middle of an animation. In that
182 // case do not clear allDrawn until the animation completes.
183 boolean deferClearAllDrawn;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800184
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800185 // Is this window's surface needed? This is almost like hidden, except
186 // it will sometimes be true a little earlier: when the token has
187 // been shown, but is still waiting for its app transition to execute
188 // before making its windows shown.
189 boolean hiddenRequested;
190
191 // Have we told the window clients to hide themselves?
Wale Ogunwale89973222017-04-23 18:39:45 -0700192 private boolean mClientHidden;
193
194 // If true we will defer setting mClientHidden to true and reporting to the client that it is
195 // hidden.
196 boolean mDeferHidingClient;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800197
198 // Last visibility state we reported to the app token.
199 boolean reportedVisible;
200
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700201 // Last drawn state we reported to the app token.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700202 private boolean reportedDrawn;
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700203
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800204 // Set to true when the token has been removed from the window mgr.
205 boolean removed;
206
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800207 // Information about an application starting window if displayed.
208 StartingData startingData;
209 WindowState startingWindow;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800210 StartingSurface startingSurface;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800211 boolean startingDisplayed;
212 boolean startingMoved;
Jorim Jaggi60f9c972018-02-01 19:21:07 +0100213
Wale Ogunwale6c459212017-05-17 08:56:03 -0700214 // True if the hidden state of this token was forced to false due to a transferred starting
215 // window.
216 private boolean mHiddenSetFromTransferredStartingWindow;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800217 boolean firstWindowDrawn;
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700218 private final WindowState.UpdateReportedVisibilityResults mReportedVisibilityResults =
219 new WindowState.UpdateReportedVisibilityResults();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800220
221 // Input application handle used by the input dispatcher.
Jeff Brown9302c872011-07-13 22:51:29 -0700222 final InputApplicationHandle mInputApplicationHandle;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800223
Wale Ogunwale571771c2016-08-26 13:18:50 -0700224 // TODO: Have a WindowContainer state for tracking exiting/deferred removal.
Craig Mautner799bc1d2015-01-14 10:33:48 -0800225 boolean mIsExiting;
Craig Mautner9ef471f2014-02-07 13:11:47 -0800226
Craig Mautnerbb742462014-07-07 15:28:55 -0700227 boolean mLaunchTaskBehind;
Craig Mautner8746a472014-07-24 15:12:54 -0700228 boolean mEnteringAnimation;
Craig Mautnerbb742462014-07-07 15:28:55 -0700229
Wale Ogunwale72919d22016-12-08 18:58:50 -0800230 private boolean mAlwaysFocusable;
Wale Ogunwale6cae7652015-12-26 07:36:26 -0800231
Robert Carre12aece2016-02-02 22:43:27 -0800232 boolean mAppStopped;
Robert Carrfd10cd12016-06-29 16:41:50 -0700233 int mRotationAnimationHint;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700234 private int mPendingRelaunchCount;
Robert Carre12aece2016-02-02 22:43:27 -0800235
Jorim Jaggife762342016-10-13 14:33:27 +0200236 private boolean mLastContainsShowWhenLockedWindow;
237 private boolean mLastContainsDismissKeyguardWindow;
238
Jorim Jaggi0429f352015-12-22 16:29:16 +0100239 ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
Jorim Jaggi26c8c422016-05-09 19:57:25 -0700240 ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
Jorim Jaggi0429f352015-12-22 16:29:16 +0100241
Riddle Hsub398da32019-01-21 21:48:16 +0800242 /**
243 * The scale to fit at least one side of the activity to its parent. If the activity uses
244 * 1920x1080, and the actually size on the screen is 960x540, then the scale is 0.5.
245 */
246 private float mSizeCompatScale = 1f;
247 /**
248 * The bounds in global coordinates for activity in size compatibility mode.
249 * @see ActivityRecord#inSizeCompatMode
250 */
251 private Rect mSizeCompatBounds;
252
Wale Ogunwale6c459212017-05-17 08:56:03 -0700253 private boolean mDisablePreviewScreenshots;
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +0100254
Wale Ogunwale034a8ec2017-09-02 17:14:40 -0700255 private Task mLastParent;
Robert Carred3e83b2017-04-21 13:26:55 -0700256
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800257 // TODO: Remove after unification
258 ActivityRecord mActivityRecord;
259
chaviwd3bf08d2017-08-01 17:24:59 -0700260 /**
261 * See {@link #canTurnScreenOn()}
262 */
263 private boolean mCanTurnScreenOn = true;
264
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200265 /**
266 * If we are running an animation, this determines the transition type. Must be one of
267 * AppTransition.TRANSIT_* constants.
268 */
269 private int mTransit;
270
271 /**
272 * If we are running an animation, this determines the flags during this animation. Must be a
273 * bitwise combination of AppTransition.TRANSIT_FLAG_* constants.
274 */
275 private int mTransitFlags;
276
277 /** Whether our surface was set to be showing in the last call to {@link #prepareSurfaces} */
Jorim Jaggifd1891462017-12-29 15:41:36 +0100278 private boolean mLastSurfaceShowing = true;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200279
Evan Rosky2289ba12018-11-19 18:28:18 -0800280 /**
281 * This gets used during some open/close transitions as well as during a change transition
282 * where it represents the starting-state snapshot.
283 */
Jorim Jaggi988f6682017-11-17 17:46:43 +0100284 private AppWindowThumbnail mThumbnail;
Evan Rosky2289ba12018-11-19 18:28:18 -0800285 private final Rect mTransitStartRect = new Rect();
286
287 /**
288 * This leash is used to "freeze" the app surface in place after the state change, but before
289 * the animation is ready to start.
290 */
291 private SurfaceControl mTransitChangeLeash = null;
Jorim Jaggi988f6682017-11-17 17:46:43 +0100292
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000293 /** Have we been asked to have this token keep the screen frozen? */
294 private boolean mFreezingScreen;
295
296 /** Whether this token should be boosted at the top of all app window tokens. */
297 private boolean mNeedsZBoost;
Adrian Roos4d18a2e2017-12-19 19:08:05 +0100298 private Letterbox mLetterbox;
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000299
chaviw23ee71c2017-12-18 11:29:41 -0800300 private final Point mTmpPoint = new Point();
chaviw23012112017-12-20 15:29:04 -0800301 private final Rect mTmpRect = new Rect();
Evan Rosky2289ba12018-11-19 18:28:18 -0800302 private final Rect mTmpPrevBounds = new Rect();
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100303 private RemoteAnimationDefinition mRemoteAnimationDefinition;
Jorim Jaggi6de61012018-03-19 14:53:23 +0100304 private AnimatingAppWindowTokenRegistry mAnimatingAppWindowTokenRegistry;
chaviw23ee71c2017-12-18 11:29:41 -0800305
chaviw4ad54912018-05-30 11:05:44 -0700306 /**
307 * A flag to determine if this AWT is in the process of closing or entering PIP. This is needed
308 * to help AWT know that the app is in the process of closing but hasn't yet started closing on
309 * the WM side.
310 */
311 private boolean mWillCloseOrEnterPip;
312
Vishnu Naira2977262018-07-26 13:31:26 -0700313 /** Layer used to constrain the animation to a token's stack bounds. */
314 SurfaceControl mAnimationBoundsLayer;
315
316 /** Whether this token needs to create mAnimationBoundsLayer for cropping animations. */
317 boolean mNeedsAnimationBoundsLayer;
318
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800319 private static final int STARTING_WINDOW_TYPE_NONE = 0;
320 private static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
321 private static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
322
chaviwdcf76ec2019-01-11 16:48:46 -0800323 private AppSaturationInfo mLastAppSaturationInfo;
324
325 private final ColorDisplayService.ColorTransformController mColorTransformController =
326 (matrix, translation) -> mWmService.mH.post(() -> {
327 synchronized (mWmService.mGlobalLock) {
328 if (mLastAppSaturationInfo == null) {
329 mLastAppSaturationInfo = new AppSaturationInfo();
330 }
331
332 mLastAppSaturationInfo.setSaturation(matrix, translation);
333 updateColorTransform();
334 }
335 });
336
Winson Chung48b25652018-10-22 14:04:30 -0700337 AppWindowToken(WindowManagerService service, IApplicationToken token,
338 ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
339 long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers,
340 int targetSdk, int orientation, int rotationAnimationHint, int configChanges,
341 boolean launchTaskBehind, boolean alwaysFocusable,
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800342 ActivityRecord activityRecord) {
Winson Chung48b25652018-10-22 14:04:30 -0700343 this(service, token, activityComponent, voiceInteraction, dc, fullscreen);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800344 // TODO: remove after unification
345 mActivityRecord = activityRecord;
346 mActivityRecord.registerConfigurationChangeListener(this);
Wale Ogunwale72919d22016-12-08 18:58:50 -0800347 mInputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800348 mShowForAllUsers = showForAllUsers;
349 mTargetSdk = targetSdk;
350 mOrientation = orientation;
351 layoutConfigChanges = (configChanges & (CONFIG_SCREEN_SIZE | CONFIG_ORIENTATION)) != 0;
352 mLaunchTaskBehind = launchTaskBehind;
353 mAlwaysFocusable = alwaysFocusable;
354 mRotationAnimationHint = rotationAnimationHint;
355
356 // Application tokens start out hidden.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200357 setHidden(true);
Wale Ogunwale72919d22016-12-08 18:58:50 -0800358 hiddenRequested = true;
chaviwdcf76ec2019-01-11 16:48:46 -0800359
360 ColorDisplayService.ColorDisplayServiceInternal cds = LocalServices.getService(
361 ColorDisplayService.ColorDisplayServiceInternal.class);
362 cds.attachColorTransformController(activityRecord.packageName, activityRecord.mUserId,
363 new WeakReference<>(mColorTransformController));
Wale Ogunwale72919d22016-12-08 18:58:50 -0800364 }
365
Winson Chung48b25652018-10-22 14:04:30 -0700366 AppWindowToken(WindowManagerService service, IApplicationToken token,
367 ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
368 boolean fillsParent) {
Wale Ogunwale5cd907d2017-01-26 14:14:08 -0800369 super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true, dc,
370 false /* ownerCanManageAppTokens */);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700371 appToken = token;
Winson Chung48b25652018-10-22 14:04:30 -0700372 mActivityComponent = activityComponent;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800373 mVoiceInteraction = voiceInteraction;
Wale Ogunwale17f175c2017-02-07 16:54:10 -0800374 mFillsParent = fillsParent;
Robert Carr0bcbe642018-10-11 19:07:43 -0700375 mInputApplicationHandle = new InputApplicationHandle(appToken.asBinder());
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800376 }
377
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800378 void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
379 firstWindowDrawn = true;
380
381 // We now have a good window to show, remove dead placeholders
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700382 removeDeadWindows();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800383
Jorim Jaggi02886a82016-12-06 09:10:06 -0800384 if (startingWindow != null) {
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800385 if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Slog.v(TAG, "Finish starting "
386 + win.mToken + ": first real window is shown, no animation");
387 // If this initial window is animating, stop it -- we will do an animation to reveal
388 // it from behind the starting window, so there is no need for it to also be doing its
389 // own stuff.
Jorim Jaggia5e10572017-11-15 14:36:26 +0100390 win.cancelAnimation();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800391 removeStartingWindow();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800392 }
393 updateReportedVisibilityLocked();
394 }
395
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800396 void updateReportedVisibilityLocked() {
397 if (appToken == null) {
398 return;
399 }
400
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700401 if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700402 final int count = mChildren.size();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800403
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700404 mReportedVisibilityResults.reset();
405
406 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700407 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700408 win.updateReportedVisibility(mReportedVisibilityResults);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800409 }
410
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700411 int numInteresting = mReportedVisibilityResults.numInteresting;
412 int numVisible = mReportedVisibilityResults.numVisible;
413 int numDrawn = mReportedVisibilityResults.numDrawn;
414 boolean nowGone = mReportedVisibilityResults.nowGone;
415
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700416 boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200417 boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting && !isHidden();
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700418 if (!nowGone) {
419 // If the app is not yet gone, then it can only become visible/drawn.
420 if (!nowDrawn) {
421 nowDrawn = reportedDrawn;
422 }
423 if (!nowVisible) {
424 nowVisible = reportedVisible;
425 }
426 }
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800427 if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800428 + numInteresting + " visible=" + numVisible);
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700429 if (nowDrawn != reportedDrawn) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800430 if (mActivityRecord != null) {
431 mActivityRecord.onWindowsDrawn(nowDrawn, SystemClock.uptimeMillis());
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700432 }
433 reportedDrawn = nowDrawn;
434 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800435 if (nowVisible != reportedVisible) {
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700436 if (DEBUG_VISIBILITY) Slog.v(TAG,
437 "Visibility changed in " + this + ": vis=" + nowVisible);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800438 reportedVisible = nowVisible;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800439 if (mActivityRecord != null) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800440 if (nowVisible) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800441 onWindowsVisible();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800442 } else {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800443 onWindowsGone();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800444 }
445 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800446 }
447 }
448
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800449 private void onWindowsGone() {
450 if (mActivityRecord == null) {
451 return;
452 }
453 if (DEBUG_VISIBILITY) {
454 Slog.v(TAG_WM, "Reporting gone in " + mActivityRecord.appToken);
455 }
456 mActivityRecord.onWindowsGone();
457 }
458
459 private void onWindowsVisible() {
460 if (mActivityRecord == null) {
461 return;
462 }
463 if (DEBUG_VISIBILITY) {
464 Slog.v(TAG_WM, "Reporting visible in " + mActivityRecord.appToken);
465 }
466 mActivityRecord.onWindowsVisible();
467 }
468
Wale Ogunwale89973222017-04-23 18:39:45 -0700469 boolean isClientHidden() {
470 return mClientHidden;
471 }
472
473 void setClientHidden(boolean hideClient) {
474 if (mClientHidden == hideClient || (hideClient && mDeferHidingClient)) {
475 return;
476 }
Jorim Jaggi067b5bf2018-02-23 17:42:39 +0100477 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "setClientHidden: " + this
478 + " clientHidden=" + hideClient + " Callers=" + Debug.getCallers(5));
Wale Ogunwale89973222017-04-23 18:39:45 -0700479 mClientHidden = hideClient;
480 sendAppVisibilityToClients();
481 }
482
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800483 void setVisibility(boolean visible, boolean deferHidingClient) {
484 final AppTransition appTransition = getDisplayContent().mAppTransition;
485
486 // Don't set visibility to false if we were already not visible. This prevents WM from
487 // adding the app to the closing app list which doesn't make sense for something that is
488 // already not visible. However, set visibility to true even if we are already visible.
489 // This makes sure the app is added to the opening apps list so that the right
490 // transition can be selected.
491 // TODO: Probably a good idea to separate the concept of opening/closing apps from the
492 // concept of setting visibility...
493 if (!visible && hiddenRequested) {
494
495 if (!deferHidingClient && mDeferHidingClient) {
496 // We previously deferred telling the client to hide itself when visibility was
497 // initially set to false. Now we would like it to hide, so go ahead and set it.
498 mDeferHidingClient = deferHidingClient;
499 setClientHidden(true);
500 }
501 return;
502 }
503
504 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) {
505 Slog.v(TAG_WM, "setAppVisibility("
506 + appToken + ", visible=" + visible + "): " + appTransition
507 + " hidden=" + isHidden() + " hiddenRequested="
508 + hiddenRequested + " Callers=" + Debug.getCallers(6));
509 }
510
511 final DisplayContent displayContent = getDisplayContent();
512 displayContent.mOpeningApps.remove(this);
513 displayContent.mClosingApps.remove(this);
514 waitingToShow = false;
515 hiddenRequested = !visible;
516 mDeferHidingClient = deferHidingClient;
517
518 if (!visible) {
519 // If the app is dead while it was visible, we kept its dead window on screen.
520 // Now that the app is going invisible, we can remove it. It will be restarted
521 // if made visible again.
522 removeDeadWindows();
523 } else {
524 if (!appTransition.isTransitionSet()
525 && appTransition.isReady()) {
526 // Add the app mOpeningApps if transition is unset but ready. This means
527 // we're doing a screen freeze, and the unfreeze will wait for all opening
528 // apps to be ready.
529 displayContent.mOpeningApps.add(this);
530 }
531 startingMoved = false;
532 // If the token is currently hidden (should be the common case), or has been
533 // stopped, then we need to set up to wait for its windows to be ready.
534 if (isHidden() || mAppStopped) {
535 clearAllDrawn();
536
537 // If the app was already visible, don't reset the waitingToShow state.
538 if (isHidden()) {
539 waitingToShow = true;
540 }
541 }
542
543 // In the case where we are making an app visible but holding off for a transition,
544 // we still need to tell the client to make its windows visible so they get drawn.
545 // Otherwise, we will wait on performing the transition until all windows have been
546 // drawn, they never will be, and we are sad.
547 setClientHidden(false);
548
549 requestUpdateWallpaperIfNeeded();
550
551 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "No longer Stopped: " + this);
552 mAppStopped = false;
553
554 transferStartingWindowFromHiddenAboveTokenIfNeeded();
555 }
556
557 // If we are preparing an app transition, then delay changing
558 // the visibility of this token until we execute that transition.
559 if (okToAnimate() && appTransition.isTransitionSet()) {
560 inPendingTransaction = true;
561 if (visible) {
562 displayContent.mOpeningApps.add(this);
563 mEnteringAnimation = true;
564 } else {
565 displayContent.mClosingApps.add(this);
566 mEnteringAnimation = false;
567 }
568 if (appTransition.getAppTransition()
569 == WindowManager.TRANSIT_TASK_OPEN_BEHIND) {
570 // We're launchingBehind, add the launching activity to mOpeningApps.
571 final WindowState win = getDisplayContent().findFocusedWindow();
572 if (win != null) {
573 final AppWindowToken focusedToken = win.mAppToken;
574 if (focusedToken != null) {
575 if (DEBUG_APP_TRANSITIONS) {
576 Slog.d(TAG_WM, "TRANSIT_TASK_OPEN_BEHIND, "
577 + " adding " + focusedToken + " to mOpeningApps");
578 }
579 // Force animation to be loaded.
580 focusedToken.setHidden(true);
581 displayContent.mOpeningApps.add(focusedToken);
582 }
583 }
584 }
585 return;
586 }
587
588 commitVisibility(null, visible, TRANSIT_UNSET, true, mVoiceInteraction);
589 updateReportedVisibilityLocked();
590 }
591
592 boolean commitVisibility(WindowManager.LayoutParams lp,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700593 boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
594
595 boolean delayed = false;
596 inPendingTransaction = false;
Wale Ogunwale9e4721f2017-05-23 19:37:30 -0700597 // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually
598 // been set by the app now.
599 mHiddenSetFromTransferredStartingWindow = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700600
601 // Allow for state changes and animation to be applied if:
602 // * token is transitioning visibility state
603 // * or the token was marked as hidden and is exiting before we had a chance to play the
604 // transition animation
605 // * or this is an opening app and windows are being replaced.
606 boolean visibilityChanged = false;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200607 if (isHidden() == visible || (isHidden() && mIsExiting) || (visible && waitingForReplacement())) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800608 final AccessibilityController accessibilityController =
609 mWmService.mAccessibilityController;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700610 boolean changed = false;
611 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM,
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200612 "Changing app " + this + " hidden=" + isHidden() + " performLayout=" + performLayout);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700613
614 boolean runningAppAnimation = false;
615
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100616 if (transit != WindowManager.TRANSIT_UNSET) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200617 if (applyAnimationLocked(lp, transit, visible, isVoiceInteraction)) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700618 delayed = runningAppAnimation = true;
619 }
620 final WindowState window = findMainWindow();
Rhed Jao02655dc2018-10-30 20:44:52 +0800621 if (window != null && accessibilityController != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700622 accessibilityController.onAppWindowTransitionLocked(window, transit);
623 }
624 changed = true;
625 }
626
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700627 final int windowsCount = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700628 for (int i = 0; i < windowsCount; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700629 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700630 changed |= win.onAppVisibilityChanged(visible, runningAppAnimation);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700631 }
632
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200633 setHidden(!visible);
634 hiddenRequested = !visible;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700635 visibilityChanged = true;
636 if (!visible) {
637 stopFreezingScreen(true, true);
638 } else {
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700639 // If we are being set visible, and the starting window is not yet displayed,
640 // then make sure it doesn't get displayed.
641 if (startingWindow != null && !startingWindow.isDrawnLw()) {
642 startingWindow.mPolicyVisibility = false;
643 startingWindow.mPolicyVisibilityAfterAnim = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700644 }
Jorim Jaggi38d44ec2017-06-14 16:04:59 -0700645
646 // We are becoming visible, so better freeze the screen with the windows that are
647 // getting visible so we also wait for them.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800648 forAllWindows(mWmService::makeWindowFreezingScreenIfNeededLocked, true);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700649 }
650
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800651 if (DEBUG_APP_TRANSITIONS) {
652 Slog.v(TAG_WM, "commitVisibility: " + this
653 + ": hidden=" + isHidden() + " hiddenRequested=" + hiddenRequested);
654 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700655
656 if (changed) {
Arthur Hung95b38a92018-07-20 18:56:12 +0800657 getDisplayContent().getInputMonitor().setUpdateInputWindowsNeededLw();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700658 if (performLayout) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800659 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700660 false /*updateInputWindows*/);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800661 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700662 }
Arthur Hung95b38a92018-07-20 18:56:12 +0800663 getDisplayContent().getInputMonitor().updateInputWindowsLw(false /*force*/);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700664 }
665 }
666
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200667 if (isReallyAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700668 delayed = true;
Jorim Jaggiab9fcb22018-03-15 23:46:12 +0100669 } else {
670
671 // We aren't animating anything, but exiting windows rely on the animation finished
672 // callback being called in case the AppWindowToken was pretending to be animating,
673 // which we might have done because we were in closing/opening apps list.
674 onAnimationFinished();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700675 }
676
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700677 for (int i = mChildren.size() - 1; i >= 0 && !delayed; i--) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100678 if ((mChildren.get(i)).isSelfOrChildAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700679 delayed = true;
680 }
681 }
682
683 if (visibilityChanged) {
684 if (visible && !delayed) {
685 // The token was made immediately visible, there will be no entrance animation.
686 // We need to inform the client the enter animation was finished.
687 mEnteringAnimation = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800688 mWmService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(
689 token);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700690 }
Robert Carr61b81112017-07-17 18:08:15 -0700691
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800692 // If we're becoming visible, immediately change client visibility as well. there seem
693 // to be some edge cases where we change our visibility but client visibility never gets
694 // updated.
Jorim Jaggi110839b2018-01-22 12:49:04 +0100695 // If we're becoming invisible, update the client visibility if we are not running an
696 // animation. Otherwise, we'll update client visibility in onAnimationFinished.
Jorim Jaggi3cad57f2018-02-20 18:32:01 +0100697 if (visible || !isReallyAnimating()) {
Jorim Jaggi110839b2018-01-22 12:49:04 +0100698 setClientHidden(!visible);
Jorim Jaggi4876b4a2018-01-11 15:43:49 +0100699 }
700
lumark588a3e82018-07-20 18:53:54 +0800701 if (!getDisplayContent().mClosingApps.contains(this)
702 && !getDisplayContent().mOpeningApps.contains(this)) {
chaviwa953fcf2018-03-01 12:00:39 -0800703 // The token is not closing nor opening, so even if there is an animation set, that
704 // doesn't mean that it goes through the normal app transition cycle so we have
705 // to inform the docked controller about visibility change.
706 // TODO(multi-display): notify docked divider on all displays where visibility was
707 // affected.
lumark588a3e82018-07-20 18:53:54 +0800708 getDisplayContent().getDockedDividerController().notifyAppVisibilityChanged();
chaviwa953fcf2018-03-01 12:00:39 -0800709
710 // Take the screenshot before possibly hiding the WSA, otherwise the screenshot
711 // will not be taken.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800712 mWmService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible);
chaviwa953fcf2018-03-01 12:00:39 -0800713 }
714
Robert Carre7cc44d2017-03-20 19:04:30 -0700715 // If we are hidden but there is no delay needed we immediately
716 // apply the Surface transaction so that the ActivityManager
Robert Carr61b81112017-07-17 18:08:15 -0700717 // can have some guarantee on the Surface state following
718 // setting the visibility. This captures cases like dismissing
719 // the docked or pinned stack where there is no app transition.
720 //
721 // In the case of a "Null" animation, there will be
722 // no animation but there will still be a transition set.
723 // We still need to delay hiding the surface such that it
724 // can be synchronized with showing the next surface in the transition.
lumark588a3e82018-07-20 18:53:54 +0800725 if (isHidden() && !delayed && !getDisplayContent().mAppTransition.isTransitionSet()) {
Robert Carr6914f082017-03-20 19:04:30 -0700726 SurfaceControl.openTransaction();
727 for (int i = mChildren.size() - 1; i >= 0; i--) {
728 mChildren.get(i).mWinAnimator.hide("immediately hidden");
729 }
730 SurfaceControl.closeTransaction();
731 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700732 }
733
734 return delayed;
735 }
736
Jorim Jaggi87fdbcb2017-08-17 13:41:11 +0200737 /**
738 * @return The to top most child window for which {@link LayoutParams#isFullscreen()} returns
739 * true.
740 */
741 WindowState getTopFullscreenWindow() {
742 for (int i = mChildren.size() - 1; i >= 0; i--) {
743 final WindowState win = mChildren.get(i);
744 if (win != null && win.mAttrs.isFullscreen()) {
745 return win;
746 }
747 }
748 return null;
749 }
750
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800751 WindowState findMainWindow() {
Matthew Ng53e66b22018-01-12 17:13:13 -0800752 return findMainWindow(true);
753 }
754
755 /**
756 * Finds the main window that either has type base application or application starting if
757 * requested.
758 *
759 * @param includeStartingApp Allow to search application-starting windows to also be returned.
760 * @return The main window of type base application or application starting if requested.
761 */
762 WindowState findMainWindow(boolean includeStartingApp) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700763 WindowState candidate = null;
Matthew Ng53e66b22018-01-12 17:13:13 -0800764 for (int j = mChildren.size() - 1; j >= 0; --j) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700765 final WindowState win = mChildren.get(j);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700766 final int type = win.mAttrs.type;
767 // No need to loop through child window as base application and starting types can't be
768 // child windows.
Matthew Ng53e66b22018-01-12 17:13:13 -0800769 if (type == TYPE_BASE_APPLICATION
770 || (includeStartingApp && type == TYPE_APPLICATION_STARTING)) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700771 // In cases where there are multiple windows, we prefer the non-exiting window. This
Sungsoo Lim0d3d1f82015-12-02 14:47:59 +0900772 // happens for example when replacing windows during an activity relaunch. When
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700773 // constructing the animation, we want the new window, not the exiting one.
Wale Ogunwalec48a3542016-02-19 15:18:45 -0800774 if (win.mAnimatingExit) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700775 candidate = win;
776 } else {
777 return win;
778 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800779 }
780 }
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700781 return candidate;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800782 }
783
Wale Ogunwale6cae7652015-12-26 07:36:26 -0800784 boolean windowsAreFocusable() {
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800785 if (mTargetSdk < Build.VERSION_CODES.Q) {
786 final int pid = mActivityRecord != null
787 ? (mActivityRecord.app != null ? mActivityRecord.app.getPid() : 0) : 0;
788 final AppWindowToken topFocusedAppOfMyProcess =
789 mWmService.mRoot.mTopFocusedAppByProcess.get(pid);
790 if (topFocusedAppOfMyProcess != null && topFocusedAppOfMyProcess != this) {
791 // For the apps below Q, there can be only one app which has the focused window per
792 // process, because legacy apps may not be ready for a multi-focus system.
793 return false;
794 }
795 }
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700796 return getWindowConfiguration().canReceiveKeys() || mAlwaysFocusable;
Wale Ogunwaled045c822015-12-02 09:14:28 -0800797 }
798
Wale Ogunwale571771c2016-08-26 13:18:50 -0700799 @Override
Wale Ogunwale44f21802016-09-02 12:49:48 -0700800 boolean isVisible() {
Wale Ogunwalee471be62016-10-03 07:53:55 -0700801 // If the app token isn't hidden then it is considered visible and there is no need to check
802 // its children windows to see if they are visible.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200803 return !isHidden();
Wale Ogunwale44f21802016-09-02 12:49:48 -0700804 }
805
806 @Override
Wale Ogunwalee287e192017-04-21 09:30:12 -0700807 void removeImmediately() {
808 onRemovedFromDisplay();
Yunfan Chen3a77f282018-12-12 15:47:52 -0800809 if (mActivityRecord != null) {
810 mActivityRecord.unregisterConfigurationChangeListener(this);
811 }
Wale Ogunwalee287e192017-04-21 09:30:12 -0700812 super.removeImmediately();
813 }
814
815 @Override
Wale Ogunwale571771c2016-08-26 13:18:50 -0700816 void removeIfPossible() {
Craig Mautnere3119b72015-01-20 15:02:36 -0800817 mIsExiting = false;
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800818 removeAllWindowsIfPossible();
Bryce Lee6d410262017-02-28 15:30:17 -0800819 removeImmediately();
Craig Mautnere3119b72015-01-20 15:02:36 -0800820 }
821
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700822 @Override
823 boolean checkCompleteDeferredRemoval() {
824 if (mIsExiting) {
825 removeIfPossible();
826 }
827 return super.checkCompleteDeferredRemoval();
828 }
829
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700830 void onRemovedFromDisplay() {
Wale Ogunwalee287e192017-04-21 09:30:12 -0700831 if (mRemovingFromDisplay) {
832 return;
833 }
834 mRemovingFromDisplay = true;
835
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700836 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app token: " + this);
837
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800838 boolean delayed = commitVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700839
lumark588a3e82018-07-20 18:53:54 +0800840 getDisplayContent().mOpeningApps.remove(this);
Evan Rosky2289ba12018-11-19 18:28:18 -0800841 getDisplayContent().mChangingApps.remove(this);
lumark588a3e82018-07-20 18:53:54 +0800842 getDisplayContent().mUnknownAppVisibilityController.appRemovedOrHidden(this);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800843 mWmService.mTaskSnapshotController.onAppRemoved(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700844 waitingToShow = false;
lumark588a3e82018-07-20 18:53:54 +0800845 if (getDisplayContent().mClosingApps.contains(this)) {
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700846 delayed = true;
lumark588a3e82018-07-20 18:53:54 +0800847 } else if (getDisplayContent().mAppTransition.isTransitionSet()) {
848 getDisplayContent().mClosingApps.add(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700849 delayed = true;
850 }
851
852 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app " + this + " delayed=" + delayed
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200853 + " animation=" + getAnimation() + " animating=" + isSelfAnimating());
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700854
855 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: "
856 + this + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
857
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800858 if (startingData != null) {
859 removeStartingWindow();
Jorim Jaggi19be6052017-08-03 18:33:43 +0200860 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800861
Winson Chung87e5d552017-04-05 11:49:38 -0700862 // If this window was animating, then we need to ensure that the app transition notifies
lumark588a3e82018-07-20 18:53:54 +0800863 // that animations have completed in DisplayContent.handleAnimatingStoppedAndTransition(),
864 // so add to that list now
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200865 if (isSelfAnimating()) {
lumark588a3e82018-07-20 18:53:54 +0800866 getDisplayContent().mNoAnimationNotifyOnTransitionFinished.add(token);
Winson Chung87e5d552017-04-05 11:49:38 -0700867 }
868
Wale Ogunwalee287e192017-04-21 09:30:12 -0700869 final TaskStack stack = getStack();
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700870 if (delayed && !isEmpty()) {
871 // set the token aside because it has an active animation to be finished
872 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM,
873 "removeAppToken make exiting: " + this);
Wale Ogunwalee287e192017-04-21 09:30:12 -0700874 if (stack != null) {
875 stack.mExitingAppTokens.add(this);
876 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700877 mIsExiting = true;
878 } else {
879 // Make sure there is no animation running on this token, so any windows associated
880 // with it will be removed as soon as their animations are complete
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200881 cancelAnimation();
Wale Ogunwale3106ae012017-05-16 08:56:37 -0700882 if (stack != null) {
883 stack.mExitingAppTokens.remove(this);
884 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700885 removeIfPossible();
886 }
887
888 removed = true;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700889 stopFreezingScreen(true, true);
Bryce Lee6d410262017-02-28 15:30:17 -0800890
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800891 final DisplayContent dc = getDisplayContent();
892 if (dc.mFocusedApp == this) {
893 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + this
894 + " displayId=" + dc.getDisplayId());
895 dc.setFocusedApp(null);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800896 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700897 }
Riddle Hsu192fe762019-01-15 23:41:57 +0800898 if (mLetterbox != null) {
899 mLetterbox.destroy();
900 mLetterbox = null;
901 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700902
903 if (!delayed) {
904 updateReportedVisibilityLocked();
905 }
Wale Ogunwalee287e192017-04-21 09:30:12 -0700906
907 mRemovingFromDisplay = false;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700908 }
909
Chong Zhange05bcb12016-07-26 17:47:29 -0700910 void clearAnimatingFlags() {
Chong Zhangb0d26702016-08-12 16:03:29 -0700911 boolean wallpaperMightChange = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700912 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700913 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700914 wallpaperMightChange |= win.clearAnimatingFlags();
Chong Zhange05bcb12016-07-26 17:47:29 -0700915 }
Chong Zhangb0d26702016-08-12 16:03:29 -0700916 if (wallpaperMightChange) {
917 requestUpdateWallpaperIfNeeded();
918 }
Chong Zhange05bcb12016-07-26 17:47:29 -0700919 }
920
Robert Carre12aece2016-02-02 22:43:27 -0800921 void destroySurfaces() {
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700922 destroySurfaces(false /*cleanupOnResume*/);
923 }
924
925 /**
926 * Destroy surfaces which have been marked as eligible by the animator, taking care to ensure
927 * the client has finished with them.
928 *
929 * @param cleanupOnResume whether this is done when app is resumed without fully stopped. If
930 * set to true, destroy only surfaces of removed windows, and clear relevant flags of the
931 * others so that they are ready to be reused. If set to false (common case), destroy all
932 * surfaces that's eligible, if the app is already stopped.
933 */
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700934 private void destroySurfaces(boolean cleanupOnResume) {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700935 boolean destroyedSomething = false;
Jorim Jaggia5e10572017-11-15 14:36:26 +0100936
937 // Copying to a different list as multiple children can be removed.
Jorim Jaggi59f3e922018-01-05 15:40:32 +0100938 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
Jorim Jaggia5e10572017-11-15 14:36:26 +0100939 for (int i = children.size() - 1; i >= 0; i--) {
940 final WindowState win = children.get(i);
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700941 destroyedSomething |= win.destroySurface(cleanupOnResume, mAppStopped);
Robert Carre12aece2016-02-02 22:43:27 -0800942 }
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700943 if (destroyedSomething) {
944 final DisplayContent dc = getDisplayContent();
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700945 dc.assignWindowLayers(true /*setLayoutNeeded*/);
Adrian Roos23df3a32018-03-15 15:41:13 +0100946 updateLetterboxSurface(null);
Robert Carre12aece2016-02-02 22:43:27 -0800947 }
948 }
949
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800950 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700951 * Notify that the app is now resumed, and it was not stopped before, perform a clean
952 * up of the surfaces
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800953 */
Jorim Jaggibae01b12017-04-11 16:29:10 -0700954 void notifyAppResumed(boolean wasStopped) {
Chong Zhangad24f962016-08-25 12:12:33 -0700955 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppResumed: wasStopped=" + wasStopped
Jorim Jaggibae01b12017-04-11 16:29:10 -0700956 + " " + this);
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700957 mAppStopped = false;
chaviwd3bf08d2017-08-01 17:24:59 -0700958 // Allow the window to turn the screen on once the app is resumed again.
959 setCanTurnScreenOn(true);
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700960 if (!wasStopped) {
961 destroySurfaces(true /*cleanupOnResume*/);
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800962 }
Robert Carre12aece2016-02-02 22:43:27 -0800963 }
964
Chong Zhangbef461f2015-10-27 11:38:24 -0700965 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700966 * Notify that the app has stopped, and it is okay to destroy any surfaces which were
967 * keeping alive in case they were still being used.
968 */
969 void notifyAppStopped() {
970 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: " + this);
971 mAppStopped = true;
972 destroySurfaces();
973 // Remove any starting window that was added for this app if they are still around.
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800974 removeStartingWindow();
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700975 }
976
Chong Zhang92147042016-05-09 12:47:11 -0700977 void clearAllDrawn() {
978 allDrawn = false;
979 deferClearAllDrawn = false;
Chong Zhangbef461f2015-10-27 11:38:24 -0700980 }
981
Bryce Lee6d410262017-02-28 15:30:17 -0800982 Task getTask() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -0800983 return (Task) getParent();
Bryce Lee6d410262017-02-28 15:30:17 -0800984 }
985
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800986 TaskStack getStack() {
987 final Task task = getTask();
988 if (task != null) {
989 return task.mStack;
990 } else {
991 return null;
992 }
993 }
994
Bryce Lee6d410262017-02-28 15:30:17 -0800995 @Override
Riddle Hsu3a4bb612019-01-31 00:02:22 +0800996 void onParentChanged() {
997 super.onParentChanged();
Bryce Lee6d410262017-02-28 15:30:17 -0800998
Robert Carred3e83b2017-04-21 13:26:55 -0700999 final Task task = getTask();
1000
Bryce Lee6d410262017-02-28 15:30:17 -08001001 // When the associated task is {@code null}, the {@link AppWindowToken} can no longer
1002 // access visual elements like the {@link DisplayContent}. We must remove any associations
1003 // such as animations.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001004 if (!mReparenting) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001005 if (task == null) {
1006 // It is possible we have been marked as a closing app earlier. We must remove ourselves
1007 // from this list so we do not participate in any future animations.
lumark588a3e82018-07-20 18:53:54 +08001008 getDisplayContent().mClosingApps.remove(this);
Robert Carred3e83b2017-04-21 13:26:55 -07001009 } else if (mLastParent != null && mLastParent.mStack != null) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001010 task.mStack.mExitingAppTokens.remove(this);
1011 }
Bryce Lee6d410262017-02-28 15:30:17 -08001012 }
Jorim Jaggi6de61012018-03-19 14:53:23 +01001013 final TaskStack stack = getStack();
1014
1015 // If we reparent, make sure to remove ourselves from the old animation registry.
1016 if (mAnimatingAppWindowTokenRegistry != null) {
1017 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
1018 }
1019 mAnimatingAppWindowTokenRegistry = stack != null
1020 ? stack.getAnimatingAppWindowTokenRegistry()
1021 : null;
1022
Robert Carred3e83b2017-04-21 13:26:55 -07001023 mLastParent = task;
chaviwdcf76ec2019-01-11 16:48:46 -08001024
1025 updateColorTransform();
Bryce Lee6d410262017-02-28 15:30:17 -08001026 }
1027
Wale Ogunwalefa854eb2016-09-20 13:43:52 -07001028 void postWindowRemoveStartingWindowCleanup(WindowState win) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001029 // TODO: Something smells about the code below...Is there a better way?
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001030 if (startingWindow == win) {
1031 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Notify removed startingWindow " + win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001032 removeStartingWindow();
Wale Ogunwale6c459212017-05-17 08:56:03 -07001033 } else if (mChildren.size() == 0) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001034 // If this is the last window and we had requested a starting transition window,
1035 // well there is no point now.
Jorim Jaggi02886a82016-12-06 09:10:06 -08001036 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Nulling last startingData");
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001037 startingData = null;
Wale Ogunwale6c459212017-05-17 08:56:03 -07001038 if (mHiddenSetFromTransferredStartingWindow) {
1039 // We set the hidden state to false for the token from a transferred starting window.
1040 // We now reset it back to true since the starting window was the last window in the
1041 // token.
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001042 setHidden(true);
Wale Ogunwale6c459212017-05-17 08:56:03 -07001043 }
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01001044 } else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001045 // If this is the last window except for a starting transition window,
1046 // we need to get rid of the starting transition.
Jorim Jaggie4b0f282017-05-17 15:10:29 +02001047 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Last window, removing starting window "
1048 + win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001049 removeStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001050 }
1051 }
1052
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001053 void removeDeadWindows() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001054 for (int winNdx = mChildren.size() - 1; winNdx >= 0; --winNdx) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001055 WindowState win = mChildren.get(winNdx);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001056 if (win.mAppDied) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001057 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.w(TAG,
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001058 "removeDeadWindows: " + win);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001059 // Set mDestroying, we don't want any animation or delayed removal here.
1060 win.mDestroying = true;
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001061 // Also removes child windows.
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001062 win.removeIfPossible();
Chong Zhang112eb8c2015-11-02 11:17:00 -08001063 }
1064 }
1065 }
1066
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001067 boolean hasWindowsAlive() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001068 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001069 // No need to loop through child windows as the answer should be the same as that of the
1070 // parent window.
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001071 if (!(mChildren.get(i)).mAppDied) {
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001072 return true;
1073 }
1074 }
1075 return false;
1076 }
1077
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001078 void setWillReplaceWindows(boolean animate) {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001079 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
1080 "Marking app token " + this + " with replacing windows.");
Robert Carra1eb4392015-12-10 12:43:51 -08001081
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001082 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001083 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001084 w.setWillReplaceWindow(animate);
Robert Carra1eb4392015-12-10 12:43:51 -08001085 }
Robert Carra1eb4392015-12-10 12:43:51 -08001086 }
1087
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001088 void setWillReplaceChildWindows() {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001089 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Marking app token " + this
Robert Carr23fa16b2016-01-13 13:19:58 -08001090 + " with replacing child windows.");
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001091 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001092 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001093 w.setWillReplaceChildWindows();
Robert Carr23fa16b2016-01-13 13:19:58 -08001094 }
1095 }
1096
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001097 void clearWillReplaceWindows() {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001098 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
1099 "Resetting app token " + this + " of replacing window marks.");
Chong Zhangf596cd52016-01-05 13:42:44 -08001100
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001101 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001102 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001103 w.clearWillReplaceWindow();
Chong Zhangf596cd52016-01-05 13:42:44 -08001104 }
1105 }
1106
Chong Zhang4d7369a2016-04-25 16:09:14 -07001107 void requestUpdateWallpaperIfNeeded() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001108 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001109 final WindowState w = mChildren.get(i);
Chong Zhang4d7369a2016-04-25 16:09:14 -07001110 w.requestUpdateWallpaperIfNeeded();
1111 }
1112 }
1113
Chong Zhangd78ddb42016-03-02 17:01:14 -08001114 boolean isRelaunching() {
1115 return mPendingRelaunchCount > 0;
1116 }
1117
Robert Carr68375192017-06-13 12:41:53 -07001118 boolean shouldFreezeBounds() {
1119 final Task task = getTask();
1120
1121 // For freeform windows, we can't freeze the bounds at the moment because this would make
1122 // the resizing unresponsive.
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001123 if (task == null || task.inFreeformWindowingMode()) {
Robert Carr68375192017-06-13 12:41:53 -07001124 return false;
1125 }
1126
1127 // We freeze the bounds while drag resizing to deal with the time between
1128 // the divider/drag handle being released, and the handling it's new
1129 // configuration. If we are relaunched outside of the drag resizing state,
1130 // we need to be careful not to do this.
1131 return getTask().isDragResizing();
1132 }
1133
Chong Zhangd78ddb42016-03-02 17:01:14 -08001134 void startRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001135 if (shouldFreezeBounds()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08001136 freezeBounds();
1137 }
Robert Carrd5c7dd62017-03-08 10:39:30 -08001138
1139 // In the process of tearing down before relaunching, the app will
1140 // try and clean up it's child surfaces. We need to prevent this from
1141 // happening, so we sever the children, transfering their ownership
1142 // from the client it-self to the parent surface (owned by us).
Robert Carr29daa922018-04-27 11:56:48 -07001143 detachChildren();
1144
1145 mPendingRelaunchCount++;
1146 }
1147
1148 void detachChildren() {
Robert Carrfd8e93b2018-05-10 13:40:25 -07001149 SurfaceControl.openTransaction();
Robert Carrd5c7dd62017-03-08 10:39:30 -08001150 for (int i = mChildren.size() - 1; i >= 0; i--) {
1151 final WindowState w = mChildren.get(i);
1152 w.mWinAnimator.detachChildren();
1153 }
Robert Carrfd8e93b2018-05-10 13:40:25 -07001154 SurfaceControl.closeTransaction();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001155 }
1156
1157 void finishRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001158 unfreezeBounds();
1159
Chong Zhangd78ddb42016-03-02 17:01:14 -08001160 if (mPendingRelaunchCount > 0) {
1161 mPendingRelaunchCount--;
Bryce Lee081554b2017-05-25 07:52:12 -07001162 } else {
1163 // Update keyguard flags upon finishing relaunch.
1164 checkKeyguardFlagsChanged();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001165 }
1166 }
1167
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001168 void clearRelaunching() {
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001169 if (mPendingRelaunchCount == 0) {
1170 return;
1171 }
Robert Carr68375192017-06-13 12:41:53 -07001172 unfreezeBounds();
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001173 mPendingRelaunchCount = 0;
1174 }
1175
Wale Ogunwale07bcab72016-10-14 15:30:09 -07001176 /**
1177 * Returns true if the new child window we are adding to this token is considered greater than
1178 * the existing child window in this token in terms of z-order.
1179 */
1180 @Override
1181 protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
1182 WindowState existingWindow) {
1183 final int type1 = newWindow.mAttrs.type;
1184 final int type2 = existingWindow.mAttrs.type;
1185
1186 // Base application windows should be z-ordered BELOW all other windows in the app token.
1187 if (type1 == TYPE_BASE_APPLICATION && type2 != TYPE_BASE_APPLICATION) {
1188 return false;
1189 } else if (type1 != TYPE_BASE_APPLICATION && type2 == TYPE_BASE_APPLICATION) {
1190 return true;
1191 }
1192
1193 // Starting windows should be z-ordered ABOVE all other windows in the app token.
1194 if (type1 == TYPE_APPLICATION_STARTING && type2 != TYPE_APPLICATION_STARTING) {
1195 return true;
1196 } else if (type1 != TYPE_APPLICATION_STARTING && type2 == TYPE_APPLICATION_STARTING) {
1197 return false;
1198 }
1199
1200 // Otherwise the new window is greater than the existing window.
1201 return true;
1202 }
1203
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001204 @Override
Robert Carra1eb4392015-12-10 12:43:51 -08001205 void addWindow(WindowState w) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001206 super.addWindow(w);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001207
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001208 boolean gotReplacementWindow = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001209 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001210 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001211 gotReplacementWindow |= candidate.setReplacementWindowIfNeeded(w);
1212 }
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001213
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001214 // if we got a replacement window, reset the timeout to give drawing more time
1215 if (gotReplacementWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001216 mWmService.scheduleWindowReplacementTimeouts(this);
Robert Carra1eb4392015-12-10 12:43:51 -08001217 }
Jorim Jaggife762342016-10-13 14:33:27 +02001218 checkKeyguardFlagsChanged();
1219 }
1220
1221 @Override
1222 void removeChild(WindowState child) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001223 if (!mChildren.contains(child)) {
1224 // This can be true when testing.
1225 return;
1226 }
Jorim Jaggife762342016-10-13 14:33:27 +02001227 super.removeChild(child);
1228 checkKeyguardFlagsChanged();
Adrian Roos23df3a32018-03-15 15:41:13 +01001229 updateLetterboxSurface(child);
Robert Carra1eb4392015-12-10 12:43:51 -08001230 }
1231
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001232 private boolean waitingForReplacement() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001233 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001234 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001235 if (candidate.waitingForReplacement()) {
Robert Carra1eb4392015-12-10 12:43:51 -08001236 return true;
1237 }
1238 }
1239 return false;
1240 }
1241
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001242 void onWindowReplacementTimeout() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001243 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001244 (mChildren.get(i)).onWindowReplacementTimeout();
Robert Carra1eb4392015-12-10 12:43:51 -08001245 }
1246 }
1247
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001248 void reparent(Task task, int position) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001249 if (DEBUG_ADD_REMOVE) {
1250 Slog.i(TAG_WM, "reparent: moving app token=" + this
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001251 + " to task=" + task.mTaskId + " at " + position);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001252 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001253 if (task == null) {
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001254 throw new IllegalArgumentException("reparent: could not find task");
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001255 }
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001256 final Task currentTask = getTask();
1257 if (task == currentTask) {
Winson Chung30480042017-01-26 10:55:34 -08001258 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001259 "window token=" + this + " already child of task=" + currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001260 }
Bryce Lee6d410262017-02-28 15:30:17 -08001261
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001262 if (currentTask.mStack != task.mStack) {
Bryce Lee6d410262017-02-28 15:30:17 -08001263 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001264 "window token=" + this + " current task=" + currentTask
Bryce Lee6d410262017-02-28 15:30:17 -08001265 + " belongs to a different stack than " + task);
1266 }
1267
Winson Chung30480042017-01-26 10:55:34 -08001268 if (DEBUG_ADD_REMOVE) Slog.i(TAG, "reParentWindowToken: removing window token=" + this
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001269 + " from task=" + currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001270 final DisplayContent prevDisplayContent = getDisplayContent();
1271
Bryce Lee6d410262017-02-28 15:30:17 -08001272 mReparenting = true;
1273
Winson Chung30480042017-01-26 10:55:34 -08001274 getParent().removeChild(this);
1275 task.addChild(this, position);
1276
Bryce Lee6d410262017-02-28 15:30:17 -08001277 mReparenting = false;
1278
Winson Chung30480042017-01-26 10:55:34 -08001279 // Relayout display(s).
1280 final DisplayContent displayContent = task.getDisplayContent();
1281 displayContent.setLayoutNeeded();
1282 if (prevDisplayContent != displayContent) {
1283 onDisplayChanged(displayContent);
1284 prevDisplayContent.setLayoutNeeded();
1285 }
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001286 getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
Winson Chung30480042017-01-26 10:55:34 -08001287 }
1288
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001289 @Override
1290 void onDisplayChanged(DisplayContent dc) {
1291 DisplayContent prevDc = mDisplayContent;
1292 super.onDisplayChanged(dc);
Evan Rosky25b56192019-02-06 16:10:56 -08001293 if (prevDc == null) {
1294 return;
1295 }
1296 if (prevDc.mChangingApps.contains(this)) {
1297 // This gets called *after* the AppWindowToken has been reparented to the new display.
1298 // That reparenting resulted in this window changing modes (eg. FREEFORM -> FULLSCREEN),
1299 // so this token is now "frozen" while waiting for the animation to start on prevDc
1300 // (which will be cancelled since the window is no-longer a child). However, since this
1301 // is no longer a child of prevDc, this won't be notified of the cancelled animation,
1302 // so we need to cancel the change transition here.
1303 clearChangeLeash(getPendingTransaction(), true /* cancel */);
1304 }
1305 if (prevDc.mFocusedApp == this) {
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001306 prevDc.setFocusedApp(null);
lumarkbf844642018-11-23 17:11:36 +08001307 final TaskStack stack = dc.getTopStack();
1308 if (stack != null) {
1309 final Task task = stack.getTopChild();
1310 if (task != null && task.getTopChild() == this) {
1311 dc.setFocusedApp(this);
1312 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001313 }
1314 }
Riddle Hsu192fe762019-01-15 23:41:57 +08001315
1316 if (prevDc != mDisplayContent && mLetterbox != null) {
1317 mLetterbox.onMovedToDisplay(mDisplayContent.getDisplayId());
1318 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001319 }
1320
Jorim Jaggi0429f352015-12-22 16:29:16 +01001321 /**
1322 * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds
1323 * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even
1324 * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen
1325 * with a queue.
1326 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001327 private void freezeBounds() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001328 final Task task = getTask();
1329 mFrozenBounds.offer(new Rect(task.mPreparedFrozenBounds));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001330
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001331 if (task.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001332 // We didn't call prepareFreezingBounds on the task, so use the current value.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001333 mFrozenMergedConfig.offer(new Configuration(task.getConfiguration()));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001334 } else {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001335 mFrozenMergedConfig.offer(new Configuration(task.mPreparedFrozenMergedConfig));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001336 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001337 // Calling unset() to make it equal to Configuration.EMPTY.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001338 task.mPreparedFrozenMergedConfig.unset();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001339 }
1340
1341 /**
1342 * Unfreezes the previously frozen bounds. See {@link #freezeBounds}.
1343 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001344 private void unfreezeBounds() {
Robert Carr68375192017-06-13 12:41:53 -07001345 if (mFrozenBounds.isEmpty()) {
1346 return;
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001347 }
Robert Carr68375192017-06-13 12:41:53 -07001348 mFrozenBounds.remove();
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001349 if (!mFrozenMergedConfig.isEmpty()) {
1350 mFrozenMergedConfig.remove();
1351 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001352 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001353 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001354 win.onUnfreezeBounds();
Jorim Jaggi4846ee32016-01-07 17:39:12 +01001355 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001356 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001357 }
1358
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001359 void setAppLayoutChanges(int changes, String reason) {
1360 if (!mChildren.isEmpty()) {
1361 final DisplayContent dc = getDisplayContent();
1362 dc.pendingLayoutChanges |= changes;
1363 if (DEBUG_LAYOUT_REPEATS) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001364 mWmService.mWindowPlacerLocked.debugLayoutRepeats(reason, dc.pendingLayoutChanges);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001365 }
1366 }
1367 }
1368
1369 void removeReplacedWindowIfNeeded(WindowState replacement) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001370 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001371 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001372 if (win.removeReplacedWindowIfNeeded(replacement)) {
1373 return;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001374 }
1375 }
1376 }
1377
1378 void startFreezingScreen() {
1379 if (DEBUG_ORIENTATION) logWithStack(TAG, "Set freezing of " + appToken + ": hidden="
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001380 + isHidden() + " freezing=" + mFreezingScreen + " hiddenRequested="
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001381 + hiddenRequested);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001382 if (!hiddenRequested) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001383 if (!mFreezingScreen) {
1384 mFreezingScreen = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001385 mWmService.registerAppFreezeListener(this);
1386 mWmService.mAppsFreezingScreen++;
1387 if (mWmService.mAppsFreezingScreen == 1) {
1388 mWmService.startFreezingDisplayLocked(0, 0, getDisplayContent());
1389 mWmService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
1390 mWmService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001391 }
1392 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001393 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001394 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001395 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001396 w.onStartFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001397 }
1398 }
1399 }
1400
1401 void stopFreezingScreen(boolean unfreezeSurfaceNow, boolean force) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001402 if (!mFreezingScreen) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001403 return;
1404 }
1405 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + this + " force=" + force);
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001406 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001407 boolean unfrozeWindows = false;
1408 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001409 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001410 unfrozeWindows |= w.onStopFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001411 }
1412 if (force || unfrozeWindows) {
1413 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "No longer freezing: " + this);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001414 mFreezingScreen = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001415 mWmService.unregisterAppFreezeListener(this);
1416 mWmService.mAppsFreezingScreen--;
1417 mWmService.mLastFinishedFreezeSource = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001418 }
1419 if (unfreezeSurfaceNow) {
1420 if (unfrozeWindows) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001421 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001422 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001423 mWmService.stopFreezingDisplayLocked();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001424 }
1425 }
1426
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001427 @Override
1428 public void onAppFreezeTimeout() {
1429 Slog.w(TAG_WM, "Force clearing freeze: " + this);
1430 stopFreezingScreen(true, true);
1431 }
1432
Jorim Jaggi60f9c972018-02-01 19:21:07 +01001433 /**
1434 * Tries to transfer the starting window from a token that's above ourselves in the task but
1435 * not visible anymore. This is a common scenario apps use: Trampoline activity T start main
1436 * activity M in the same task. Now, when reopening the task, T starts on top of M but then
1437 * immediately finishes after, so we have to transfer T to M.
1438 */
1439 void transferStartingWindowFromHiddenAboveTokenIfNeeded() {
1440 final Task task = getTask();
1441 for (int i = task.mChildren.size() - 1; i >= 0; i--) {
1442 final AppWindowToken fromToken = task.mChildren.get(i);
1443 if (fromToken == this) {
1444 return;
1445 }
1446 if (fromToken.hiddenRequested && transferStartingWindow(fromToken.token)) {
1447 return;
1448 }
1449 }
1450 }
1451
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001452 boolean transferStartingWindow(IBinder transferFrom) {
Wale Ogunwale02319a62016-09-26 15:21:22 -07001453 final AppWindowToken fromToken = getDisplayContent().getAppWindowToken(transferFrom);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001454 if (fromToken == null) {
1455 return false;
1456 }
1457
1458 final WindowState tStartingWindow = fromToken.startingWindow;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08001459 if (tStartingWindow != null && fromToken.startingSurface != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001460 // In this case, the starting icon has already been displayed, so start
1461 // letting windows get shown immediately without any more transitions.
lumark588a3e82018-07-20 18:53:54 +08001462 getDisplayContent().mSkipAppTransitionAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001463
1464 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Moving existing starting " + tStartingWindow
1465 + " from " + fromToken + " to " + this);
1466
1467 final long origId = Binder.clearCallingIdentity();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001468 try {
1469 // Transfer the starting window over to the new token.
1470 startingData = fromToken.startingData;
1471 startingSurface = fromToken.startingSurface;
1472 startingDisplayed = fromToken.startingDisplayed;
1473 fromToken.startingDisplayed = false;
1474 startingWindow = tStartingWindow;
1475 reportedVisible = fromToken.reportedVisible;
1476 fromToken.startingData = null;
1477 fromToken.startingSurface = null;
1478 fromToken.startingWindow = null;
1479 fromToken.startingMoved = true;
1480 tStartingWindow.mToken = this;
1481 tStartingWindow.mAppToken = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001482
Peter Visontay3556a3b2017-11-01 17:23:17 +00001483 if (DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
1484 "Removing starting " + tStartingWindow + " from " + fromToken);
1485 fromToken.removeChild(tStartingWindow);
1486 fromToken.postWindowRemoveStartingWindowCleanup(tStartingWindow);
1487 fromToken.mHiddenSetFromTransferredStartingWindow = false;
1488 addWindow(tStartingWindow);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001489
Peter Visontay3556a3b2017-11-01 17:23:17 +00001490 // Propagate other interesting state between the tokens. If the old token is displayed,
1491 // we should immediately force the new one to be displayed. If it is animating, we need
1492 // to move that animation to the new one.
1493 if (fromToken.allDrawn) {
1494 allDrawn = true;
1495 deferClearAllDrawn = fromToken.deferClearAllDrawn;
1496 }
1497 if (fromToken.firstWindowDrawn) {
1498 firstWindowDrawn = true;
1499 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001500 if (!fromToken.isHidden()) {
1501 setHidden(false);
Peter Visontay3556a3b2017-11-01 17:23:17 +00001502 hiddenRequested = false;
1503 mHiddenSetFromTransferredStartingWindow = true;
1504 }
1505 setClientHidden(fromToken.mClientHidden);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001506
Jorim Jaggi980c9de2017-11-17 01:41:37 +01001507 transferAnimation(fromToken);
1508
1509 // When transferring an animation, we no longer need to apply an animation to the
1510 // the token we transfer the animation over. Thus, remove the animation from
1511 // pending opening apps.
lumark588a3e82018-07-20 18:53:54 +08001512 getDisplayContent().mOpeningApps.remove(this);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001513
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001514 mWmService.updateFocusedWindowLocked(
Peter Visontay3556a3b2017-11-01 17:23:17 +00001515 UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/);
1516 getDisplayContent().setLayoutNeeded();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001517 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001518 } finally {
1519 Binder.restoreCallingIdentity(origId);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001520 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001521 return true;
1522 } else if (fromToken.startingData != null) {
1523 // The previous app was getting ready to show a
1524 // starting window, but hasn't yet done so. Steal it!
1525 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
1526 "Moving pending starting from " + fromToken + " to " + this);
1527 startingData = fromToken.startingData;
1528 fromToken.startingData = null;
1529 fromToken.startingMoved = true;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001530 scheduleAddStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001531 return true;
1532 }
1533
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001534 // TODO: Transfer thumbnail
1535
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001536 return false;
1537 }
1538
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001539 boolean isLastWindow(WindowState win) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001540 return mChildren.size() == 1 && mChildren.get(0) == win;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001541 }
1542
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001543 @Override
1544 void onAppTransitionDone() {
1545 sendingToBottom = false;
1546 }
1547
Wale Ogunwale51362492016-09-08 17:49:17 -07001548 /**
1549 * We override because this class doesn't want its children affecting its reported orientation
1550 * in anyway.
1551 */
1552 @Override
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001553 int getOrientation(int candidate) {
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001554 if (candidate == SCREEN_ORIENTATION_BEHIND) {
1555 // Allow app to specify orientation regardless of its visibility state if the current
1556 // candidate want us to use orientation behind. I.e. the visible app on-top of this one
1557 // wants us to use the orientation of the app behind it.
1558 return mOrientation;
1559 }
1560
Bryce Lee61fbcbc2017-03-10 14:14:03 -08001561 // The {@link AppWindowToken} should only specify an orientation when it is not closing or
1562 // going to the bottom. Allowing closing {@link AppWindowToken} to participate can lead to
1563 // an Activity in another task being started in the wrong orientation during the transition.
lumark588a3e82018-07-20 18:53:54 +08001564 if (!(sendingToBottom || getDisplayContent().mClosingApps.contains(this))
1565 && (isVisible() || getDisplayContent().mOpeningApps.contains(this))) {
Bryce Leea163b762017-01-24 11:05:01 -08001566 return mOrientation;
Wale Ogunwale51362492016-09-08 17:49:17 -07001567 }
Bryce Leea163b762017-01-24 11:05:01 -08001568
1569 return SCREEN_ORIENTATION_UNSET;
Wale Ogunwale51362492016-09-08 17:49:17 -07001570 }
1571
Wale Ogunwaleb198b742016-12-01 08:44:09 -08001572 /** Returns the app's preferred orientation regardless of its currently visibility state. */
1573 int getOrientationIgnoreVisibility() {
1574 return mOrientation;
1575 }
1576
Riddle Hsub398da32019-01-21 21:48:16 +08001577 /** @return {@code true} if the compatibility bounds is taking effect. */
1578 boolean inSizeCompatMode() {
1579 return mSizeCompatBounds != null;
1580 }
1581
1582 @Override
1583 float getSizeCompatScale() {
1584 return inSizeCompatMode() ? mSizeCompatScale : super.getSizeCompatScale();
1585 }
1586
1587 /**
1588 * @return Non-empty bounds if the activity has override bounds.
1589 * @see ActivityRecord#resolveOverrideConfiguration(Configuration)
1590 */
1591 Rect getResolvedOverrideBounds() {
1592 // Get bounds from resolved override configuration because it is computed with orientation.
1593 return getResolvedOverrideConfiguration().windowConfiguration.getBounds();
1594 }
1595
Craig Mautnerdbb79912012-03-01 18:59:14 -08001596 @Override
Winson Chunge55c0192017-08-24 14:50:48 -07001597 public void onConfigurationChanged(Configuration newParentConfig) {
1598 final int prevWinMode = getWindowingMode();
Evan Rosky2289ba12018-11-19 18:28:18 -08001599 mTmpPrevBounds.set(getBounds());
Winson Chunge55c0192017-08-24 14:50:48 -07001600 super.onConfigurationChanged(newParentConfig);
Riddle Hsub398da32019-01-21 21:48:16 +08001601
1602 final Task task = getTask();
1603 final Rect overrideBounds = getResolvedOverrideBounds();
1604 if (task != null && !overrideBounds.isEmpty()
1605 // If the changes come from change-listener, the incoming parent configuration is
1606 // still the old one. Make sure their orientations are the same to reduce computing
1607 // the compatibility bounds for the intermediate state.
1608 && getResolvedOverrideConfiguration().orientation == newParentConfig.orientation) {
1609 final Rect taskBounds = task.getBounds();
1610 // Since we only center the activity horizontally, if only the fixed height is smaller
1611 // than its container, the override bounds don't need to take effect.
1612 if ((overrideBounds.width() != taskBounds.width()
1613 || overrideBounds.height() > taskBounds.height())) {
1614 calculateCompatBoundsTransformation(newParentConfig);
1615 updateSurfacePosition();
1616 } else if (mSizeCompatBounds != null) {
1617 mSizeCompatBounds = null;
1618 mSizeCompatScale = 1f;
1619 updateSurfacePosition();
1620 }
1621 }
1622
Winson Chunge55c0192017-08-24 14:50:48 -07001623 final int winMode = getWindowingMode();
1624
1625 if (prevWinMode == winMode) {
1626 return;
1627 }
1628
1629 if (prevWinMode != WINDOWING_MODE_UNDEFINED && winMode == WINDOWING_MODE_PINNED) {
1630 // Entering PiP from fullscreen, reset the snap fraction
1631 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(this);
Winson Chung82267ce2018-04-06 16:38:26 -07001632 } else if (prevWinMode == WINDOWING_MODE_PINNED && winMode != WINDOWING_MODE_UNDEFINED
1633 && !isHidden()) {
Winson Chunge55c0192017-08-24 14:50:48 -07001634 // Leaving PiP to fullscreen, save the snap fraction based on the pre-animation bounds
1635 // for the next re-entry into PiP (assuming the activity is not hidden or destroyed)
1636 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
1637 if (pinnedStack != null) {
Winson Chung8efa1652018-06-06 09:34:23 -07001638 final Rect stackBounds;
1639 if (pinnedStack.lastAnimatingBoundsWasToFullscreen()) {
1640 // We are animating the bounds, use the pre-animation bounds to save the snap
1641 // fraction
1642 stackBounds = pinnedStack.mPreAnimationBounds;
1643 } else {
1644 // We skip the animation if the fullscreen configuration is not compatible, so
1645 // use the current bounds to calculate the saved snap fraction instead
1646 // (see PinnedActivityStack.skipResizeAnimation())
1647 stackBounds = mTmpRect;
1648 pinnedStack.getBounds(stackBounds);
1649 }
Winson Chunge55c0192017-08-24 14:50:48 -07001650 mDisplayContent.mPinnedStackControllerLocked.saveReentrySnapFraction(this,
Winson Chung8efa1652018-06-06 09:34:23 -07001651 stackBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001652 }
Evan Rosky2289ba12018-11-19 18:28:18 -08001653 } else if (shouldStartChangeTransition(prevWinMode, winMode)) {
1654 initializeChangeTransition(mTmpPrevBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001655 }
1656 }
1657
Evan Rosky2289ba12018-11-19 18:28:18 -08001658 private boolean shouldStartChangeTransition(int prevWinMode, int newWinMode) {
Evan Rosky25b56192019-02-06 16:10:56 -08001659 if (mWmService.mDisableTransitionAnimation
1660 || !isVisible()
1661 || getDisplayContent().mAppTransition.isTransitionSet()
1662 || getSurfaceControl() == null) {
Evan Rosky2289ba12018-11-19 18:28:18 -08001663 return false;
1664 }
1665 // Only do an animation into and out-of freeform mode for now. Other mode
1666 // transition animations are currently handled by system-ui.
1667 return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
1668 }
1669
1670 /**
1671 * Initializes a change transition. Because the app is visible already, there is a small period
1672 * of time where the user can see the app content/window update before the transition starts.
1673 * To prevent this, we immediately take a snapshot and place the app/snapshot into a leash which
1674 * "freezes" the location/crop until the transition starts.
1675 * <p>
1676 * Here's a walk-through of the process:
1677 * 1. Create a temporary leash ("interim-change-leash") and reparent the app to it.
1678 * 2. Set the temporary leash's position/crop to the current state.
1679 * 3. Create a snapshot and place that at the top of the leash to cover up content changes.
1680 * 4. Once the transition is ready, it will reparent the app to the animation leash.
1681 * 5. Detach the interim-change-leash.
1682 */
1683 private void initializeChangeTransition(Rect startBounds) {
1684 mDisplayContent.prepareAppTransition(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
1685 false /* alwaysKeepCurrent */, 0, false /* forceOverride */);
1686 mDisplayContent.mChangingApps.add(this);
1687 mTransitStartRect.set(startBounds);
1688
1689 final SurfaceControl.Builder builder = makeAnimationLeash()
1690 .setParent(getAnimationLeashParent())
1691 .setName(getSurfaceControl() + " - interim-change-leash");
1692 mTransitChangeLeash = builder.build();
1693 Transaction t = getPendingTransaction();
1694 t.setWindowCrop(mTransitChangeLeash, startBounds.width(), startBounds.height());
1695 t.setPosition(mTransitChangeLeash, startBounds.left, startBounds.top);
1696 t.show(mTransitChangeLeash);
1697 t.reparent(getSurfaceControl(), mTransitChangeLeash);
1698 onAnimationLeashCreated(t, mTransitChangeLeash);
1699
Evan Rosky966759f2019-01-15 10:33:58 -08001700 // Skip creating snapshot if this transition is controlled by a remote animator which
1701 // doesn't need it.
1702 ArraySet<Integer> activityTypes = new ArraySet<>();
1703 activityTypes.add(getActivityType());
1704 RemoteAnimationAdapter adapter =
1705 mDisplayContent.mAppTransitionController.getRemoteAnimationOverride(
1706 this, TRANSIT_TASK_CHANGE_WINDOWING_MODE, activityTypes);
1707 if (adapter != null && !adapter.getChangeNeedsSnapshot()) {
1708 return;
1709 }
1710
Evan Rosky2289ba12018-11-19 18:28:18 -08001711 if (mThumbnail == null && getTask() != null) {
1712 final TaskSnapshotController snapshotCtrl = mWmService.mTaskSnapshotController;
1713 final ArraySet<Task> tasks = new ArraySet<>();
1714 tasks.add(getTask());
1715 snapshotCtrl.snapshotTasks(tasks);
1716 snapshotCtrl.addSkipClosingAppSnapshotTasks(tasks);
1717 final ActivityManager.TaskSnapshot snapshot = snapshotCtrl.getSnapshot(
1718 getTask().mTaskId, getTask().mUserId, false /* restoreFromDisk */,
1719 false /* reducedResolution */);
Yunfan Chendcb1fcf2019-02-07 19:08:41 +09001720 if (snapshot != null) {
1721 mThumbnail = new AppWindowThumbnail(t, this, snapshot.getSnapshot(),
1722 true /* relative */);
1723 }
Evan Rosky2289ba12018-11-19 18:28:18 -08001724 }
1725 }
1726
1727 boolean isInChangeTransition() {
1728 return mTransitChangeLeash != null || isChangeTransition(mTransit);
1729 }
1730
Evan Rosky966759f2019-01-15 10:33:58 -08001731 @VisibleForTesting
1732 AppWindowThumbnail getThumbnail() {
1733 return mThumbnail;
1734 }
1735
Riddle Hsub398da32019-01-21 21:48:16 +08001736 /**
1737 * Calculates the scale and offset to horizontal center the size compatibility bounds into the
1738 * region which is available to application.
1739 */
1740 private void calculateCompatBoundsTransformation(Configuration newParentConfig) {
1741 final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds();
1742 final Rect viewportBounds = parentAppBounds != null
1743 ? parentAppBounds : newParentConfig.windowConfiguration.getBounds();
1744 final Rect contentBounds = getResolvedOverrideBounds();
1745 final float contentW = contentBounds.width();
1746 final float contentH = contentBounds.height();
1747 final float viewportW = viewportBounds.width();
1748 final float viewportH = viewportBounds.height();
1749 // Only allow to scale down.
1750 mSizeCompatScale = (contentW <= viewportW && contentH <= viewportH)
1751 ? 1 : Math.min(viewportW / contentW, viewportH / contentH);
1752 final int offsetX = (int) ((viewportW - contentW * mSizeCompatScale + 1) * 0.5f)
1753 + viewportBounds.left;
1754
1755 if (mSizeCompatBounds == null) {
1756 mSizeCompatBounds = new Rect();
1757 }
1758 mSizeCompatBounds.set(contentBounds);
1759 mSizeCompatBounds.offsetTo(0, 0);
1760 mSizeCompatBounds.scale(mSizeCompatScale);
1761 mSizeCompatBounds.left += offsetX;
1762 mSizeCompatBounds.right += offsetX;
1763 }
1764
1765 @Override
1766 public Rect getBounds() {
1767 if (mSizeCompatBounds != null) {
1768 return mSizeCompatBounds;
1769 }
1770 return super.getBounds();
1771 }
1772
1773 @Override
1774 public boolean matchParentBounds() {
1775 if (super.matchParentBounds()) {
1776 return true;
1777 }
1778 // An activity in size compatibility mode may have override bounds which equals to its
1779 // parent bounds, so the exact bounds should also be checked.
1780 final WindowContainer parent = getParent();
1781 return parent == null || parent.getBounds().equals(getResolvedOverrideBounds());
1782 }
1783
Winson Chunge55c0192017-08-24 14:50:48 -07001784 @Override
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001785 void checkAppWindowsReadyToShow() {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001786 if (allDrawn == mLastAllDrawn) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001787 return;
1788 }
1789
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001790 mLastAllDrawn = allDrawn;
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001791 if (!allDrawn) {
1792 return;
1793 }
1794
1795 // The token has now changed state to having all windows shown... what to do, what to do?
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001796 if (mFreezingScreen) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001797 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001798 stopFreezingScreen(false, true);
1799 if (DEBUG_ORIENTATION) Slog.i(TAG,
1800 "Setting mOrientationChangeComplete=true because wtoken " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001801 + " numInteresting=" + mNumInterestingWindows + " numDrawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001802 // This will set mOrientationChangeComplete and cause a pass through layout.
1803 setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001804 "checkAppWindowsReadyToShow: freezingScreen");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001805 } else {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001806 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001807
1808 // We can now show all of the drawn windows!
lumark588a3e82018-07-20 18:53:54 +08001809 if (!getDisplayContent().mOpeningApps.contains(this) && canShowWindows()) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001810 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001811 }
1812 }
1813 }
1814
Matthew Ng5d23afa2017-06-21 16:16:24 -07001815 /**
Bryce Leed390deb2017-06-22 13:14:28 -07001816 * Returns whether the drawn window states of this {@link AppWindowToken} has considered every
1817 * child {@link WindowState}. A child is considered if it has been passed into
1818 * {@link #updateDrawnWindowStates(WindowState)} after being added. This is used to determine
1819 * whether states, such as {@code allDrawn}, can be set, which relies on state variables such as
1820 * {@code mNumInterestingWindows}, which depend on all {@link WindowState}s being considered.
1821 *
1822 * @return {@code true} If all children have been considered, {@code false}.
1823 */
1824 private boolean allDrawnStatesConsidered() {
Bryce Lee6311c4b2017-07-06 14:09:29 -07001825 for (int i = mChildren.size() - 1; i >= 0; --i) {
1826 final WindowState child = mChildren.get(i);
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001827 if (child.mightAffectAllDrawn() && !child.getDrawnStateEvaluated()) {
Bryce Leed390deb2017-06-22 13:14:28 -07001828 return false;
1829 }
1830 }
1831 return true;
1832 }
1833
1834 /**
Matthew Ng5d23afa2017-06-21 16:16:24 -07001835 * Determines if the token has finished drawing. This should only be called from
1836 * {@link DisplayContent#applySurfaceChangesTransaction}
1837 */
Matthew Ng498c71d2017-04-18 13:55:45 -07001838 void updateAllDrawn() {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001839 if (!allDrawn) {
Matthew Ng498c71d2017-04-18 13:55:45 -07001840 // Number of drawn windows can be less when a window is being relaunched, wait for
Bryce Leed390deb2017-06-22 13:14:28 -07001841 // all windows to be launched and drawn for this token be considered all drawn.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001842 final int numInteresting = mNumInterestingWindows;
Bryce Leed390deb2017-06-22 13:14:28 -07001843
1844 // We must make sure that all present children have been considered (determined by
1845 // {@link #allDrawnStatesConsidered}) before evaluating whether everything has been
1846 // drawn.
1847 if (numInteresting > 0 && allDrawnStatesConsidered()
1848 && mNumDrawnWindows >= numInteresting && !isRelaunching()) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001849 if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawn: " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001850 + " interesting=" + numInteresting + " drawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001851 allDrawn = true;
1852 // Force an additional layout pass where
1853 // WindowStateAnimator#commitFinishDrawingLocked() will call performShowLocked().
Matthew Ng498c71d2017-04-18 13:55:45 -07001854 if (mDisplayContent != null) {
1855 mDisplayContent.setLayoutNeeded();
1856 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001857 mWmService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
Robert Carrecc06b32017-04-18 14:25:10 -07001858
Winson Chunge7ba6862017-05-24 12:13:33 -07001859 // Notify the pinned stack upon all windows drawn. If there was an animation in
1860 // progress then this signal will resume that animation.
Wale Ogunwale61911492017-10-11 08:50:50 -07001861 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
Winson Chunge7ba6862017-05-24 12:13:33 -07001862 if (pinnedStack != null) {
1863 pinnedStack.onAllWindowsDrawn();
Robert Carrecc06b32017-04-18 14:25:10 -07001864 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001865 }
1866 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001867 }
1868
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001869 boolean keyDispatchingTimedOut(String reason, int windowPid) {
1870 return mActivityRecord != null && mActivityRecord.keyDispatchingTimedOut(reason, windowPid);
1871 }
1872
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001873 /**
1874 * Updated this app token tracking states for interesting and drawn windows based on the window.
1875 *
1876 * @return Returns true if the input window is considered interesting and drawn while all the
1877 * windows in this app token where not considered drawn as of the last pass.
1878 */
1879 boolean updateDrawnWindowStates(WindowState w) {
Bryce Leed390deb2017-06-22 13:14:28 -07001880 w.setDrawnStateEvaluated(true /*evaluated*/);
1881
Jorim Jaggie4b0f282017-05-17 15:10:29 +02001882 if (DEBUG_STARTING_WINDOW_VERBOSE && w == startingWindow) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001883 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + w.isOnScreen()
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001884 + " allDrawn=" + allDrawn + " freezingScreen=" + mFreezingScreen);
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001885 }
1886
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001887 if (allDrawn && !mFreezingScreen) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001888 return false;
1889 }
1890
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001891 if (mLastTransactionSequence != mWmService.mTransactionSequence) {
1892 mLastTransactionSequence = mWmService.mTransactionSequence;
Matthew Ng53e66b22018-01-12 17:13:13 -08001893 mNumDrawnWindows = 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001894 startingDisplayed = false;
Matthew Ng53e66b22018-01-12 17:13:13 -08001895
1896 // There is the main base application window, even if it is exiting, wait for it
1897 mNumInterestingWindows = findMainWindow(false /* includeStartingApp */) != null ? 1 : 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001898 }
1899
1900 final WindowStateAnimator winAnimator = w.mWinAnimator;
1901
1902 boolean isInterestingAndDrawn = false;
1903
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001904 if (!allDrawn && w.mightAffectAllDrawn()) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001905 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
1906 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001907 + ", isAnimationSet=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001908 if (!w.isDrawnLw()) {
1909 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController
1910 + " pv=" + w.mPolicyVisibility
1911 + " mDrawState=" + winAnimator.drawStateToString()
1912 + " ph=" + w.isParentWindowHidden() + " th=" + hiddenRequested
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001913 + " a=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001914 }
1915 }
1916
1917 if (w != startingWindow) {
1918 if (w.isInteresting()) {
Matthew Ng53e66b22018-01-12 17:13:13 -08001919 // Add non-main window as interesting since the main app has already been added
1920 if (findMainWindow(false /* includeStartingApp */) != w) {
1921 mNumInterestingWindows++;
1922 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001923 if (w.isDrawnLw()) {
1924 mNumDrawnWindows++;
1925
1926 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, "tokenMayBeDrawn: "
1927 + this + " w=" + w + " numInteresting=" + mNumInterestingWindows
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001928 + " freezingScreen=" + mFreezingScreen
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001929 + " mAppFreezing=" + w.mAppFreezing);
1930
1931 isInterestingAndDrawn = true;
1932 }
1933 }
1934 } else if (w.isDrawnLw()) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001935 if (mActivityRecord != null) {
1936 mActivityRecord.onStartingWindowDrawn(SystemClock.uptimeMillis());
Jorim Jaggi3878ca32017-02-02 17:13:05 -08001937 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001938 startingDisplayed = true;
1939 }
1940 }
1941
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001942 return isInterestingAndDrawn;
1943 }
1944
Adrian Roos23df3a32018-03-15 15:41:13 +01001945 void layoutLetterbox(WindowState winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001946 final WindowState w = findMainWindow();
Adrian Roosf93b6d22018-03-21 13:48:26 +01001947 if (w == null || winHint != null && w != winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001948 return;
1949 }
Jorim Jaggia32da382018-03-28 18:01:22 +02001950 final boolean surfaceReady = w.isDrawnLw() // Regular case
Adrian Roosf93b6d22018-03-21 13:48:26 +01001951 || w.mWinAnimator.mSurfaceDestroyDeferred // The preserved surface is still ready.
1952 || w.isDragResizeChanged(); // Waiting for relayoutWindow to call preserveSurface.
1953 final boolean needsLetterbox = w.isLetterboxedAppWindow() && fillsParent() && surfaceReady;
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001954 if (needsLetterbox) {
1955 if (mLetterbox == null) {
1956 mLetterbox = new Letterbox(() -> makeChildSurface(null));
Riddle Hsu192fe762019-01-15 23:41:57 +08001957 mLetterbox.attachInput(w);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001958 }
Adrian Roos7af9d972018-11-30 15:26:27 +01001959 getPosition(mTmpPoint);
1960 mLetterbox.layout(getParent().getBounds(), w.getFrameLw(), mTmpPoint);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001961 } else if (mLetterbox != null) {
Adrian Roos23df3a32018-03-15 15:41:13 +01001962 mLetterbox.hide();
1963 }
1964 }
1965
1966 void updateLetterboxSurface(WindowState winHint) {
1967 final WindowState w = findMainWindow();
1968 if (w != winHint && winHint != null && w != null) {
1969 return;
1970 }
1971 layoutLetterbox(winHint);
1972 if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) {
1973 mLetterbox.applySurfaceChanges(mPendingTransaction);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001974 }
1975 }
1976
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001977 @Override
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001978 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001979 // For legacy reasons we process the TaskStack.mExitingAppTokens first in DisplayContent
1980 // before the non-exiting app tokens. So, we skip the exiting app tokens here.
1981 // TODO: Investigate if we need to continue to do this or if we can just process them
1982 // in-order.
1983 if (mIsExiting && !waitingForReplacement()) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001984 return false;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001985 }
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001986 return forAllWindowsUnchecked(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001987 }
1988
lumark588a3e82018-07-20 18:53:54 +08001989 @Override
1990 void forAllAppWindows(Consumer<AppWindowToken> callback) {
1991 callback.accept(this);
1992 }
1993
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001994 boolean forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback,
1995 boolean traverseTopToBottom) {
1996 return super.forAllWindows(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001997 }
1998
1999 @Override
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002000 AppWindowToken asAppWindowToken() {
2001 // I am an app window token!
2002 return this;
2003 }
2004
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002005 boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
2006 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
2007 IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
2008 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
2009 // If the display is frozen, we won't do anything until the actual window is
2010 // displayed so there is no reason to put in the starting window.
2011 if (!okToDisplay()) {
2012 return false;
2013 }
2014
2015 if (startingData != null) {
2016 return false;
2017 }
2018
2019 final WindowState mainWin = findMainWindow();
2020 if (mainWin != null && mainWin.mWinAnimator.getShown()) {
2021 // App already has a visible window...why would you want a starting window?
2022 return false;
2023 }
2024
2025 final ActivityManager.TaskSnapshot snapshot =
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002026 mWmService.mTaskSnapshotController.getSnapshot(
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002027 getTask().mTaskId, getTask().mUserId,
2028 false /* restoreFromDisk */, false /* reducedResolution */);
2029 final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
2030 allowTaskSnapshot, activityCreated, fromRecents, snapshot);
2031
2032 if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
2033 return createSnapshot(snapshot);
2034 }
2035
2036 // If this is a translucent window, then don't show a starting window -- the current
2037 // effect (a full-screen opaque starting window that fades away to the real contents
2038 // when it is ready) does not work for this.
2039 if (DEBUG_STARTING_WINDOW) {
2040 Slog.v(TAG, "Checking theme of starting window: 0x" + Integer.toHexString(theme));
2041 }
2042 if (theme != 0) {
2043 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
2044 com.android.internal.R.styleable.Window,
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002045 mWmService.mCurrentUserId);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002046 if (ent == null) {
2047 // Whoops! App doesn't exist. Um. Okay. We'll just pretend like we didn't
2048 // see that.
2049 return false;
2050 }
2051 final boolean windowIsTranslucent = ent.array.getBoolean(
2052 com.android.internal.R.styleable.Window_windowIsTranslucent, false);
2053 final boolean windowIsFloating = ent.array.getBoolean(
2054 com.android.internal.R.styleable.Window_windowIsFloating, false);
2055 final boolean windowShowWallpaper = ent.array.getBoolean(
2056 com.android.internal.R.styleable.Window_windowShowWallpaper, false);
2057 final boolean windowDisableStarting = ent.array.getBoolean(
2058 com.android.internal.R.styleable.Window_windowDisablePreview, false);
2059 if (DEBUG_STARTING_WINDOW) {
2060 Slog.v(TAG, "Translucent=" + windowIsTranslucent
2061 + " Floating=" + windowIsFloating
2062 + " ShowWallpaper=" + windowShowWallpaper);
2063 }
2064 if (windowIsTranslucent) {
2065 return false;
2066 }
2067 if (windowIsFloating || windowDisableStarting) {
2068 return false;
2069 }
2070 if (windowShowWallpaper) {
2071 if (getDisplayContent().mWallpaperController
2072 .getWallpaperTarget() == null) {
2073 // If this theme is requesting a wallpaper, and the wallpaper
2074 // is not currently visible, then this effectively serves as
2075 // an opaque window and our starting window transition animation
2076 // can still work. We just need to make sure the starting window
2077 // is also showing the wallpaper.
2078 windowFlags |= FLAG_SHOW_WALLPAPER;
2079 } else {
2080 return false;
2081 }
2082 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002083 }
Yunfan Chen8a8c0ed2018-12-18 16:46:32 -08002084
2085 if (transferStartingWindow(transferFrom)) {
2086 return true;
2087 }
2088
2089 // There is no existing starting window, and we don't want to create a splash screen, so
2090 // that's it!
2091 if (type != STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
2092 return false;
2093 }
2094
2095 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SplashScreenStartingData");
2096 startingData = new SplashScreenStartingData(mWmService, pkg,
2097 theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
2098 getMergedOverrideConfiguration());
2099 scheduleAddStartingWindow();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002100 return true;
2101 }
2102
2103
2104 private boolean createSnapshot(ActivityManager.TaskSnapshot snapshot) {
2105 if (snapshot == null) {
2106 return false;
2107 }
2108
2109 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SnapshotStartingData");
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002110 startingData = new SnapshotStartingData(mWmService, snapshot);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002111 scheduleAddStartingWindow();
2112 return true;
2113 }
2114
2115 void scheduleAddStartingWindow() {
2116 // Note: we really want to do sendMessageAtFrontOfQueue() because we
2117 // want to process the message ASAP, before any other queued
2118 // messages.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002119 if (!mWmService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002120 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING");
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002121 mWmService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002122 }
2123 }
2124
2125 private final Runnable mAddStartingWindow = new Runnable() {
2126
2127 @Override
2128 public void run() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002129 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002130 // There can only be one adding request, silly caller!
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002131 mWmService.mAnimationHandler.removeCallbacks(this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002132 }
2133
2134 if (startingData == null) {
2135 // Animation has been canceled... do nothing.
2136 if (DEBUG_STARTING_WINDOW) {
2137 Slog.v(TAG, "startingData was nulled out before handling"
2138 + " mAddStartingWindow: " + AppWindowToken.this);
2139 }
2140 return;
2141 }
2142
2143 if (DEBUG_STARTING_WINDOW) {
2144 Slog.v(TAG, "Add starting " + this + ": startingData=" + startingData);
2145 }
2146
2147 WindowManagerPolicy.StartingSurface surface = null;
2148 try {
2149 surface = startingData.createStartingSurface(AppWindowToken.this);
2150 } catch (Exception e) {
2151 Slog.w(TAG, "Exception when adding starting window", e);
2152 }
2153 if (surface != null) {
2154 boolean abort = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002155 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002156 // If the window was successfully added, then
2157 // we need to remove it.
2158 if (removed || startingData == null) {
2159 if (DEBUG_STARTING_WINDOW) {
2160 Slog.v(TAG, "Aborted starting " + AppWindowToken.this
2161 + ": removed=" + removed + " startingData=" + startingData);
2162 }
2163 startingWindow = null;
2164 startingData = null;
2165 abort = true;
2166 } else {
2167 startingSurface = surface;
2168 }
2169 if (DEBUG_STARTING_WINDOW && !abort) {
2170 Slog.v(TAG, "Added starting " + AppWindowToken.this + ": startingWindow="
2171 + startingWindow + " startingView=" + startingSurface);
2172 }
2173 }
2174 if (abort) {
2175 surface.remove();
2176 }
2177 } else if (DEBUG_STARTING_WINDOW) {
2178 Slog.v(TAG, "Surface returned was null: " + AppWindowToken.this);
2179 }
2180 }
2181 };
2182
2183 private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
2184 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents,
2185 ActivityManager.TaskSnapshot snapshot) {
2186 if (getDisplayContent().mAppTransition.getAppTransition()
2187 == TRANSIT_DOCK_TASK_FROM_RECENTS) {
2188 // TODO(b/34099271): Remove this statement to add back the starting window and figure
2189 // out why it causes flickering, the starting window appears over the thumbnail while
2190 // the docked from recents transition occurs
2191 return STARTING_WINDOW_TYPE_NONE;
2192 } else if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
2193 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2194 } else if (taskSwitch && allowTaskSnapshot) {
Kevin716a9db2018-12-18 16:53:39 -08002195 if (mWmService.mLowRamTaskSnapshotsAndRecents) {
Kevin58b47f12018-12-17 14:09:01 -08002196 // For low RAM devices, we use the splash screen starting window instead of the
2197 // task snapshot starting window.
2198 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2199 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002200 return snapshot == null ? STARTING_WINDOW_TYPE_NONE
2201 : snapshotOrientationSameAsTask(snapshot) || fromRecents
2202 ? STARTING_WINDOW_TYPE_SNAPSHOT : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2203 } else {
2204 return STARTING_WINDOW_TYPE_NONE;
2205 }
2206 }
2207
2208
2209 private boolean snapshotOrientationSameAsTask(ActivityManager.TaskSnapshot snapshot) {
2210 if (snapshot == null) {
2211 return false;
2212 }
2213 return getTask().getConfiguration().orientation == snapshot.getOrientation();
2214 }
2215
2216 void removeStartingWindow() {
2217 if (startingWindow == null) {
2218 if (startingData != null) {
2219 // Starting window has not been added yet, but it is scheduled to be added.
2220 // Go ahead and cancel the request.
2221 if (DEBUG_STARTING_WINDOW) {
2222 Slog.v(TAG_WM, "Clearing startingData for token=" + this);
2223 }
2224 startingData = null;
2225 }
2226 return;
2227 }
2228
2229 final WindowManagerPolicy.StartingSurface surface;
2230 if (startingData != null) {
2231 surface = startingSurface;
2232 startingData = null;
2233 startingSurface = null;
2234 startingWindow = null;
2235 startingDisplayed = false;
2236 if (surface == null) {
2237 if (DEBUG_STARTING_WINDOW) {
2238 Slog.v(TAG_WM, "startingWindow was set but startingSurface==null, couldn't "
2239 + "remove");
2240 }
2241 return;
2242 }
2243 } else {
2244 if (DEBUG_STARTING_WINDOW) {
2245 Slog.v(TAG_WM, "Tried to remove starting window but startingWindow was null:"
2246 + this);
2247 }
2248 return;
2249 }
2250
2251 if (DEBUG_STARTING_WINDOW) {
2252 Slog.v(TAG_WM, "Schedule remove starting " + this
2253 + " startingWindow=" + startingWindow
2254 + " startingView=" + startingSurface
2255 + " Callers=" + Debug.getCallers(5));
2256 }
2257
2258 // Use the same thread to remove the window as we used to add it, as otherwise we end up
2259 // with things in the view hierarchy being called from different threads.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002260 mWmService.mAnimationHandler.post(() -> {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002261 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Removing startingView=" + surface);
2262 try {
2263 surface.remove();
2264 } catch (Exception e) {
2265 Slog.w(TAG_WM, "Exception when removing starting window", e);
2266 }
2267 });
2268 }
2269
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002270 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -07002271 boolean fillsParent() {
2272 return mFillsParent;
2273 }
2274
2275 void setFillsParent(boolean fillsParent) {
2276 mFillsParent = fillsParent;
2277 }
2278
Jorim Jaggife762342016-10-13 14:33:27 +02002279 boolean containsDismissKeyguardWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002280 // Window state is transient during relaunch. We are not guaranteed to be frozen during the
2281 // entirety of the relaunch.
2282 if (isRelaunching()) {
2283 return mLastContainsDismissKeyguardWindow;
2284 }
2285
Jorim Jaggife762342016-10-13 14:33:27 +02002286 for (int i = mChildren.size() - 1; i >= 0; i--) {
2287 if ((mChildren.get(i).mAttrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
2288 return true;
2289 }
2290 }
2291 return false;
2292 }
2293
2294 boolean containsShowWhenLockedWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002295 // When we are relaunching, it is possible for us to be unfrozen before our previous
2296 // windows have been added back. Using the cached value ensures that our previous
2297 // showWhenLocked preference is honored until relaunching is complete.
2298 if (isRelaunching()) {
2299 return mLastContainsShowWhenLockedWindow;
2300 }
2301
Jorim Jaggife762342016-10-13 14:33:27 +02002302 for (int i = mChildren.size() - 1; i >= 0; i--) {
2303 if ((mChildren.get(i).mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
2304 return true;
2305 }
2306 }
Bryce Lee081554b2017-05-25 07:52:12 -07002307
Jorim Jaggife762342016-10-13 14:33:27 +02002308 return false;
2309 }
2310
2311 void checkKeyguardFlagsChanged() {
2312 final boolean containsDismissKeyguard = containsDismissKeyguardWindow();
2313 final boolean containsShowWhenLocked = containsShowWhenLockedWindow();
2314 if (containsDismissKeyguard != mLastContainsDismissKeyguardWindow
2315 || containsShowWhenLocked != mLastContainsShowWhenLockedWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002316 mWmService.notifyKeyguardFlagsChanged(null /* callback */,
lumark588a3e82018-07-20 18:53:54 +08002317 getDisplayContent().getDisplayId());
Jorim Jaggife762342016-10-13 14:33:27 +02002318 }
2319 mLastContainsDismissKeyguardWindow = containsDismissKeyguard;
2320 mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
2321 }
2322
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002323 WindowState getImeTargetBelowWindow(WindowState w) {
2324 final int index = mChildren.indexOf(w);
2325 if (index > 0) {
2326 final WindowState target = mChildren.get(index - 1);
2327 if (target.canBeImeTarget()) {
2328 return target;
2329 }
2330 }
2331 return null;
2332 }
2333
2334 WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
2335 WindowState candidate = null;
2336 for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
2337 final WindowState w = mChildren.get(i);
2338 if (w.mRemoved) {
2339 continue;
2340 }
Jorim Jaggi35d328a2018-08-14 17:00:20 +02002341 if (candidate == null) {
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002342 candidate = w;
2343 }
2344 }
2345 return candidate;
2346 }
2347
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002348 /**
2349 * See {@link Activity#setDisablePreviewScreenshots}.
2350 */
2351 void setDisablePreviewScreenshots(boolean disable) {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002352 mDisablePreviewScreenshots = disable;
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002353 }
2354
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002355 /**
chaviwd3bf08d2017-08-01 17:24:59 -07002356 * Sets whether the current launch can turn the screen on. See {@link #canTurnScreenOn()}
2357 */
2358 void setCanTurnScreenOn(boolean canTurnScreenOn) {
2359 mCanTurnScreenOn = canTurnScreenOn;
2360 }
2361
2362 /**
2363 * Indicates whether the current launch can turn the screen on. This is to prevent multiple
2364 * relayouts from turning the screen back on. The screen should only turn on at most
2365 * once per activity resume.
2366 *
2367 * @return true if the screen can be turned on.
2368 */
2369 boolean canTurnScreenOn() {
2370 return mCanTurnScreenOn;
2371 }
2372
2373 /**
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002374 * Retrieves whether we'd like to generate a snapshot that's based solely on the theme. This is
2375 * the case when preview screenshots are disabled {@link #setDisablePreviewScreenshots} or when
2376 * we can't take a snapshot for other reasons, for example, if we have a secure window.
2377 *
2378 * @return True if we need to generate an app theme snapshot, false if we'd like to take a real
2379 * screenshot.
2380 */
2381 boolean shouldUseAppThemeSnapshot() {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002382 return mDisablePreviewScreenshots || forAllWindows(w -> (w.mAttrs.flags & FLAG_SECURE) != 0,
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002383 true /* topToBottom */);
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002384 }
2385
Jorim Jaggibe418292018-03-26 16:14:12 +02002386 SurfaceControl getAppAnimationLayer() {
Jorim Jaggi391790622018-04-18 15:30:44 +02002387 return getAppAnimationLayer(isActivityTypeHome() ? ANIMATION_LAYER_HOME
2388 : needsZBoost() ? ANIMATION_LAYER_BOOSTED
2389 : ANIMATION_LAYER_STANDARD);
Jorim Jaggibe418292018-03-26 16:14:12 +02002390 }
2391
chaviw23ee71c2017-12-18 11:29:41 -08002392 @Override
Jorim Jaggi596a1992017-12-29 14:48:02 +01002393 public SurfaceControl getAnimationLeashParent() {
Robert Carrb9506032018-02-13 13:54:00 -08002394 // All normal app transitions take place in an animation layer which is below the pinned
2395 // stack but may be above the parent stacks of the given animating apps.
2396 // For transitions in the pinned stack (menu activity) we just let them occur as a child
2397 // of the pinned stack.
2398 if (!inPinnedWindowingMode()) {
2399 return getAppAnimationLayer();
2400 } else {
2401 return getStack().getSurfaceControl();
2402 }
chaviw23ee71c2017-12-18 11:29:41 -08002403 }
2404
Jorim Jaggic6976f02018-04-18 16:31:07 +02002405 private boolean shouldAnimate(int transit) {
2406 final boolean isSplitScreenPrimary =
2407 getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
2408 final boolean allowSplitScreenPrimaryAnimation = transit != TRANSIT_WALLPAPER_OPEN;
2409
2410 // We animate always if it's not split screen primary, and only some special cases in split
2411 // screen primary because it causes issues with stack clipping when we run an un-minimize
2412 // animation at the same time.
2413 return !isSplitScreenPrimary || allowSplitScreenPrimaryAnimation;
2414 }
2415
Vishnu Naira2977262018-07-26 13:31:26 -07002416 /**
2417 * Creates a layer to apply crop to an animation.
2418 */
2419 private SurfaceControl createAnimationBoundsLayer(Transaction t) {
2420 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.i(TAG, "Creating animation bounds layer");
2421 final SurfaceControl.Builder builder = makeAnimationLeash()
2422 .setParent(getAnimationLeashParent())
Vishnu Naire86bd982018-11-28 13:23:17 -08002423 .setName(getSurfaceControl() + " - animation-bounds");
Vishnu Naira2977262018-07-26 13:31:26 -07002424 final SurfaceControl boundsLayer = builder.build();
2425 t.show(boundsLayer);
2426 return boundsLayer;
2427 }
2428
Riddle Hsua118b3a2018-10-11 22:05:06 +08002429 /** Get position and crop region of animation. */
2430 @VisibleForTesting
2431 void getAnimationBounds(Point outPosition, Rect outBounds) {
2432 outPosition.set(0, 0);
2433 outBounds.setEmpty();
2434
2435 final TaskStack stack = getStack();
2436 final Task task = getTask();
2437 if (task != null && task.inFreeformWindowingMode()) {
Evan Roskyed6767f2018-10-26 17:21:06 -07002438 task.getRelativeDisplayedPosition(outPosition);
Riddle Hsua118b3a2018-10-11 22:05:06 +08002439 } else if (stack != null) {
Evan Roskyed6767f2018-10-26 17:21:06 -07002440 stack.getRelativeDisplayedPosition(outPosition);
Riddle Hsua118b3a2018-10-11 22:05:06 +08002441 }
2442
2443 // Always use stack bounds in order to have the ability to animate outside the task region.
2444 // It also needs to be consistent when {@link #mNeedsAnimationBoundsLayer} is set that crops
2445 // according to the bounds.
2446 if (stack != null) {
2447 stack.getBounds(outBounds);
2448 }
2449 // We have the relative position so the local position can be removed from bounds.
2450 outBounds.offsetTo(0, 0);
2451 }
2452
Evan Roskyed6767f2018-10-26 17:21:06 -07002453 @Override
2454 Rect getDisplayedBounds() {
2455 final Task task = getTask();
2456 if (task != null) {
2457 final Rect overrideDisplayedBounds = task.getOverrideDisplayedBounds();
2458 if (!overrideDisplayedBounds.isEmpty()) {
2459 return overrideDisplayedBounds;
2460 }
2461 }
2462 return getBounds();
2463 }
2464
Evan Rosky2289ba12018-11-19 18:28:18 -08002465 private static boolean isChangeTransition(int transit) {
2466 return transit == TRANSIT_TASK_CHANGE_WINDOWING_MODE;
2467 }
2468
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002469 boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter,
2470 boolean isVoiceInteraction) {
2471
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002472 if (mWmService.mDisableTransitionAnimation || !shouldAnimate(transit)) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002473 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
Jorim Jaggic6976f02018-04-18 16:31:07 +02002474 Slog.v(TAG_WM, "applyAnimation: transition animation is disabled or skipped."
2475 + " atoken=" + this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002476 }
2477 cancelAnimation();
2478 return false;
2479 }
2480
2481 // Only apply an animation if the display isn't frozen. If it is frozen, there is no reason
2482 // to animate and it can cause strange artifacts when we unfreeze the display if some
2483 // different animation is running.
2484 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#applyAnimationLocked");
2485 if (okToAnimate()) {
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002486 final AnimationAdapter adapter;
Evan Rosky2289ba12018-11-19 18:28:18 -08002487 AnimationAdapter thumbnailAdapter = null;
Riddle Hsua118b3a2018-10-11 22:05:06 +08002488 getAnimationBounds(mTmpPoint, mTmpRect);
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002489
Evan Rosky966759f2019-01-15 10:33:58 -08002490 boolean isChanging = isChangeTransition(transit) && enter;
Evan Rosky2289ba12018-11-19 18:28:18 -08002491
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002492 // Delaying animation start isn't compatible with remote animations at all.
lumark588a3e82018-07-20 18:53:54 +08002493 if (getDisplayContent().mAppTransition.getRemoteAnimationController() != null
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002494 && !mSurfaceAnimator.isAnimationStartDelayed()) {
Evan Rosky2289ba12018-11-19 18:28:18 -08002495 RemoteAnimationRecord adapters =
2496 getDisplayContent().mAppTransition.getRemoteAnimationController()
2497 .createRemoteAnimationRecord(this, mTmpPoint, mTmpRect,
2498 (isChanging ? mTransitStartRect : null));
2499 adapter = adapters.mAdapter;
2500 thumbnailAdapter = adapters.mThumbnailAdapter;
2501 } else if (isChanging) {
Evan Roskycf76bed2019-01-15 10:33:58 -08002502 final float durationScale = mWmService.getTransitionAnimationScaleLocked();
Evan Rosky2289ba12018-11-19 18:28:18 -08002503 mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y);
2504 adapter = new LocalAnimationAdapter(
2505 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
Evan Roskycf76bed2019-01-15 10:33:58 -08002506 getDisplayContent().getDisplayInfo(), durationScale,
Evan Rosky2289ba12018-11-19 18:28:18 -08002507 true /* isAppAnimation */, false /* isThumbnail */),
2508 mWmService.mSurfaceAnimationRunner);
Evan Rosky966759f2019-01-15 10:33:58 -08002509 if (mThumbnail != null) {
2510 thumbnailAdapter = new LocalAnimationAdapter(
2511 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
Evan Roskycf76bed2019-01-15 10:33:58 -08002512 getDisplayContent().getDisplayInfo(), durationScale,
Evan Rosky966759f2019-01-15 10:33:58 -08002513 true /* isAppAnimation */, true /* isThumbnail */),
2514 mWmService.mSurfaceAnimationRunner);
2515 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002516 mTransit = transit;
2517 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002518 } else {
lumark588a3e82018-07-20 18:53:54 +08002519 final int appStackClipMode =
2520 getDisplayContent().mAppTransition.getAppStackClipMode();
Vishnu Naira2977262018-07-26 13:31:26 -07002521 mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM);
2522
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002523 final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
2524 if (a != null) {
2525 adapter = new LocalAnimationAdapter(
2526 new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
lumark588a3e82018-07-20 18:53:54 +08002527 getDisplayContent().mAppTransition.canSkipFirstFrame(),
Vishnu Naira2977262018-07-26 13:31:26 -07002528 appStackClipMode,
Lucas Dupin3e1dc202018-12-02 15:14:20 -08002529 true /* isAppAnimation */,
2530 mWmService.mWindowCornerRadius),
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002531 mWmService.mSurfaceAnimationRunner);
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002532 if (a.getZAdjustment() == Animation.ZORDER_TOP) {
2533 mNeedsZBoost = true;
2534 }
2535 mTransit = transit;
lumark588a3e82018-07-20 18:53:54 +08002536 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002537 } else {
2538 adapter = null;
chaviw23ee71c2017-12-18 11:29:41 -08002539 }
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002540 }
2541 if (adapter != null) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002542 startAnimation(getPendingTransaction(), adapter, !isVisible());
Jorim Jaggi82c17862018-02-21 17:50:18 +01002543 if (adapter.getShowWallpaper()) {
2544 mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2545 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002546 if (thumbnailAdapter != null) {
2547 mThumbnail.startAnimation(
2548 getPendingTransaction(), thumbnailAdapter, !isVisible());
2549 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002550 }
2551 } else {
2552 cancelAnimation();
2553 }
2554 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2555
2556 return isReallyAnimating();
2557 }
2558
2559 private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
2560 boolean isVoiceInteraction) {
2561 final DisplayContent displayContent = getTask().getDisplayContent();
2562 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2563 final int width = displayInfo.appWidth;
2564 final int height = displayInfo.appHeight;
2565 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG_WM,
2566 "applyAnimation: atoken=" + this);
2567
2568 // Determine the visible rect to calculate the thumbnail clip
2569 final WindowState win = findMainWindow();
2570 final Rect frame = new Rect(0, 0, width, height);
2571 final Rect displayFrame = new Rect(0, 0,
2572 displayInfo.logicalWidth, displayInfo.logicalHeight);
2573 final Rect insets = new Rect();
2574 final Rect stableInsets = new Rect();
2575 Rect surfaceInsets = null;
2576 final boolean freeform = win != null && win.inFreeformWindowingMode();
2577 if (win != null) {
2578 // Containing frame will usually cover the whole screen, including dialog windows.
2579 // For freeform workspace windows it will not cover the whole screen and it also
2580 // won't exactly match the final freeform window frame (e.g. when overlapping with
2581 // the status bar). In that case we need to use the final frame.
2582 if (freeform) {
chaviw492139a2018-07-16 16:07:35 -07002583 frame.set(win.getFrameLw());
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002584 } else if (win.isLetterboxedAppWindow()) {
2585 frame.set(getTask().getBounds());
Winson Chungc1674272018-02-21 10:15:17 -08002586 } else if (win.isDockedResizing()) {
2587 // If we are animating while docked resizing, then use the stack bounds as the
2588 // animation target (which will be different than the task bounds)
2589 frame.set(getTask().getParent().getBounds());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002590 } else {
chaviw553b0212018-07-12 13:37:01 -07002591 frame.set(win.getContainingFrame());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002592 }
2593 surfaceInsets = win.getAttrs().surfaceInsets;
Adrian Roos20e07892018-02-23 19:12:01 +01002594 // XXX(b/72757033): These are insets relative to the window frame, but we're really
2595 // interested in the insets relative to the frame we chose in the if-blocks above.
chaviw9c81e632018-07-31 11:17:52 -07002596 win.getContentInsets(insets);
2597 win.getStableInsets(stableInsets);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002598 }
2599
2600 if (mLaunchTaskBehind) {
2601 // Differentiate the two animations. This one which is briefly on the screen
2602 // gets the !enter animation, and the other activity which remains on the
2603 // screen gets the enter animation. Both appear in the mOpeningApps set.
2604 enter = false;
2605 }
2606 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "Loading animation for app transition."
2607 + " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter
2608 + " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets);
2609 final Configuration displayConfig = displayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08002610 final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002611 displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
2612 surfaceInsets, stableInsets, isVoiceInteraction, freeform, getTask().mTaskId);
2613 if (a != null) {
2614 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
2615 final int containingWidth = frame.width();
2616 final int containingHeight = frame.height();
2617 a.initialize(containingWidth, containingHeight, width, height);
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002618 a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002619 }
2620 return a;
2621 }
2622
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002623 @Override
Jorim Jaggi6de61012018-03-19 14:53:23 +01002624 public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
2625 return mAnimatingAppWindowTokenRegistry != null
2626 && mAnimatingAppWindowTokenRegistry.notifyAboutToFinish(
2627 this, endDeferFinishCallback);
2628 }
2629
2630 @Override
2631 public void onAnimationLeashDestroyed(Transaction t) {
2632 super.onAnimationLeashDestroyed(t);
Vishnu Naira2977262018-07-26 13:31:26 -07002633 if (mAnimationBoundsLayer != null) {
Robert Carr71200f22019-02-05 09:44:53 -08002634 t.remove(mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002635 mAnimationBoundsLayer = null;
2636 }
2637
Jorim Jaggi6de61012018-03-19 14:53:23 +01002638 if (mAnimatingAppWindowTokenRegistry != null) {
2639 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
2640 }
2641 }
2642
2643 @Override
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002644 protected void setLayer(Transaction t, int layer) {
2645 if (!mSurfaceAnimator.hasLeash()) {
2646 t.setLayer(mSurfaceControl, layer);
2647 }
2648 }
2649
2650 @Override
2651 protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
2652 if (!mSurfaceAnimator.hasLeash()) {
2653 t.setRelativeLayer(mSurfaceControl, relativeTo, layer);
2654 }
2655 }
2656
2657 @Override
2658 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
2659 if (!mSurfaceAnimator.hasLeash()) {
Robert Carr10584fa2019-01-14 15:55:19 -08002660 t.reparent(mSurfaceControl, newParent);
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002661 }
2662 }
2663
2664 @Override
2665 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002666 // The leash is parented to the animation layer. We need to preserve the z-order by using
2667 // the prefix order index, but we boost if necessary.
Robert Carrb9506032018-02-13 13:54:00 -08002668 int layer = 0;
2669 if (!inPinnedWindowingMode()) {
2670 layer = getPrefixOrderIndex();
2671 } else {
2672 // Pinned stacks have animations take place within themselves rather than an animation
2673 // layer so we need to preserve the order relative to the stack (e.g. the order of our
2674 // task/parent).
2675 layer = getParent().getPrefixOrderIndex();
2676 }
2677
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002678 if (mNeedsZBoost) {
2679 layer += Z_BOOST_BASE;
2680 }
2681 leash.setLayer(layer);
Robert Carr2f8aa392018-01-31 14:46:51 -08002682
2683 final DisplayContent dc = getDisplayContent();
Jorim Jaggibe418292018-03-26 16:14:12 +02002684 dc.assignStackOrdering();
Evan Rosky2289ba12018-11-19 18:28:18 -08002685
2686 if (leash == mTransitChangeLeash) {
2687 // This is a temporary state so skip any animation notifications
2688 return;
2689 } else if (mTransitChangeLeash != null) {
2690 // unparent mTransitChangeLeash for clean-up
Evan Rosky25b56192019-02-06 16:10:56 -08002691 clearChangeLeash(t, false /* cancel */);
Evan Rosky2289ba12018-11-19 18:28:18 -08002692 }
2693
Jorim Jaggi6de61012018-03-19 14:53:23 +01002694 if (mAnimatingAppWindowTokenRegistry != null) {
2695 mAnimatingAppWindowTokenRegistry.notifyStarting(this);
2696 }
Vishnu Naira2977262018-07-26 13:31:26 -07002697
2698 // If the animation needs to be cropped then an animation bounds layer is created as a child
2699 // of the pinned stack or animation layer. The leash is then reparented to this new layer.
2700 if (mNeedsAnimationBoundsLayer) {
2701 final TaskStack stack = getStack();
2702 if (stack == null) {
2703 return;
2704 }
2705 mAnimationBoundsLayer = createAnimationBoundsLayer(t);
2706
2707 // Set clip rect to stack bounds.
2708 mTmpRect.setEmpty();
2709 stack.getBounds(mTmpRect);
2710
2711 // Crop to stack bounds.
2712 t.setWindowCrop(mAnimationBoundsLayer, mTmpRect);
2713
2714 // Reparent leash to animation bounds layer.
Robert Carr10584fa2019-01-14 15:55:19 -08002715 t.reparent(leash, mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002716 }
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002717 }
2718
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002719 /**
2720 * This must be called while inside a transaction.
2721 */
2722 void showAllWindowsLocked() {
2723 forAllWindows(windowState -> {
2724 if (DEBUG_VISIBILITY) Slog.v(TAG, "performing show on: " + windowState);
2725 windowState.performShowLocked();
2726 }, false /* traverseTopToBottom */);
Jorim Jaggia5e10572017-11-15 14:36:26 +01002727 }
2728
2729 @Override
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002730 protected void onAnimationFinished() {
2731 super.onAnimationFinished();
2732
2733 mTransit = TRANSIT_UNSET;
2734 mTransitFlags = 0;
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002735 mNeedsZBoost = false;
Vishnu Naira2977262018-07-26 13:31:26 -07002736 mNeedsAnimationBoundsLayer = false;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002737
2738 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER,
2739 "AppWindowToken");
2740
Jorim Jaggi988f6682017-11-17 17:46:43 +01002741 clearThumbnail();
Jorim Jaggi752cd822018-03-29 16:29:18 +02002742 setClientHidden(isHidden() && hiddenRequested);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002743
lumarkff0ab692018-11-05 20:32:30 +08002744 getDisplayContent().computeImeTargetIfNeeded(this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002745
2746 if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + this
2747 + ": reportedVisible=" + reportedVisible
2748 + " okToDisplay=" + okToDisplay()
2749 + " okToAnimate=" + okToAnimate()
2750 + " startingDisplayed=" + startingDisplayed);
2751
Evan Rosky2289ba12018-11-19 18:28:18 -08002752 // clean up thumbnail window
2753 if (mThumbnail != null) {
2754 mThumbnail.destroy();
2755 mThumbnail = null;
2756 }
2757
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002758 // WindowState.onExitAnimationDone might modify the children list, so make a copy and then
2759 // traverse the copy.
2760 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
2761 children.forEach(WindowState::onExitAnimationDone);
2762
lumark588a3e82018-07-20 18:53:54 +08002763 getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002764 scheduleAnimation();
2765 }
2766
2767 @Override
2768 boolean isAppAnimating() {
2769 return isSelfAnimating();
2770 }
2771
2772 @Override
2773 boolean isSelfAnimating() {
2774 // If we are about to start a transition, we also need to be considered animating.
2775 return isWaitingForTransitionStart() || isReallyAnimating();
2776 }
2777
2778 /**
2779 * @return True if and only if we are actually running an animation. Note that
2780 * {@link #isSelfAnimating} also returns true if we are waiting for an animation to
2781 * start.
2782 */
2783 private boolean isReallyAnimating() {
2784 return super.isSelfAnimating();
2785 }
2786
Evan Rosky25b56192019-02-06 16:10:56 -08002787 /**
2788 * @param cancel {@code true} if clearing the leash due to cancelling instead of transferring
2789 * to another leash.
2790 */
2791 private void clearChangeLeash(Transaction t, boolean cancel) {
2792 if (mTransitChangeLeash == null) {
2793 return;
2794 }
2795 if (cancel) {
2796 clearThumbnail();
2797 SurfaceControl sc = getSurfaceControl();
2798 SurfaceControl parentSc = getParentSurfaceControl();
2799 // Don't reparent if surface is getting destroyed
2800 if (parentSc != null && sc != null) {
2801 t.reparent(sc, getParentSurfaceControl());
2802 }
2803 }
2804 t.hide(mTransitChangeLeash);
2805 t.reparent(mTransitChangeLeash, null);
2806 mTransitChangeLeash = null;
2807 if (cancel) {
2808 onAnimationLeashDestroyed(t);
2809 }
2810 }
2811
Jorim Jaggi988f6682017-11-17 17:46:43 +01002812 @Override
2813 void cancelAnimation() {
Evan Rosky2289ba12018-11-19 18:28:18 -08002814 cancelAnimationOnly();
Jorim Jaggi988f6682017-11-17 17:46:43 +01002815 clearThumbnail();
Evan Rosky25b56192019-02-06 16:10:56 -08002816 clearChangeLeash(getPendingTransaction(), true /* cancel */);
Evan Rosky2289ba12018-11-19 18:28:18 -08002817 }
2818
2819 /**
2820 * This only cancels the animation. It doesn't do other teardown like cleaning-up thumbnail
2821 * or interim leashes.
2822 * <p>
2823 * Used when canceling in preparation for starting a new animation.
2824 */
2825 void cancelAnimationOnly() {
2826 super.cancelAnimation();
Jorim Jaggi988f6682017-11-17 17:46:43 +01002827 }
2828
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002829 boolean isWaitingForTransitionStart() {
lumark588a3e82018-07-20 18:53:54 +08002830 return getDisplayContent().mAppTransition.isTransitionSet()
2831 && (getDisplayContent().mOpeningApps.contains(this)
Evan Rosky2289ba12018-11-19 18:28:18 -08002832 || getDisplayContent().mClosingApps.contains(this)
2833 || getDisplayContent().mChangingApps.contains(this));
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002834 }
2835
2836 public int getTransit() {
2837 return mTransit;
2838 }
2839
2840 int getTransitFlags() {
2841 return mTransitFlags;
2842 }
2843
Jorim Jaggi988f6682017-11-17 17:46:43 +01002844 void attachThumbnailAnimation() {
2845 if (!isReallyAnimating()) {
2846 return;
2847 }
2848 final int taskId = getTask().mTaskId;
2849 final GraphicBuffer thumbnailHeader =
lumark588a3e82018-07-20 18:53:54 +08002850 getDisplayContent().mAppTransition.getAppTransitionThumbnailHeader(taskId);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002851 if (thumbnailHeader == null) {
2852 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG, "No thumbnail header bitmap for: " + taskId);
2853 return;
2854 }
2855 clearThumbnail();
2856 mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnailHeader);
2857 mThumbnail.startAnimation(getPendingTransaction(), loadThumbnailAnimation(thumbnailHeader));
2858 }
2859
Tony Mak64b8d562017-12-28 17:44:02 +00002860 /**
2861 * Attaches a surface with a thumbnail for the
2862 * {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation.
2863 */
2864 void attachCrossProfileAppsThumbnailAnimation() {
2865 if (!isReallyAnimating()) {
2866 return;
2867 }
2868 clearThumbnail();
2869
2870 final WindowState win = findMainWindow();
2871 if (win == null) {
2872 return;
2873 }
chaviw492139a2018-07-16 16:07:35 -07002874 final Rect frame = win.getFrameLw();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002875 final int thumbnailDrawableRes = getTask().mUserId == mWmService.mCurrentUserId
Tony Mak64b8d562017-12-28 17:44:02 +00002876 ? R.drawable.ic_account_circle
Tony Makda4af232018-04-27 11:01:10 +01002877 : R.drawable.ic_corp_badge;
Tony Mak64b8d562017-12-28 17:44:02 +00002878 final GraphicBuffer thumbnail =
lumark588a3e82018-07-20 18:53:54 +08002879 getDisplayContent().mAppTransition
Tony Mak64b8d562017-12-28 17:44:02 +00002880 .createCrossProfileAppsThumbnail(thumbnailDrawableRes, frame);
2881 if (thumbnail == null) {
2882 return;
2883 }
2884 mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnail);
2885 final Animation animation =
lumark588a3e82018-07-20 18:53:54 +08002886 getDisplayContent().mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(
chaviw492139a2018-07-16 16:07:35 -07002887 win.getFrameLw());
Tony Mak64b8d562017-12-28 17:44:02 +00002888 mThumbnail.startAnimation(getPendingTransaction(), animation, new Point(frame.left,
2889 frame.top));
2890 }
2891
Jorim Jaggi988f6682017-11-17 17:46:43 +01002892 private Animation loadThumbnailAnimation(GraphicBuffer thumbnailHeader) {
2893 final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
2894
2895 // If this is a multi-window scenario, we use the windows frame as
2896 // destination of the thumbnail header animation. If this is a full screen
2897 // window scenario, we use the whole display as the target.
2898 WindowState win = findMainWindow();
2899 Rect appRect = win != null ? win.getContentFrameLw() :
2900 new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
chaviw9c81e632018-07-31 11:17:52 -07002901 final Rect insets = win != null ? win.getContentInsets() : null;
Jorim Jaggi988f6682017-11-17 17:46:43 +01002902 final Configuration displayConfig = mDisplayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08002903 return getDisplayContent().mAppTransition.createThumbnailAspectScaleAnimationLocked(
Jorim Jaggi988f6682017-11-17 17:46:43 +01002904 appRect, insets, thumbnailHeader, getTask().mTaskId, displayConfig.uiMode,
2905 displayConfig.orientation);
2906 }
2907
2908 private void clearThumbnail() {
2909 if (mThumbnail == null) {
2910 return;
2911 }
2912 mThumbnail.destroy();
2913 mThumbnail = null;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002914 }
2915
Jorim Jaggif84e2f62018-01-16 14:17:59 +01002916 void registerRemoteAnimations(RemoteAnimationDefinition definition) {
2917 mRemoteAnimationDefinition = definition;
2918 }
2919
2920 RemoteAnimationDefinition getRemoteAnimationDefinition() {
2921 return mRemoteAnimationDefinition;
2922 }
2923
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002924 @Override
2925 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
2926 super.dump(pw, prefix, dumpAll);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002927 if (appToken != null) {
Wale Ogunwale72919d22016-12-08 18:58:50 -08002928 pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002929 }
Winson Chung48b25652018-10-22 14:04:30 -07002930 pw.println(prefix + "component=" + mActivityComponent.flattenToShortString());
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08002931 pw.print(prefix); pw.print("task="); pw.println(getTask());
Wale Ogunwale51362492016-09-08 17:49:17 -07002932 pw.print(prefix); pw.print(" mFillsParent="); pw.print(mFillsParent);
2933 pw.print(" mOrientation="); pw.println(mOrientation);
Wale Ogunwale89973222017-04-23 18:39:45 -07002934 pw.println(prefix + "hiddenRequested=" + hiddenRequested + " mClientHidden=" + mClientHidden
2935 + ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "")
2936 + " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible);
Craig Mautner59431632012-04-04 11:56:44 -07002937 if (paused) {
2938 pw.print(prefix); pw.print("paused="); pw.println(paused);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002939 }
Wale Ogunwale9017ec02016-02-25 08:55:25 -08002940 if (mAppStopped) {
2941 pw.print(prefix); pw.print("mAppStopped="); pw.println(mAppStopped);
2942 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002943 if (mNumInterestingWindows != 0 || mNumDrawnWindows != 0
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002944 || allDrawn || mLastAllDrawn) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002945 pw.print(prefix); pw.print("mNumInterestingWindows=");
2946 pw.print(mNumInterestingWindows);
2947 pw.print(" mNumDrawnWindows="); pw.print(mNumDrawnWindows);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002948 pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
Craig Mautner6fbda632012-07-03 09:26:39 -07002949 pw.print(" allDrawn="); pw.print(allDrawn);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002950 pw.print(" lastAllDrawn="); pw.print(mLastAllDrawn);
Craig Mautner6fbda632012-07-03 09:26:39 -07002951 pw.println(")");
2952 }
2953 if (inPendingTransaction) {
2954 pw.print(prefix); pw.print("inPendingTransaction=");
2955 pw.println(inPendingTransaction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002956 }
Craig Mautner799bc1d2015-01-14 10:33:48 -08002957 if (startingData != null || removed || firstWindowDrawn || mIsExiting) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002958 pw.print(prefix); pw.print("startingData="); pw.print(startingData);
2959 pw.print(" removed="); pw.print(removed);
Craig Mautner3d7ca312015-01-08 10:56:00 -08002960 pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
Craig Mautner799bc1d2015-01-14 10:33:48 -08002961 pw.print(" mIsExiting="); pw.println(mIsExiting);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002962 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08002963 if (startingWindow != null || startingSurface != null
Wale Ogunwale6c459212017-05-17 08:56:03 -07002964 || startingDisplayed || startingMoved || mHiddenSetFromTransferredStartingWindow) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002965 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08002966 pw.print(" startingSurface="); pw.print(startingSurface);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002967 pw.print(" startingDisplayed="); pw.print(startingDisplayed);
Wale Ogunwale6c459212017-05-17 08:56:03 -07002968 pw.print(" startingMoved="); pw.print(startingMoved);
2969 pw.println(" mHiddenSetFromTransferredStartingWindow="
2970 + mHiddenSetFromTransferredStartingWindow);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002971 }
Jorim Jaggi0429f352015-12-22 16:29:16 +01002972 if (!mFrozenBounds.isEmpty()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08002973 pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
Jorim Jaggi26c8c422016-05-09 19:57:25 -07002974 pw.print(prefix); pw.print("mFrozenMergedConfig="); pw.println(mFrozenMergedConfig);
Chong Zhangd78ddb42016-03-02 17:01:14 -08002975 }
2976 if (mPendingRelaunchCount != 0) {
2977 pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount);
Jorim Jaggi0429f352015-12-22 16:29:16 +01002978 }
Riddle Hsub398da32019-01-21 21:48:16 +08002979 if (mSizeCompatScale != 1f || mSizeCompatBounds != null) {
2980 pw.println(prefix + "mSizeCompatScale=" + mSizeCompatScale + " mSizeCompatBounds="
2981 + mSizeCompatBounds);
2982 }
Wale Ogunwalee287e192017-04-21 09:30:12 -07002983 if (mRemovingFromDisplay) {
2984 pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay);
2985 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002986 }
2987
2988 @Override
2989 void setHidden(boolean hidden) {
2990 super.setHidden(hidden);
Winson Chunge55c0192017-08-24 14:50:48 -07002991
2992 if (hidden) {
2993 // Once the app window is hidden, reset the last saved PiP snap fraction
2994 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(this);
2995 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002996 scheduleAnimation();
2997 }
2998
2999 @Override
3000 void prepareSurfaces() {
3001 // isSelfAnimating also returns true when we are about to start a transition, so we need
3002 // to check super here.
3003 final boolean reallyAnimating = super.isSelfAnimating();
3004 final boolean show = !isHidden() || reallyAnimating;
Robert Carrd8e4fb72019-01-31 11:14:30 -08003005
3006 if (mSurfaceControl != null) {
3007 if (show && !mLastSurfaceShowing) {
3008 mPendingTransaction.show(mSurfaceControl);
3009 } else if (!show && mLastSurfaceShowing) {
3010 mPendingTransaction.hide(mSurfaceControl);
3011 }
Jorim Jaggi4d1835d2017-08-31 17:28:27 +02003012 }
Jorim Jaggi988f6682017-11-17 17:46:43 +01003013 if (mThumbnail != null) {
3014 mThumbnail.setShowing(mPendingTransaction, show);
3015 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003016 mLastSurfaceShowing = show;
3017 super.prepareSurfaces();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003018 }
3019
Jorim Jaggi77d0f36c2018-03-16 17:49:49 +01003020 /**
3021 * @return Whether our {@link #getSurfaceControl} is currently showing.
3022 */
3023 boolean isSurfaceShowing() {
3024 return mLastSurfaceShowing;
3025 }
3026
Jorim Jaggib0fc8172017-11-23 17:04:08 +00003027 boolean isFreezingScreen() {
3028 return mFreezingScreen;
3029 }
3030
3031 @Override
3032 boolean needsZBoost() {
3033 return mNeedsZBoost || super.needsZBoost();
3034 }
3035
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07003036 @CallSuper
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003037 @Override
Nataniel Borges023ecb52019-01-16 14:15:43 -08003038 public void writeToProto(ProtoOutputStream proto, long fieldId,
3039 @WindowTraceLogLevel int logLevel) {
3040 // Critical log level logs only visible elements to mitigate performance overheard
3041 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
3042 return;
3043 }
3044
Steven Timotiusaf03df62017-07-18 16:56:43 -07003045 final long token = proto.start(fieldId);
3046 writeNameToProto(proto, NAME);
Nataniel Borges023ecb52019-01-16 14:15:43 -08003047 super.writeToProto(proto, WINDOW_TOKEN, logLevel);
Vishnu Nair04ab4392018-01-10 11:00:06 -08003048 proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing);
3049 proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart());
3050 proto.write(IS_REALLY_ANIMATING, isReallyAnimating());
3051 if (mThumbnail != null){
3052 mThumbnail.writeToProto(proto, THUMBNAIL);
3053 }
3054 proto.write(FILLS_PARENT, mFillsParent);
3055 proto.write(APP_STOPPED, mAppStopped);
3056 proto.write(HIDDEN_REQUESTED, hiddenRequested);
3057 proto.write(CLIENT_HIDDEN, mClientHidden);
3058 proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient);
3059 proto.write(REPORTED_DRAWN, reportedDrawn);
3060 proto.write(REPORTED_VISIBLE, reportedVisible);
3061 proto.write(NUM_INTERESTING_WINDOWS, mNumInterestingWindows);
3062 proto.write(NUM_DRAWN_WINDOWS, mNumDrawnWindows);
3063 proto.write(ALL_DRAWN, allDrawn);
3064 proto.write(LAST_ALL_DRAWN, mLastAllDrawn);
3065 proto.write(REMOVED, removed);
Nataniel Borges023ecb52019-01-16 14:15:43 -08003066 if (startingWindow != null) {
Vishnu Nair04ab4392018-01-10 11:00:06 -08003067 startingWindow.writeIdentifierToProto(proto, STARTING_WINDOW);
3068 }
3069 proto.write(STARTING_DISPLAYED, startingDisplayed);
3070 proto.write(STARTING_MOVED, startingMoved);
3071 proto.write(HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW,
3072 mHiddenSetFromTransferredStartingWindow);
3073 for (Rect bounds : mFrozenBounds) {
3074 bounds.writeToProto(proto, FROZEN_BOUNDS);
3075 }
Steven Timotiusaf03df62017-07-18 16:56:43 -07003076 proto.end(token);
3077 }
3078
3079 void writeNameToProto(ProtoOutputStream proto, long fieldId) {
3080 if (appToken == null) {
3081 return;
3082 }
3083 try {
3084 proto.write(fieldId, appToken.getName());
3085 } catch (RemoteException e) {
3086 // This shouldn't happen, but in this case fall back to outputting nothing
3087 Slog.e(TAG, e.toString());
3088 }
3089 }
3090
3091 @Override
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003092 public String toString() {
3093 if (stringName == null) {
3094 StringBuilder sb = new StringBuilder();
3095 sb.append("AppWindowToken{");
3096 sb.append(Integer.toHexString(System.identityHashCode(this)));
3097 sb.append(" token="); sb.append(token); sb.append('}');
3098 stringName = sb.toString();
3099 }
Wale Ogunwaleba51ca22016-09-23 06:06:54 -07003100 return stringName + ((mIsExiting) ? " mIsExiting=" : "");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003101 }
Adrian Roos20e07892018-02-23 19:12:01 +01003102
3103 Rect getLetterboxInsets() {
3104 if (mLetterbox != null) {
3105 return mLetterbox.getInsets();
3106 } else {
3107 return new Rect();
3108 }
3109 }
Adrian Roos23df3a32018-03-15 15:41:13 +01003110
3111 /**
3112 * @eturn true if there is a letterbox and any part of that letterbox overlaps with
3113 * the given {@code rect}.
3114 */
3115 boolean isLetterboxOverlappingWith(Rect rect) {
3116 return mLetterbox != null && mLetterbox.isOverlappingWith(rect);
3117 }
chaviw4ad54912018-05-30 11:05:44 -07003118
3119 /**
3120 * Sets if this AWT is in the process of closing or entering PIP.
3121 * {@link #mWillCloseOrEnterPip}}
3122 */
3123 void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
3124 mWillCloseOrEnterPip = willCloseOrEnterPip;
3125 }
3126
3127 /**
3128 * Returns whether this AWT is considered closing. Conditions are either
3129 * 1. Is this app animating and was requested to be hidden
3130 * 2. App is delayed closing since it might enter PIP.
3131 */
3132 boolean isClosingOrEnteringPip() {
3133 return (isAnimating() && hiddenRequested) || mWillCloseOrEnterPip;
3134 }
Jorim Jaggiaf0d6d22018-06-08 15:25:35 +02003135
3136 /**
3137 * @return Whether we are allowed to show non-starting windows at the moment. We disallow
3138 * showing windows during transitions in case we have windows that have wide-color-gamut
3139 * color mode set to avoid jank in the middle of the transition.
3140 */
3141 boolean canShowWindows() {
3142 return allDrawn && !(isReallyAnimating() && hasNonDefaultColorWindow());
3143 }
3144
3145 /**
3146 * @return true if we have a window that has a non-default color mode set; false otherwise.
3147 */
3148 private boolean hasNonDefaultColorWindow() {
3149 return forAllWindows(ws -> ws.mAttrs.getColorMode() != COLOR_MODE_DEFAULT,
3150 true /* topToBottom */);
3151 }
lumark588a3e82018-07-20 18:53:54 +08003152
3153 void removeFromPendingTransition() {
3154 if (isWaitingForTransitionStart() && mDisplayContent != null) {
3155 mDisplayContent.mOpeningApps.remove(this);
Evan Rosky25b56192019-02-06 16:10:56 -08003156 if (mDisplayContent.mChangingApps.remove(this)) {
3157 clearChangeLeash(getPendingTransaction(), true /* cancel */);
3158 }
lumark588a3e82018-07-20 18:53:54 +08003159 mDisplayContent.mClosingApps.remove(this);
3160 }
3161 }
chaviwdcf76ec2019-01-11 16:48:46 -08003162
3163 private void updateColorTransform() {
3164 if (mSurfaceControl != null && mLastAppSaturationInfo != null) {
3165 mPendingTransaction.setColorTransform(mSurfaceControl, mLastAppSaturationInfo.mMatrix,
3166 mLastAppSaturationInfo.mTranslation);
3167 mWmService.scheduleAnimationLocked();
3168 }
3169 }
3170
3171 private static class AppSaturationInfo {
3172 float[] mMatrix = new float[9];
3173 float[] mTranslation = new float[3];
3174
3175 void setSaturation(@Size(9) float[] matrix, @Size(3) float[] translation) {
3176 System.arraycopy(matrix, 0, mMatrix, 0, mMatrix.length);
3177 System.arraycopy(translation, 0, mTranslation, 0, mTranslation.length);
3178 }
3179 }
Jeff Browne9bdb312012-04-05 15:30:10 -07003180}