blob: 9a8943c0b5e4557972b5dffea92ba912b5c7f107 [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
Wale Ogunwale6c459212017-05-17 08:56:03 -0700242 private boolean mDisablePreviewScreenshots;
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +0100243
Wale Ogunwale034a8ec2017-09-02 17:14:40 -0700244 private Task mLastParent;
Robert Carred3e83b2017-04-21 13:26:55 -0700245
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800246 // TODO: Remove after unification
247 ActivityRecord mActivityRecord;
248
chaviwd3bf08d2017-08-01 17:24:59 -0700249 /**
250 * See {@link #canTurnScreenOn()}
251 */
252 private boolean mCanTurnScreenOn = true;
253
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200254 /**
255 * If we are running an animation, this determines the transition type. Must be one of
256 * AppTransition.TRANSIT_* constants.
257 */
258 private int mTransit;
259
260 /**
261 * If we are running an animation, this determines the flags during this animation. Must be a
262 * bitwise combination of AppTransition.TRANSIT_FLAG_* constants.
263 */
264 private int mTransitFlags;
265
266 /** Whether our surface was set to be showing in the last call to {@link #prepareSurfaces} */
Jorim Jaggifd1891462017-12-29 15:41:36 +0100267 private boolean mLastSurfaceShowing = true;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200268
Evan Rosky2289ba12018-11-19 18:28:18 -0800269 /**
270 * This gets used during some open/close transitions as well as during a change transition
271 * where it represents the starting-state snapshot.
272 */
Jorim Jaggi988f6682017-11-17 17:46:43 +0100273 private AppWindowThumbnail mThumbnail;
Evan Rosky2289ba12018-11-19 18:28:18 -0800274 private final Rect mTransitStartRect = new Rect();
275
276 /**
277 * This leash is used to "freeze" the app surface in place after the state change, but before
278 * the animation is ready to start.
279 */
280 private SurfaceControl mTransitChangeLeash = null;
Jorim Jaggi988f6682017-11-17 17:46:43 +0100281
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000282 /** Have we been asked to have this token keep the screen frozen? */
283 private boolean mFreezingScreen;
284
285 /** Whether this token should be boosted at the top of all app window tokens. */
286 private boolean mNeedsZBoost;
Adrian Roos4d18a2e2017-12-19 19:08:05 +0100287 private Letterbox mLetterbox;
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000288
chaviw23ee71c2017-12-18 11:29:41 -0800289 private final Point mTmpPoint = new Point();
chaviw23012112017-12-20 15:29:04 -0800290 private final Rect mTmpRect = new Rect();
Evan Rosky2289ba12018-11-19 18:28:18 -0800291 private final Rect mTmpPrevBounds = new Rect();
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100292 private RemoteAnimationDefinition mRemoteAnimationDefinition;
Jorim Jaggi6de61012018-03-19 14:53:23 +0100293 private AnimatingAppWindowTokenRegistry mAnimatingAppWindowTokenRegistry;
chaviw23ee71c2017-12-18 11:29:41 -0800294
chaviw4ad54912018-05-30 11:05:44 -0700295 /**
296 * A flag to determine if this AWT is in the process of closing or entering PIP. This is needed
297 * to help AWT know that the app is in the process of closing but hasn't yet started closing on
298 * the WM side.
299 */
300 private boolean mWillCloseOrEnterPip;
301
Vishnu Naira2977262018-07-26 13:31:26 -0700302 /** Layer used to constrain the animation to a token's stack bounds. */
303 SurfaceControl mAnimationBoundsLayer;
304
305 /** Whether this token needs to create mAnimationBoundsLayer for cropping animations. */
306 boolean mNeedsAnimationBoundsLayer;
307
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800308 private static final int STARTING_WINDOW_TYPE_NONE = 0;
309 private static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
310 private static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
311
chaviwdcf76ec2019-01-11 16:48:46 -0800312 private AppSaturationInfo mLastAppSaturationInfo;
313
314 private final ColorDisplayService.ColorTransformController mColorTransformController =
315 (matrix, translation) -> mWmService.mH.post(() -> {
316 synchronized (mWmService.mGlobalLock) {
317 if (mLastAppSaturationInfo == null) {
318 mLastAppSaturationInfo = new AppSaturationInfo();
319 }
320
321 mLastAppSaturationInfo.setSaturation(matrix, translation);
322 updateColorTransform();
323 }
324 });
325
Winson Chung48b25652018-10-22 14:04:30 -0700326 AppWindowToken(WindowManagerService service, IApplicationToken token,
327 ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
328 long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers,
329 int targetSdk, int orientation, int rotationAnimationHint, int configChanges,
330 boolean launchTaskBehind, boolean alwaysFocusable,
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800331 ActivityRecord activityRecord) {
Winson Chung48b25652018-10-22 14:04:30 -0700332 this(service, token, activityComponent, voiceInteraction, dc, fullscreen);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800333 // TODO: remove after unification
334 mActivityRecord = activityRecord;
335 mActivityRecord.registerConfigurationChangeListener(this);
Wale Ogunwale72919d22016-12-08 18:58:50 -0800336 mInputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800337 mShowForAllUsers = showForAllUsers;
338 mTargetSdk = targetSdk;
339 mOrientation = orientation;
340 layoutConfigChanges = (configChanges & (CONFIG_SCREEN_SIZE | CONFIG_ORIENTATION)) != 0;
341 mLaunchTaskBehind = launchTaskBehind;
342 mAlwaysFocusable = alwaysFocusable;
343 mRotationAnimationHint = rotationAnimationHint;
344
345 // Application tokens start out hidden.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200346 setHidden(true);
Wale Ogunwale72919d22016-12-08 18:58:50 -0800347 hiddenRequested = true;
chaviwdcf76ec2019-01-11 16:48:46 -0800348
349 ColorDisplayService.ColorDisplayServiceInternal cds = LocalServices.getService(
350 ColorDisplayService.ColorDisplayServiceInternal.class);
351 cds.attachColorTransformController(activityRecord.packageName, activityRecord.mUserId,
352 new WeakReference<>(mColorTransformController));
Wale Ogunwale72919d22016-12-08 18:58:50 -0800353 }
354
Winson Chung48b25652018-10-22 14:04:30 -0700355 AppWindowToken(WindowManagerService service, IApplicationToken token,
356 ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
357 boolean fillsParent) {
Wale Ogunwale5cd907d2017-01-26 14:14:08 -0800358 super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true, dc,
359 false /* ownerCanManageAppTokens */);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700360 appToken = token;
Winson Chung48b25652018-10-22 14:04:30 -0700361 mActivityComponent = activityComponent;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800362 mVoiceInteraction = voiceInteraction;
Wale Ogunwale17f175c2017-02-07 16:54:10 -0800363 mFillsParent = fillsParent;
Robert Carr0bcbe642018-10-11 19:07:43 -0700364 mInputApplicationHandle = new InputApplicationHandle(appToken.asBinder());
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800365 }
366
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800367 void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
368 firstWindowDrawn = true;
369
370 // We now have a good window to show, remove dead placeholders
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700371 removeDeadWindows();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800372
Jorim Jaggi02886a82016-12-06 09:10:06 -0800373 if (startingWindow != null) {
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800374 if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Slog.v(TAG, "Finish starting "
375 + win.mToken + ": first real window is shown, no animation");
376 // If this initial window is animating, stop it -- we will do an animation to reveal
377 // it from behind the starting window, so there is no need for it to also be doing its
378 // own stuff.
Jorim Jaggia5e10572017-11-15 14:36:26 +0100379 win.cancelAnimation();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800380 removeStartingWindow();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800381 }
382 updateReportedVisibilityLocked();
383 }
384
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800385 void updateReportedVisibilityLocked() {
386 if (appToken == null) {
387 return;
388 }
389
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700390 if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700391 final int count = mChildren.size();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800392
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700393 mReportedVisibilityResults.reset();
394
395 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700396 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700397 win.updateReportedVisibility(mReportedVisibilityResults);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800398 }
399
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700400 int numInteresting = mReportedVisibilityResults.numInteresting;
401 int numVisible = mReportedVisibilityResults.numVisible;
402 int numDrawn = mReportedVisibilityResults.numDrawn;
403 boolean nowGone = mReportedVisibilityResults.nowGone;
404
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700405 boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200406 boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting && !isHidden();
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700407 if (!nowGone) {
408 // If the app is not yet gone, then it can only become visible/drawn.
409 if (!nowDrawn) {
410 nowDrawn = reportedDrawn;
411 }
412 if (!nowVisible) {
413 nowVisible = reportedVisible;
414 }
415 }
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800416 if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800417 + numInteresting + " visible=" + numVisible);
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700418 if (nowDrawn != reportedDrawn) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800419 if (mActivityRecord != null) {
420 mActivityRecord.onWindowsDrawn(nowDrawn, SystemClock.uptimeMillis());
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700421 }
422 reportedDrawn = nowDrawn;
423 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800424 if (nowVisible != reportedVisible) {
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700425 if (DEBUG_VISIBILITY) Slog.v(TAG,
426 "Visibility changed in " + this + ": vis=" + nowVisible);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800427 reportedVisible = nowVisible;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800428 if (mActivityRecord != null) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800429 if (nowVisible) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800430 onWindowsVisible();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800431 } else {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800432 onWindowsGone();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800433 }
434 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800435 }
436 }
437
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800438 private void onWindowsGone() {
439 if (mActivityRecord == null) {
440 return;
441 }
442 if (DEBUG_VISIBILITY) {
443 Slog.v(TAG_WM, "Reporting gone in " + mActivityRecord.appToken);
444 }
445 mActivityRecord.onWindowsGone();
446 }
447
448 private void onWindowsVisible() {
449 if (mActivityRecord == null) {
450 return;
451 }
452 if (DEBUG_VISIBILITY) {
453 Slog.v(TAG_WM, "Reporting visible in " + mActivityRecord.appToken);
454 }
455 mActivityRecord.onWindowsVisible();
456 }
457
Wale Ogunwale89973222017-04-23 18:39:45 -0700458 boolean isClientHidden() {
459 return mClientHidden;
460 }
461
462 void setClientHidden(boolean hideClient) {
463 if (mClientHidden == hideClient || (hideClient && mDeferHidingClient)) {
464 return;
465 }
Jorim Jaggi067b5bf2018-02-23 17:42:39 +0100466 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "setClientHidden: " + this
467 + " clientHidden=" + hideClient + " Callers=" + Debug.getCallers(5));
Wale Ogunwale89973222017-04-23 18:39:45 -0700468 mClientHidden = hideClient;
469 sendAppVisibilityToClients();
470 }
471
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800472 void setVisibility(boolean visible, boolean deferHidingClient) {
473 final AppTransition appTransition = getDisplayContent().mAppTransition;
474
475 // Don't set visibility to false if we were already not visible. This prevents WM from
476 // adding the app to the closing app list which doesn't make sense for something that is
477 // already not visible. However, set visibility to true even if we are already visible.
478 // This makes sure the app is added to the opening apps list so that the right
479 // transition can be selected.
480 // TODO: Probably a good idea to separate the concept of opening/closing apps from the
481 // concept of setting visibility...
482 if (!visible && hiddenRequested) {
483
484 if (!deferHidingClient && mDeferHidingClient) {
485 // We previously deferred telling the client to hide itself when visibility was
486 // initially set to false. Now we would like it to hide, so go ahead and set it.
487 mDeferHidingClient = deferHidingClient;
488 setClientHidden(true);
489 }
490 return;
491 }
492
493 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) {
494 Slog.v(TAG_WM, "setAppVisibility("
495 + appToken + ", visible=" + visible + "): " + appTransition
496 + " hidden=" + isHidden() + " hiddenRequested="
497 + hiddenRequested + " Callers=" + Debug.getCallers(6));
498 }
499
500 final DisplayContent displayContent = getDisplayContent();
501 displayContent.mOpeningApps.remove(this);
502 displayContent.mClosingApps.remove(this);
503 waitingToShow = false;
504 hiddenRequested = !visible;
505 mDeferHidingClient = deferHidingClient;
506
507 if (!visible) {
508 // If the app is dead while it was visible, we kept its dead window on screen.
509 // Now that the app is going invisible, we can remove it. It will be restarted
510 // if made visible again.
511 removeDeadWindows();
512 } else {
513 if (!appTransition.isTransitionSet()
514 && appTransition.isReady()) {
515 // Add the app mOpeningApps if transition is unset but ready. This means
516 // we're doing a screen freeze, and the unfreeze will wait for all opening
517 // apps to be ready.
518 displayContent.mOpeningApps.add(this);
519 }
520 startingMoved = false;
521 // If the token is currently hidden (should be the common case), or has been
522 // stopped, then we need to set up to wait for its windows to be ready.
523 if (isHidden() || mAppStopped) {
524 clearAllDrawn();
525
526 // If the app was already visible, don't reset the waitingToShow state.
527 if (isHidden()) {
528 waitingToShow = true;
529 }
530 }
531
532 // In the case where we are making an app visible but holding off for a transition,
533 // we still need to tell the client to make its windows visible so they get drawn.
534 // Otherwise, we will wait on performing the transition until all windows have been
535 // drawn, they never will be, and we are sad.
536 setClientHidden(false);
537
538 requestUpdateWallpaperIfNeeded();
539
540 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "No longer Stopped: " + this);
541 mAppStopped = false;
542
543 transferStartingWindowFromHiddenAboveTokenIfNeeded();
544 }
545
546 // If we are preparing an app transition, then delay changing
547 // the visibility of this token until we execute that transition.
548 if (okToAnimate() && appTransition.isTransitionSet()) {
549 inPendingTransaction = true;
550 if (visible) {
551 displayContent.mOpeningApps.add(this);
552 mEnteringAnimation = true;
553 } else {
554 displayContent.mClosingApps.add(this);
555 mEnteringAnimation = false;
556 }
557 if (appTransition.getAppTransition()
558 == WindowManager.TRANSIT_TASK_OPEN_BEHIND) {
559 // We're launchingBehind, add the launching activity to mOpeningApps.
560 final WindowState win = getDisplayContent().findFocusedWindow();
561 if (win != null) {
562 final AppWindowToken focusedToken = win.mAppToken;
563 if (focusedToken != null) {
564 if (DEBUG_APP_TRANSITIONS) {
565 Slog.d(TAG_WM, "TRANSIT_TASK_OPEN_BEHIND, "
566 + " adding " + focusedToken + " to mOpeningApps");
567 }
568 // Force animation to be loaded.
569 focusedToken.setHidden(true);
570 displayContent.mOpeningApps.add(focusedToken);
571 }
572 }
573 }
574 return;
575 }
576
577 commitVisibility(null, visible, TRANSIT_UNSET, true, mVoiceInteraction);
578 updateReportedVisibilityLocked();
579 }
580
581 boolean commitVisibility(WindowManager.LayoutParams lp,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700582 boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
583
584 boolean delayed = false;
585 inPendingTransaction = false;
Wale Ogunwale9e4721f2017-05-23 19:37:30 -0700586 // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually
587 // been set by the app now.
588 mHiddenSetFromTransferredStartingWindow = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700589
590 // Allow for state changes and animation to be applied if:
591 // * token is transitioning visibility state
592 // * or the token was marked as hidden and is exiting before we had a chance to play the
593 // transition animation
594 // * or this is an opening app and windows are being replaced.
595 boolean visibilityChanged = false;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200596 if (isHidden() == visible || (isHidden() && mIsExiting) || (visible && waitingForReplacement())) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800597 final AccessibilityController accessibilityController =
598 mWmService.mAccessibilityController;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700599 boolean changed = false;
600 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM,
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200601 "Changing app " + this + " hidden=" + isHidden() + " performLayout=" + performLayout);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700602
603 boolean runningAppAnimation = false;
604
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100605 if (transit != WindowManager.TRANSIT_UNSET) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200606 if (applyAnimationLocked(lp, transit, visible, isVoiceInteraction)) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700607 delayed = runningAppAnimation = true;
608 }
609 final WindowState window = findMainWindow();
Rhed Jao02655dc2018-10-30 20:44:52 +0800610 if (window != null && accessibilityController != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700611 accessibilityController.onAppWindowTransitionLocked(window, transit);
612 }
613 changed = true;
614 }
615
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700616 final int windowsCount = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700617 for (int i = 0; i < windowsCount; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700618 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700619 changed |= win.onAppVisibilityChanged(visible, runningAppAnimation);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700620 }
621
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200622 setHidden(!visible);
623 hiddenRequested = !visible;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700624 visibilityChanged = true;
625 if (!visible) {
626 stopFreezingScreen(true, true);
627 } else {
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700628 // If we are being set visible, and the starting window is not yet displayed,
629 // then make sure it doesn't get displayed.
630 if (startingWindow != null && !startingWindow.isDrawnLw()) {
631 startingWindow.mPolicyVisibility = false;
632 startingWindow.mPolicyVisibilityAfterAnim = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700633 }
Jorim Jaggi38d44ec2017-06-14 16:04:59 -0700634
635 // We are becoming visible, so better freeze the screen with the windows that are
636 // getting visible so we also wait for them.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800637 forAllWindows(mWmService::makeWindowFreezingScreenIfNeededLocked, true);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700638 }
639
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800640 if (DEBUG_APP_TRANSITIONS) {
641 Slog.v(TAG_WM, "commitVisibility: " + this
642 + ": hidden=" + isHidden() + " hiddenRequested=" + hiddenRequested);
643 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700644
645 if (changed) {
Arthur Hung95b38a92018-07-20 18:56:12 +0800646 getDisplayContent().getInputMonitor().setUpdateInputWindowsNeededLw();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700647 if (performLayout) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800648 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700649 false /*updateInputWindows*/);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800650 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700651 }
Arthur Hung95b38a92018-07-20 18:56:12 +0800652 getDisplayContent().getInputMonitor().updateInputWindowsLw(false /*force*/);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700653 }
654 }
655
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200656 if (isReallyAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700657 delayed = true;
Jorim Jaggiab9fcb22018-03-15 23:46:12 +0100658 } else {
659
660 // We aren't animating anything, but exiting windows rely on the animation finished
661 // callback being called in case the AppWindowToken was pretending to be animating,
662 // which we might have done because we were in closing/opening apps list.
663 onAnimationFinished();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700664 }
665
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700666 for (int i = mChildren.size() - 1; i >= 0 && !delayed; i--) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100667 if ((mChildren.get(i)).isSelfOrChildAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700668 delayed = true;
669 }
670 }
671
672 if (visibilityChanged) {
673 if (visible && !delayed) {
674 // The token was made immediately visible, there will be no entrance animation.
675 // We need to inform the client the enter animation was finished.
676 mEnteringAnimation = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800677 mWmService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(
678 token);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700679 }
Robert Carr61b81112017-07-17 18:08:15 -0700680
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800681 // If we're becoming visible, immediately change client visibility as well. there seem
682 // to be some edge cases where we change our visibility but client visibility never gets
683 // updated.
Jorim Jaggi110839b2018-01-22 12:49:04 +0100684 // If we're becoming invisible, update the client visibility if we are not running an
685 // animation. Otherwise, we'll update client visibility in onAnimationFinished.
Jorim Jaggi3cad57f2018-02-20 18:32:01 +0100686 if (visible || !isReallyAnimating()) {
Jorim Jaggi110839b2018-01-22 12:49:04 +0100687 setClientHidden(!visible);
Jorim Jaggi4876b4a2018-01-11 15:43:49 +0100688 }
689
lumark588a3e82018-07-20 18:53:54 +0800690 if (!getDisplayContent().mClosingApps.contains(this)
691 && !getDisplayContent().mOpeningApps.contains(this)) {
chaviwa953fcf2018-03-01 12:00:39 -0800692 // The token is not closing nor opening, so even if there is an animation set, that
693 // doesn't mean that it goes through the normal app transition cycle so we have
694 // to inform the docked controller about visibility change.
695 // TODO(multi-display): notify docked divider on all displays where visibility was
696 // affected.
lumark588a3e82018-07-20 18:53:54 +0800697 getDisplayContent().getDockedDividerController().notifyAppVisibilityChanged();
chaviwa953fcf2018-03-01 12:00:39 -0800698
699 // Take the screenshot before possibly hiding the WSA, otherwise the screenshot
700 // will not be taken.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800701 mWmService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible);
chaviwa953fcf2018-03-01 12:00:39 -0800702 }
703
Robert Carre7cc44d2017-03-20 19:04:30 -0700704 // If we are hidden but there is no delay needed we immediately
705 // apply the Surface transaction so that the ActivityManager
Robert Carr61b81112017-07-17 18:08:15 -0700706 // can have some guarantee on the Surface state following
707 // setting the visibility. This captures cases like dismissing
708 // the docked or pinned stack where there is no app transition.
709 //
710 // In the case of a "Null" animation, there will be
711 // no animation but there will still be a transition set.
712 // We still need to delay hiding the surface such that it
713 // can be synchronized with showing the next surface in the transition.
lumark588a3e82018-07-20 18:53:54 +0800714 if (isHidden() && !delayed && !getDisplayContent().mAppTransition.isTransitionSet()) {
Robert Carr6914f082017-03-20 19:04:30 -0700715 SurfaceControl.openTransaction();
716 for (int i = mChildren.size() - 1; i >= 0; i--) {
717 mChildren.get(i).mWinAnimator.hide("immediately hidden");
718 }
719 SurfaceControl.closeTransaction();
720 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700721 }
722
723 return delayed;
724 }
725
Jorim Jaggi87fdbcb2017-08-17 13:41:11 +0200726 /**
727 * @return The to top most child window for which {@link LayoutParams#isFullscreen()} returns
728 * true.
729 */
730 WindowState getTopFullscreenWindow() {
731 for (int i = mChildren.size() - 1; i >= 0; i--) {
732 final WindowState win = mChildren.get(i);
733 if (win != null && win.mAttrs.isFullscreen()) {
734 return win;
735 }
736 }
737 return null;
738 }
739
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800740 WindowState findMainWindow() {
Matthew Ng53e66b22018-01-12 17:13:13 -0800741 return findMainWindow(true);
742 }
743
744 /**
745 * Finds the main window that either has type base application or application starting if
746 * requested.
747 *
748 * @param includeStartingApp Allow to search application-starting windows to also be returned.
749 * @return The main window of type base application or application starting if requested.
750 */
751 WindowState findMainWindow(boolean includeStartingApp) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700752 WindowState candidate = null;
Matthew Ng53e66b22018-01-12 17:13:13 -0800753 for (int j = mChildren.size() - 1; j >= 0; --j) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700754 final WindowState win = mChildren.get(j);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700755 final int type = win.mAttrs.type;
756 // No need to loop through child window as base application and starting types can't be
757 // child windows.
Matthew Ng53e66b22018-01-12 17:13:13 -0800758 if (type == TYPE_BASE_APPLICATION
759 || (includeStartingApp && type == TYPE_APPLICATION_STARTING)) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700760 // In cases where there are multiple windows, we prefer the non-exiting window. This
Sungsoo Lim0d3d1f82015-12-02 14:47:59 +0900761 // happens for example when replacing windows during an activity relaunch. When
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700762 // constructing the animation, we want the new window, not the exiting one.
Wale Ogunwalec48a3542016-02-19 15:18:45 -0800763 if (win.mAnimatingExit) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700764 candidate = win;
765 } else {
766 return win;
767 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800768 }
769 }
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700770 return candidate;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800771 }
772
Wale Ogunwale6cae7652015-12-26 07:36:26 -0800773 boolean windowsAreFocusable() {
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800774 if (mTargetSdk < Build.VERSION_CODES.Q) {
775 final int pid = mActivityRecord != null
776 ? (mActivityRecord.app != null ? mActivityRecord.app.getPid() : 0) : 0;
777 final AppWindowToken topFocusedAppOfMyProcess =
778 mWmService.mRoot.mTopFocusedAppByProcess.get(pid);
779 if (topFocusedAppOfMyProcess != null && topFocusedAppOfMyProcess != this) {
780 // For the apps below Q, there can be only one app which has the focused window per
781 // process, because legacy apps may not be ready for a multi-focus system.
782 return false;
783 }
784 }
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700785 return getWindowConfiguration().canReceiveKeys() || mAlwaysFocusable;
Wale Ogunwaled045c822015-12-02 09:14:28 -0800786 }
787
Wale Ogunwale571771c2016-08-26 13:18:50 -0700788 @Override
Wale Ogunwale44f21802016-09-02 12:49:48 -0700789 boolean isVisible() {
Wale Ogunwalee471be62016-10-03 07:53:55 -0700790 // If the app token isn't hidden then it is considered visible and there is no need to check
791 // its children windows to see if they are visible.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200792 return !isHidden();
Wale Ogunwale44f21802016-09-02 12:49:48 -0700793 }
794
795 @Override
Wale Ogunwalee287e192017-04-21 09:30:12 -0700796 void removeImmediately() {
797 onRemovedFromDisplay();
Yunfan Chen3a77f282018-12-12 15:47:52 -0800798 if (mActivityRecord != null) {
799 mActivityRecord.unregisterConfigurationChangeListener(this);
800 }
Wale Ogunwalee287e192017-04-21 09:30:12 -0700801 super.removeImmediately();
802 }
803
804 @Override
Wale Ogunwale571771c2016-08-26 13:18:50 -0700805 void removeIfPossible() {
Craig Mautnere3119b72015-01-20 15:02:36 -0800806 mIsExiting = false;
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800807 removeAllWindowsIfPossible();
Bryce Lee6d410262017-02-28 15:30:17 -0800808 removeImmediately();
Craig Mautnere3119b72015-01-20 15:02:36 -0800809 }
810
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700811 @Override
812 boolean checkCompleteDeferredRemoval() {
813 if (mIsExiting) {
814 removeIfPossible();
815 }
816 return super.checkCompleteDeferredRemoval();
817 }
818
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700819 void onRemovedFromDisplay() {
Wale Ogunwalee287e192017-04-21 09:30:12 -0700820 if (mRemovingFromDisplay) {
821 return;
822 }
823 mRemovingFromDisplay = true;
824
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700825 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app token: " + this);
826
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800827 boolean delayed = commitVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700828
lumark588a3e82018-07-20 18:53:54 +0800829 getDisplayContent().mOpeningApps.remove(this);
Evan Rosky2289ba12018-11-19 18:28:18 -0800830 getDisplayContent().mChangingApps.remove(this);
lumark588a3e82018-07-20 18:53:54 +0800831 getDisplayContent().mUnknownAppVisibilityController.appRemovedOrHidden(this);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800832 mWmService.mTaskSnapshotController.onAppRemoved(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700833 waitingToShow = false;
lumark588a3e82018-07-20 18:53:54 +0800834 if (getDisplayContent().mClosingApps.contains(this)) {
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700835 delayed = true;
lumark588a3e82018-07-20 18:53:54 +0800836 } else if (getDisplayContent().mAppTransition.isTransitionSet()) {
837 getDisplayContent().mClosingApps.add(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700838 delayed = true;
839 }
840
841 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app " + this + " delayed=" + delayed
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200842 + " animation=" + getAnimation() + " animating=" + isSelfAnimating());
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700843
844 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: "
845 + this + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
846
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800847 if (startingData != null) {
848 removeStartingWindow();
Jorim Jaggi19be6052017-08-03 18:33:43 +0200849 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800850
Winson Chung87e5d552017-04-05 11:49:38 -0700851 // If this window was animating, then we need to ensure that the app transition notifies
lumark588a3e82018-07-20 18:53:54 +0800852 // that animations have completed in DisplayContent.handleAnimatingStoppedAndTransition(),
853 // so add to that list now
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200854 if (isSelfAnimating()) {
lumark588a3e82018-07-20 18:53:54 +0800855 getDisplayContent().mNoAnimationNotifyOnTransitionFinished.add(token);
Winson Chung87e5d552017-04-05 11:49:38 -0700856 }
857
Wale Ogunwalee287e192017-04-21 09:30:12 -0700858 final TaskStack stack = getStack();
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700859 if (delayed && !isEmpty()) {
860 // set the token aside because it has an active animation to be finished
861 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM,
862 "removeAppToken make exiting: " + this);
Wale Ogunwalee287e192017-04-21 09:30:12 -0700863 if (stack != null) {
864 stack.mExitingAppTokens.add(this);
865 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700866 mIsExiting = true;
867 } else {
868 // Make sure there is no animation running on this token, so any windows associated
869 // with it will be removed as soon as their animations are complete
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200870 cancelAnimation();
Wale Ogunwale3106ae012017-05-16 08:56:37 -0700871 if (stack != null) {
872 stack.mExitingAppTokens.remove(this);
873 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700874 removeIfPossible();
875 }
876
877 removed = true;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700878 stopFreezingScreen(true, true);
Bryce Lee6d410262017-02-28 15:30:17 -0800879
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800880 final DisplayContent dc = getDisplayContent();
881 if (dc.mFocusedApp == this) {
882 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + this
883 + " displayId=" + dc.getDisplayId());
884 dc.setFocusedApp(null);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800885 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700886 }
Riddle Hsu192fe762019-01-15 23:41:57 +0800887 if (mLetterbox != null) {
888 mLetterbox.destroy();
889 mLetterbox = null;
890 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700891
892 if (!delayed) {
893 updateReportedVisibilityLocked();
894 }
Wale Ogunwalee287e192017-04-21 09:30:12 -0700895
896 mRemovingFromDisplay = false;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700897 }
898
Chong Zhange05bcb12016-07-26 17:47:29 -0700899 void clearAnimatingFlags() {
Chong Zhangb0d26702016-08-12 16:03:29 -0700900 boolean wallpaperMightChange = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700901 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700902 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700903 wallpaperMightChange |= win.clearAnimatingFlags();
Chong Zhange05bcb12016-07-26 17:47:29 -0700904 }
Chong Zhangb0d26702016-08-12 16:03:29 -0700905 if (wallpaperMightChange) {
906 requestUpdateWallpaperIfNeeded();
907 }
Chong Zhange05bcb12016-07-26 17:47:29 -0700908 }
909
Robert Carre12aece2016-02-02 22:43:27 -0800910 void destroySurfaces() {
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700911 destroySurfaces(false /*cleanupOnResume*/);
912 }
913
914 /**
915 * Destroy surfaces which have been marked as eligible by the animator, taking care to ensure
916 * the client has finished with them.
917 *
918 * @param cleanupOnResume whether this is done when app is resumed without fully stopped. If
919 * set to true, destroy only surfaces of removed windows, and clear relevant flags of the
920 * others so that they are ready to be reused. If set to false (common case), destroy all
921 * surfaces that's eligible, if the app is already stopped.
922 */
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700923 private void destroySurfaces(boolean cleanupOnResume) {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700924 boolean destroyedSomething = false;
Jorim Jaggia5e10572017-11-15 14:36:26 +0100925
926 // Copying to a different list as multiple children can be removed.
Jorim Jaggi59f3e922018-01-05 15:40:32 +0100927 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
Jorim Jaggia5e10572017-11-15 14:36:26 +0100928 for (int i = children.size() - 1; i >= 0; i--) {
929 final WindowState win = children.get(i);
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700930 destroyedSomething |= win.destroySurface(cleanupOnResume, mAppStopped);
Robert Carre12aece2016-02-02 22:43:27 -0800931 }
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700932 if (destroyedSomething) {
933 final DisplayContent dc = getDisplayContent();
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700934 dc.assignWindowLayers(true /*setLayoutNeeded*/);
Adrian Roos23df3a32018-03-15 15:41:13 +0100935 updateLetterboxSurface(null);
Robert Carre12aece2016-02-02 22:43:27 -0800936 }
937 }
938
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800939 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700940 * Notify that the app is now resumed, and it was not stopped before, perform a clean
941 * up of the surfaces
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800942 */
Jorim Jaggibae01b12017-04-11 16:29:10 -0700943 void notifyAppResumed(boolean wasStopped) {
Chong Zhangad24f962016-08-25 12:12:33 -0700944 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppResumed: wasStopped=" + wasStopped
Jorim Jaggibae01b12017-04-11 16:29:10 -0700945 + " " + this);
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700946 mAppStopped = false;
chaviwd3bf08d2017-08-01 17:24:59 -0700947 // Allow the window to turn the screen on once the app is resumed again.
948 setCanTurnScreenOn(true);
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700949 if (!wasStopped) {
950 destroySurfaces(true /*cleanupOnResume*/);
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800951 }
Robert Carre12aece2016-02-02 22:43:27 -0800952 }
953
Chong Zhangbef461f2015-10-27 11:38:24 -0700954 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700955 * Notify that the app has stopped, and it is okay to destroy any surfaces which were
956 * keeping alive in case they were still being used.
957 */
958 void notifyAppStopped() {
959 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: " + this);
960 mAppStopped = true;
961 destroySurfaces();
962 // Remove any starting window that was added for this app if they are still around.
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800963 removeStartingWindow();
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700964 }
965
Chong Zhang92147042016-05-09 12:47:11 -0700966 void clearAllDrawn() {
967 allDrawn = false;
968 deferClearAllDrawn = false;
Chong Zhangbef461f2015-10-27 11:38:24 -0700969 }
970
Bryce Lee6d410262017-02-28 15:30:17 -0800971 Task getTask() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -0800972 return (Task) getParent();
Bryce Lee6d410262017-02-28 15:30:17 -0800973 }
974
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800975 TaskStack getStack() {
976 final Task task = getTask();
977 if (task != null) {
978 return task.mStack;
979 } else {
980 return null;
981 }
982 }
983
Bryce Lee6d410262017-02-28 15:30:17 -0800984 @Override
Riddle Hsu3a4bb612019-01-31 00:02:22 +0800985 void onParentChanged() {
986 super.onParentChanged();
Bryce Lee6d410262017-02-28 15:30:17 -0800987
Robert Carred3e83b2017-04-21 13:26:55 -0700988 final Task task = getTask();
989
Bryce Lee6d410262017-02-28 15:30:17 -0800990 // When the associated task is {@code null}, the {@link AppWindowToken} can no longer
991 // access visual elements like the {@link DisplayContent}. We must remove any associations
992 // such as animations.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -0800993 if (!mReparenting) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -0800994 if (task == null) {
995 // It is possible we have been marked as a closing app earlier. We must remove ourselves
996 // from this list so we do not participate in any future animations.
lumark588a3e82018-07-20 18:53:54 +0800997 getDisplayContent().mClosingApps.remove(this);
Robert Carred3e83b2017-04-21 13:26:55 -0700998 } else if (mLastParent != null && mLastParent.mStack != null) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -0800999 task.mStack.mExitingAppTokens.remove(this);
1000 }
Bryce Lee6d410262017-02-28 15:30:17 -08001001 }
Jorim Jaggi6de61012018-03-19 14:53:23 +01001002 final TaskStack stack = getStack();
1003
1004 // If we reparent, make sure to remove ourselves from the old animation registry.
1005 if (mAnimatingAppWindowTokenRegistry != null) {
1006 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
1007 }
1008 mAnimatingAppWindowTokenRegistry = stack != null
1009 ? stack.getAnimatingAppWindowTokenRegistry()
1010 : null;
1011
Robert Carred3e83b2017-04-21 13:26:55 -07001012 mLastParent = task;
chaviwdcf76ec2019-01-11 16:48:46 -08001013
1014 updateColorTransform();
Bryce Lee6d410262017-02-28 15:30:17 -08001015 }
1016
Wale Ogunwalefa854eb2016-09-20 13:43:52 -07001017 void postWindowRemoveStartingWindowCleanup(WindowState win) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001018 // TODO: Something smells about the code below...Is there a better way?
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001019 if (startingWindow == win) {
1020 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Notify removed startingWindow " + win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001021 removeStartingWindow();
Wale Ogunwale6c459212017-05-17 08:56:03 -07001022 } else if (mChildren.size() == 0) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001023 // If this is the last window and we had requested a starting transition window,
1024 // well there is no point now.
Jorim Jaggi02886a82016-12-06 09:10:06 -08001025 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Nulling last startingData");
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001026 startingData = null;
Wale Ogunwale6c459212017-05-17 08:56:03 -07001027 if (mHiddenSetFromTransferredStartingWindow) {
1028 // We set the hidden state to false for the token from a transferred starting window.
1029 // We now reset it back to true since the starting window was the last window in the
1030 // token.
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001031 setHidden(true);
Wale Ogunwale6c459212017-05-17 08:56:03 -07001032 }
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01001033 } else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001034 // If this is the last window except for a starting transition window,
1035 // we need to get rid of the starting transition.
Jorim Jaggie4b0f282017-05-17 15:10:29 +02001036 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Last window, removing starting window "
1037 + win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001038 removeStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001039 }
1040 }
1041
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001042 void removeDeadWindows() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001043 for (int winNdx = mChildren.size() - 1; winNdx >= 0; --winNdx) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001044 WindowState win = mChildren.get(winNdx);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001045 if (win.mAppDied) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001046 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.w(TAG,
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001047 "removeDeadWindows: " + win);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001048 // Set mDestroying, we don't want any animation or delayed removal here.
1049 win.mDestroying = true;
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001050 // Also removes child windows.
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001051 win.removeIfPossible();
Chong Zhang112eb8c2015-11-02 11:17:00 -08001052 }
1053 }
1054 }
1055
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001056 boolean hasWindowsAlive() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001057 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001058 // No need to loop through child windows as the answer should be the same as that of the
1059 // parent window.
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001060 if (!(mChildren.get(i)).mAppDied) {
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001061 return true;
1062 }
1063 }
1064 return false;
1065 }
1066
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001067 void setWillReplaceWindows(boolean animate) {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001068 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
1069 "Marking app token " + this + " with replacing windows.");
Robert Carra1eb4392015-12-10 12:43:51 -08001070
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001071 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001072 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001073 w.setWillReplaceWindow(animate);
Robert Carra1eb4392015-12-10 12:43:51 -08001074 }
Robert Carra1eb4392015-12-10 12:43:51 -08001075 }
1076
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001077 void setWillReplaceChildWindows() {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001078 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Marking app token " + this
Robert Carr23fa16b2016-01-13 13:19:58 -08001079 + " with replacing child windows.");
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001080 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001081 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001082 w.setWillReplaceChildWindows();
Robert Carr23fa16b2016-01-13 13:19:58 -08001083 }
1084 }
1085
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001086 void clearWillReplaceWindows() {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001087 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
1088 "Resetting app token " + this + " of replacing window marks.");
Chong Zhangf596cd52016-01-05 13:42:44 -08001089
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001090 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001091 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001092 w.clearWillReplaceWindow();
Chong Zhangf596cd52016-01-05 13:42:44 -08001093 }
1094 }
1095
Chong Zhang4d7369a2016-04-25 16:09:14 -07001096 void requestUpdateWallpaperIfNeeded() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001097 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001098 final WindowState w = mChildren.get(i);
Chong Zhang4d7369a2016-04-25 16:09:14 -07001099 w.requestUpdateWallpaperIfNeeded();
1100 }
1101 }
1102
Chong Zhangd78ddb42016-03-02 17:01:14 -08001103 boolean isRelaunching() {
1104 return mPendingRelaunchCount > 0;
1105 }
1106
Robert Carr68375192017-06-13 12:41:53 -07001107 boolean shouldFreezeBounds() {
1108 final Task task = getTask();
1109
1110 // For freeform windows, we can't freeze the bounds at the moment because this would make
1111 // the resizing unresponsive.
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001112 if (task == null || task.inFreeformWindowingMode()) {
Robert Carr68375192017-06-13 12:41:53 -07001113 return false;
1114 }
1115
1116 // We freeze the bounds while drag resizing to deal with the time between
1117 // the divider/drag handle being released, and the handling it's new
1118 // configuration. If we are relaunched outside of the drag resizing state,
1119 // we need to be careful not to do this.
1120 return getTask().isDragResizing();
1121 }
1122
Chong Zhangd78ddb42016-03-02 17:01:14 -08001123 void startRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001124 if (shouldFreezeBounds()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08001125 freezeBounds();
1126 }
Robert Carrd5c7dd62017-03-08 10:39:30 -08001127
1128 // In the process of tearing down before relaunching, the app will
1129 // try and clean up it's child surfaces. We need to prevent this from
1130 // happening, so we sever the children, transfering their ownership
1131 // from the client it-self to the parent surface (owned by us).
Robert Carr29daa922018-04-27 11:56:48 -07001132 detachChildren();
1133
1134 mPendingRelaunchCount++;
1135 }
1136
1137 void detachChildren() {
Robert Carrfd8e93b2018-05-10 13:40:25 -07001138 SurfaceControl.openTransaction();
Robert Carrd5c7dd62017-03-08 10:39:30 -08001139 for (int i = mChildren.size() - 1; i >= 0; i--) {
1140 final WindowState w = mChildren.get(i);
1141 w.mWinAnimator.detachChildren();
1142 }
Robert Carrfd8e93b2018-05-10 13:40:25 -07001143 SurfaceControl.closeTransaction();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001144 }
1145
1146 void finishRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001147 unfreezeBounds();
1148
Chong Zhangd78ddb42016-03-02 17:01:14 -08001149 if (mPendingRelaunchCount > 0) {
1150 mPendingRelaunchCount--;
Bryce Lee081554b2017-05-25 07:52:12 -07001151 } else {
1152 // Update keyguard flags upon finishing relaunch.
1153 checkKeyguardFlagsChanged();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001154 }
1155 }
1156
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001157 void clearRelaunching() {
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001158 if (mPendingRelaunchCount == 0) {
1159 return;
1160 }
Robert Carr68375192017-06-13 12:41:53 -07001161 unfreezeBounds();
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001162 mPendingRelaunchCount = 0;
1163 }
1164
Wale Ogunwale07bcab72016-10-14 15:30:09 -07001165 /**
1166 * Returns true if the new child window we are adding to this token is considered greater than
1167 * the existing child window in this token in terms of z-order.
1168 */
1169 @Override
1170 protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
1171 WindowState existingWindow) {
1172 final int type1 = newWindow.mAttrs.type;
1173 final int type2 = existingWindow.mAttrs.type;
1174
1175 // Base application windows should be z-ordered BELOW all other windows in the app token.
1176 if (type1 == TYPE_BASE_APPLICATION && type2 != TYPE_BASE_APPLICATION) {
1177 return false;
1178 } else if (type1 != TYPE_BASE_APPLICATION && type2 == TYPE_BASE_APPLICATION) {
1179 return true;
1180 }
1181
1182 // Starting windows should be z-ordered ABOVE all other windows in the app token.
1183 if (type1 == TYPE_APPLICATION_STARTING && type2 != TYPE_APPLICATION_STARTING) {
1184 return true;
1185 } else if (type1 != TYPE_APPLICATION_STARTING && type2 == TYPE_APPLICATION_STARTING) {
1186 return false;
1187 }
1188
1189 // Otherwise the new window is greater than the existing window.
1190 return true;
1191 }
1192
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001193 @Override
Robert Carra1eb4392015-12-10 12:43:51 -08001194 void addWindow(WindowState w) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001195 super.addWindow(w);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001196
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001197 boolean gotReplacementWindow = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001198 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001199 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001200 gotReplacementWindow |= candidate.setReplacementWindowIfNeeded(w);
1201 }
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001202
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001203 // if we got a replacement window, reset the timeout to give drawing more time
1204 if (gotReplacementWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001205 mWmService.scheduleWindowReplacementTimeouts(this);
Robert Carra1eb4392015-12-10 12:43:51 -08001206 }
Jorim Jaggife762342016-10-13 14:33:27 +02001207 checkKeyguardFlagsChanged();
1208 }
1209
1210 @Override
1211 void removeChild(WindowState child) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001212 if (!mChildren.contains(child)) {
1213 // This can be true when testing.
1214 return;
1215 }
Jorim Jaggife762342016-10-13 14:33:27 +02001216 super.removeChild(child);
1217 checkKeyguardFlagsChanged();
Adrian Roos23df3a32018-03-15 15:41:13 +01001218 updateLetterboxSurface(child);
Robert Carra1eb4392015-12-10 12:43:51 -08001219 }
1220
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001221 private boolean waitingForReplacement() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001222 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001223 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001224 if (candidate.waitingForReplacement()) {
Robert Carra1eb4392015-12-10 12:43:51 -08001225 return true;
1226 }
1227 }
1228 return false;
1229 }
1230
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001231 void onWindowReplacementTimeout() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001232 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001233 (mChildren.get(i)).onWindowReplacementTimeout();
Robert Carra1eb4392015-12-10 12:43:51 -08001234 }
1235 }
1236
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001237 void reparent(Task task, int position) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001238 if (DEBUG_ADD_REMOVE) {
1239 Slog.i(TAG_WM, "reparent: moving app token=" + this
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001240 + " to task=" + task.mTaskId + " at " + position);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001241 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001242 if (task == null) {
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001243 throw new IllegalArgumentException("reparent: could not find task");
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001244 }
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001245 final Task currentTask = getTask();
1246 if (task == currentTask) {
Winson Chung30480042017-01-26 10:55:34 -08001247 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001248 "window token=" + this + " already child of task=" + currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001249 }
Bryce Lee6d410262017-02-28 15:30:17 -08001250
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001251 if (currentTask.mStack != task.mStack) {
Bryce Lee6d410262017-02-28 15:30:17 -08001252 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001253 "window token=" + this + " current task=" + currentTask
Bryce Lee6d410262017-02-28 15:30:17 -08001254 + " belongs to a different stack than " + task);
1255 }
1256
Winson Chung30480042017-01-26 10:55:34 -08001257 if (DEBUG_ADD_REMOVE) Slog.i(TAG, "reParentWindowToken: removing window token=" + this
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001258 + " from task=" + currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001259 final DisplayContent prevDisplayContent = getDisplayContent();
1260
Bryce Lee6d410262017-02-28 15:30:17 -08001261 mReparenting = true;
1262
Winson Chung30480042017-01-26 10:55:34 -08001263 getParent().removeChild(this);
1264 task.addChild(this, position);
1265
Bryce Lee6d410262017-02-28 15:30:17 -08001266 mReparenting = false;
1267
Winson Chung30480042017-01-26 10:55:34 -08001268 // Relayout display(s).
1269 final DisplayContent displayContent = task.getDisplayContent();
1270 displayContent.setLayoutNeeded();
1271 if (prevDisplayContent != displayContent) {
1272 onDisplayChanged(displayContent);
1273 prevDisplayContent.setLayoutNeeded();
1274 }
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001275 getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
Winson Chung30480042017-01-26 10:55:34 -08001276 }
1277
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001278 @Override
1279 void onDisplayChanged(DisplayContent dc) {
1280 DisplayContent prevDc = mDisplayContent;
1281 super.onDisplayChanged(dc);
Evan Rosky25b56192019-02-06 16:10:56 -08001282 if (prevDc == null) {
1283 return;
1284 }
1285 if (prevDc.mChangingApps.contains(this)) {
1286 // This gets called *after* the AppWindowToken has been reparented to the new display.
1287 // That reparenting resulted in this window changing modes (eg. FREEFORM -> FULLSCREEN),
1288 // so this token is now "frozen" while waiting for the animation to start on prevDc
1289 // (which will be cancelled since the window is no-longer a child). However, since this
1290 // is no longer a child of prevDc, this won't be notified of the cancelled animation,
1291 // so we need to cancel the change transition here.
1292 clearChangeLeash(getPendingTransaction(), true /* cancel */);
1293 }
1294 if (prevDc.mFocusedApp == this) {
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001295 prevDc.setFocusedApp(null);
lumarkbf844642018-11-23 17:11:36 +08001296 final TaskStack stack = dc.getTopStack();
1297 if (stack != null) {
1298 final Task task = stack.getTopChild();
1299 if (task != null && task.getTopChild() == this) {
1300 dc.setFocusedApp(this);
1301 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001302 }
1303 }
Riddle Hsu192fe762019-01-15 23:41:57 +08001304
1305 if (prevDc != mDisplayContent && mLetterbox != null) {
1306 mLetterbox.onMovedToDisplay(mDisplayContent.getDisplayId());
1307 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001308 }
1309
Jorim Jaggi0429f352015-12-22 16:29:16 +01001310 /**
1311 * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds
1312 * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even
1313 * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen
1314 * with a queue.
1315 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001316 private void freezeBounds() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001317 final Task task = getTask();
1318 mFrozenBounds.offer(new Rect(task.mPreparedFrozenBounds));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001319
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001320 if (task.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001321 // We didn't call prepareFreezingBounds on the task, so use the current value.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001322 mFrozenMergedConfig.offer(new Configuration(task.getConfiguration()));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001323 } else {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001324 mFrozenMergedConfig.offer(new Configuration(task.mPreparedFrozenMergedConfig));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001325 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001326 // Calling unset() to make it equal to Configuration.EMPTY.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001327 task.mPreparedFrozenMergedConfig.unset();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001328 }
1329
1330 /**
1331 * Unfreezes the previously frozen bounds. See {@link #freezeBounds}.
1332 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001333 private void unfreezeBounds() {
Robert Carr68375192017-06-13 12:41:53 -07001334 if (mFrozenBounds.isEmpty()) {
1335 return;
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001336 }
Robert Carr68375192017-06-13 12:41:53 -07001337 mFrozenBounds.remove();
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001338 if (!mFrozenMergedConfig.isEmpty()) {
1339 mFrozenMergedConfig.remove();
1340 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001341 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001342 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001343 win.onUnfreezeBounds();
Jorim Jaggi4846ee32016-01-07 17:39:12 +01001344 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001345 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001346 }
1347
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001348 void setAppLayoutChanges(int changes, String reason) {
1349 if (!mChildren.isEmpty()) {
1350 final DisplayContent dc = getDisplayContent();
1351 dc.pendingLayoutChanges |= changes;
1352 if (DEBUG_LAYOUT_REPEATS) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001353 mWmService.mWindowPlacerLocked.debugLayoutRepeats(reason, dc.pendingLayoutChanges);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001354 }
1355 }
1356 }
1357
1358 void removeReplacedWindowIfNeeded(WindowState replacement) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001359 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001360 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001361 if (win.removeReplacedWindowIfNeeded(replacement)) {
1362 return;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001363 }
1364 }
1365 }
1366
1367 void startFreezingScreen() {
1368 if (DEBUG_ORIENTATION) logWithStack(TAG, "Set freezing of " + appToken + ": hidden="
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001369 + isHidden() + " freezing=" + mFreezingScreen + " hiddenRequested="
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001370 + hiddenRequested);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001371 if (!hiddenRequested) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001372 if (!mFreezingScreen) {
1373 mFreezingScreen = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001374 mWmService.registerAppFreezeListener(this);
1375 mWmService.mAppsFreezingScreen++;
1376 if (mWmService.mAppsFreezingScreen == 1) {
1377 mWmService.startFreezingDisplayLocked(0, 0, getDisplayContent());
1378 mWmService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
1379 mWmService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001380 }
1381 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001382 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001383 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001384 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001385 w.onStartFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001386 }
1387 }
1388 }
1389
1390 void stopFreezingScreen(boolean unfreezeSurfaceNow, boolean force) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001391 if (!mFreezingScreen) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001392 return;
1393 }
1394 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + this + " force=" + force);
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001395 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001396 boolean unfrozeWindows = false;
1397 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001398 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001399 unfrozeWindows |= w.onStopFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001400 }
1401 if (force || unfrozeWindows) {
1402 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "No longer freezing: " + this);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001403 mFreezingScreen = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001404 mWmService.unregisterAppFreezeListener(this);
1405 mWmService.mAppsFreezingScreen--;
1406 mWmService.mLastFinishedFreezeSource = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001407 }
1408 if (unfreezeSurfaceNow) {
1409 if (unfrozeWindows) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001410 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001411 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001412 mWmService.stopFreezingDisplayLocked();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001413 }
1414 }
1415
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001416 @Override
1417 public void onAppFreezeTimeout() {
1418 Slog.w(TAG_WM, "Force clearing freeze: " + this);
1419 stopFreezingScreen(true, true);
1420 }
1421
Jorim Jaggi60f9c972018-02-01 19:21:07 +01001422 /**
1423 * Tries to transfer the starting window from a token that's above ourselves in the task but
1424 * not visible anymore. This is a common scenario apps use: Trampoline activity T start main
1425 * activity M in the same task. Now, when reopening the task, T starts on top of M but then
1426 * immediately finishes after, so we have to transfer T to M.
1427 */
1428 void transferStartingWindowFromHiddenAboveTokenIfNeeded() {
1429 final Task task = getTask();
1430 for (int i = task.mChildren.size() - 1; i >= 0; i--) {
1431 final AppWindowToken fromToken = task.mChildren.get(i);
1432 if (fromToken == this) {
1433 return;
1434 }
1435 if (fromToken.hiddenRequested && transferStartingWindow(fromToken.token)) {
1436 return;
1437 }
1438 }
1439 }
1440
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001441 boolean transferStartingWindow(IBinder transferFrom) {
Wale Ogunwale02319a62016-09-26 15:21:22 -07001442 final AppWindowToken fromToken = getDisplayContent().getAppWindowToken(transferFrom);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001443 if (fromToken == null) {
1444 return false;
1445 }
1446
1447 final WindowState tStartingWindow = fromToken.startingWindow;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08001448 if (tStartingWindow != null && fromToken.startingSurface != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001449 // In this case, the starting icon has already been displayed, so start
1450 // letting windows get shown immediately without any more transitions.
lumark588a3e82018-07-20 18:53:54 +08001451 getDisplayContent().mSkipAppTransitionAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001452
1453 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Moving existing starting " + tStartingWindow
1454 + " from " + fromToken + " to " + this);
1455
1456 final long origId = Binder.clearCallingIdentity();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001457 try {
1458 // Transfer the starting window over to the new token.
1459 startingData = fromToken.startingData;
1460 startingSurface = fromToken.startingSurface;
1461 startingDisplayed = fromToken.startingDisplayed;
1462 fromToken.startingDisplayed = false;
1463 startingWindow = tStartingWindow;
1464 reportedVisible = fromToken.reportedVisible;
1465 fromToken.startingData = null;
1466 fromToken.startingSurface = null;
1467 fromToken.startingWindow = null;
1468 fromToken.startingMoved = true;
1469 tStartingWindow.mToken = this;
1470 tStartingWindow.mAppToken = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001471
Peter Visontay3556a3b2017-11-01 17:23:17 +00001472 if (DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
1473 "Removing starting " + tStartingWindow + " from " + fromToken);
1474 fromToken.removeChild(tStartingWindow);
1475 fromToken.postWindowRemoveStartingWindowCleanup(tStartingWindow);
1476 fromToken.mHiddenSetFromTransferredStartingWindow = false;
1477 addWindow(tStartingWindow);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001478
Peter Visontay3556a3b2017-11-01 17:23:17 +00001479 // Propagate other interesting state between the tokens. If the old token is displayed,
1480 // we should immediately force the new one to be displayed. If it is animating, we need
1481 // to move that animation to the new one.
1482 if (fromToken.allDrawn) {
1483 allDrawn = true;
1484 deferClearAllDrawn = fromToken.deferClearAllDrawn;
1485 }
1486 if (fromToken.firstWindowDrawn) {
1487 firstWindowDrawn = true;
1488 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001489 if (!fromToken.isHidden()) {
1490 setHidden(false);
Peter Visontay3556a3b2017-11-01 17:23:17 +00001491 hiddenRequested = false;
1492 mHiddenSetFromTransferredStartingWindow = true;
1493 }
1494 setClientHidden(fromToken.mClientHidden);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001495
Jorim Jaggi980c9de2017-11-17 01:41:37 +01001496 transferAnimation(fromToken);
1497
1498 // When transferring an animation, we no longer need to apply an animation to the
1499 // the token we transfer the animation over. Thus, remove the animation from
1500 // pending opening apps.
lumark588a3e82018-07-20 18:53:54 +08001501 getDisplayContent().mOpeningApps.remove(this);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001502
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001503 mWmService.updateFocusedWindowLocked(
Peter Visontay3556a3b2017-11-01 17:23:17 +00001504 UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/);
1505 getDisplayContent().setLayoutNeeded();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001506 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001507 } finally {
1508 Binder.restoreCallingIdentity(origId);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001509 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001510 return true;
1511 } else if (fromToken.startingData != null) {
1512 // The previous app was getting ready to show a
1513 // starting window, but hasn't yet done so. Steal it!
1514 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
1515 "Moving pending starting from " + fromToken + " to " + this);
1516 startingData = fromToken.startingData;
1517 fromToken.startingData = null;
1518 fromToken.startingMoved = true;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001519 scheduleAddStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001520 return true;
1521 }
1522
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001523 // TODO: Transfer thumbnail
1524
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001525 return false;
1526 }
1527
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001528 boolean isLastWindow(WindowState win) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001529 return mChildren.size() == 1 && mChildren.get(0) == win;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001530 }
1531
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001532 @Override
1533 void onAppTransitionDone() {
1534 sendingToBottom = false;
1535 }
1536
Wale Ogunwale51362492016-09-08 17:49:17 -07001537 /**
1538 * We override because this class doesn't want its children affecting its reported orientation
1539 * in anyway.
1540 */
1541 @Override
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001542 int getOrientation(int candidate) {
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001543 if (candidate == SCREEN_ORIENTATION_BEHIND) {
1544 // Allow app to specify orientation regardless of its visibility state if the current
1545 // candidate want us to use orientation behind. I.e. the visible app on-top of this one
1546 // wants us to use the orientation of the app behind it.
1547 return mOrientation;
1548 }
1549
Bryce Lee61fbcbc2017-03-10 14:14:03 -08001550 // The {@link AppWindowToken} should only specify an orientation when it is not closing or
1551 // going to the bottom. Allowing closing {@link AppWindowToken} to participate can lead to
1552 // an Activity in another task being started in the wrong orientation during the transition.
lumark588a3e82018-07-20 18:53:54 +08001553 if (!(sendingToBottom || getDisplayContent().mClosingApps.contains(this))
1554 && (isVisible() || getDisplayContent().mOpeningApps.contains(this))) {
Bryce Leea163b762017-01-24 11:05:01 -08001555 return mOrientation;
Wale Ogunwale51362492016-09-08 17:49:17 -07001556 }
Bryce Leea163b762017-01-24 11:05:01 -08001557
1558 return SCREEN_ORIENTATION_UNSET;
Wale Ogunwale51362492016-09-08 17:49:17 -07001559 }
1560
Wale Ogunwaleb198b742016-12-01 08:44:09 -08001561 /** Returns the app's preferred orientation regardless of its currently visibility state. */
1562 int getOrientationIgnoreVisibility() {
1563 return mOrientation;
1564 }
1565
Craig Mautnerdbb79912012-03-01 18:59:14 -08001566 @Override
Winson Chunge55c0192017-08-24 14:50:48 -07001567 public void onConfigurationChanged(Configuration newParentConfig) {
1568 final int prevWinMode = getWindowingMode();
Evan Rosky2289ba12018-11-19 18:28:18 -08001569 mTmpPrevBounds.set(getBounds());
Winson Chunge55c0192017-08-24 14:50:48 -07001570 super.onConfigurationChanged(newParentConfig);
1571 final int winMode = getWindowingMode();
1572
1573 if (prevWinMode == winMode) {
1574 return;
1575 }
1576
1577 if (prevWinMode != WINDOWING_MODE_UNDEFINED && winMode == WINDOWING_MODE_PINNED) {
1578 // Entering PiP from fullscreen, reset the snap fraction
1579 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(this);
Winson Chung82267ce2018-04-06 16:38:26 -07001580 } else if (prevWinMode == WINDOWING_MODE_PINNED && winMode != WINDOWING_MODE_UNDEFINED
1581 && !isHidden()) {
Winson Chunge55c0192017-08-24 14:50:48 -07001582 // Leaving PiP to fullscreen, save the snap fraction based on the pre-animation bounds
1583 // for the next re-entry into PiP (assuming the activity is not hidden or destroyed)
1584 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
1585 if (pinnedStack != null) {
Winson Chung8efa1652018-06-06 09:34:23 -07001586 final Rect stackBounds;
1587 if (pinnedStack.lastAnimatingBoundsWasToFullscreen()) {
1588 // We are animating the bounds, use the pre-animation bounds to save the snap
1589 // fraction
1590 stackBounds = pinnedStack.mPreAnimationBounds;
1591 } else {
1592 // We skip the animation if the fullscreen configuration is not compatible, so
1593 // use the current bounds to calculate the saved snap fraction instead
1594 // (see PinnedActivityStack.skipResizeAnimation())
1595 stackBounds = mTmpRect;
1596 pinnedStack.getBounds(stackBounds);
1597 }
Winson Chunge55c0192017-08-24 14:50:48 -07001598 mDisplayContent.mPinnedStackControllerLocked.saveReentrySnapFraction(this,
Winson Chung8efa1652018-06-06 09:34:23 -07001599 stackBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001600 }
Evan Rosky2289ba12018-11-19 18:28:18 -08001601 } else if (shouldStartChangeTransition(prevWinMode, winMode)) {
1602 initializeChangeTransition(mTmpPrevBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001603 }
1604 }
1605
Evan Rosky2289ba12018-11-19 18:28:18 -08001606 private boolean shouldStartChangeTransition(int prevWinMode, int newWinMode) {
Evan Rosky25b56192019-02-06 16:10:56 -08001607 if (mWmService.mDisableTransitionAnimation
1608 || !isVisible()
1609 || getDisplayContent().mAppTransition.isTransitionSet()
1610 || getSurfaceControl() == null) {
Evan Rosky2289ba12018-11-19 18:28:18 -08001611 return false;
1612 }
1613 // Only do an animation into and out-of freeform mode for now. Other mode
1614 // transition animations are currently handled by system-ui.
1615 return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
1616 }
1617
1618 /**
1619 * Initializes a change transition. Because the app is visible already, there is a small period
1620 * of time where the user can see the app content/window update before the transition starts.
1621 * To prevent this, we immediately take a snapshot and place the app/snapshot into a leash which
1622 * "freezes" the location/crop until the transition starts.
1623 * <p>
1624 * Here's a walk-through of the process:
1625 * 1. Create a temporary leash ("interim-change-leash") and reparent the app to it.
1626 * 2. Set the temporary leash's position/crop to the current state.
1627 * 3. Create a snapshot and place that at the top of the leash to cover up content changes.
1628 * 4. Once the transition is ready, it will reparent the app to the animation leash.
1629 * 5. Detach the interim-change-leash.
1630 */
1631 private void initializeChangeTransition(Rect startBounds) {
1632 mDisplayContent.prepareAppTransition(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
1633 false /* alwaysKeepCurrent */, 0, false /* forceOverride */);
1634 mDisplayContent.mChangingApps.add(this);
1635 mTransitStartRect.set(startBounds);
1636
1637 final SurfaceControl.Builder builder = makeAnimationLeash()
1638 .setParent(getAnimationLeashParent())
1639 .setName(getSurfaceControl() + " - interim-change-leash");
1640 mTransitChangeLeash = builder.build();
1641 Transaction t = getPendingTransaction();
1642 t.setWindowCrop(mTransitChangeLeash, startBounds.width(), startBounds.height());
1643 t.setPosition(mTransitChangeLeash, startBounds.left, startBounds.top);
1644 t.show(mTransitChangeLeash);
1645 t.reparent(getSurfaceControl(), mTransitChangeLeash);
1646 onAnimationLeashCreated(t, mTransitChangeLeash);
1647
Evan Rosky966759f2019-01-15 10:33:58 -08001648 // Skip creating snapshot if this transition is controlled by a remote animator which
1649 // doesn't need it.
1650 ArraySet<Integer> activityTypes = new ArraySet<>();
1651 activityTypes.add(getActivityType());
1652 RemoteAnimationAdapter adapter =
1653 mDisplayContent.mAppTransitionController.getRemoteAnimationOverride(
1654 this, TRANSIT_TASK_CHANGE_WINDOWING_MODE, activityTypes);
1655 if (adapter != null && !adapter.getChangeNeedsSnapshot()) {
1656 return;
1657 }
1658
Evan Rosky2289ba12018-11-19 18:28:18 -08001659 if (mThumbnail == null && getTask() != null) {
1660 final TaskSnapshotController snapshotCtrl = mWmService.mTaskSnapshotController;
1661 final ArraySet<Task> tasks = new ArraySet<>();
1662 tasks.add(getTask());
1663 snapshotCtrl.snapshotTasks(tasks);
1664 snapshotCtrl.addSkipClosingAppSnapshotTasks(tasks);
1665 final ActivityManager.TaskSnapshot snapshot = snapshotCtrl.getSnapshot(
1666 getTask().mTaskId, getTask().mUserId, false /* restoreFromDisk */,
1667 false /* reducedResolution */);
1668 mThumbnail = new AppWindowThumbnail(t, this, snapshot.getSnapshot(),
1669 true /* relative */);
1670 }
1671 }
1672
1673 boolean isInChangeTransition() {
1674 return mTransitChangeLeash != null || isChangeTransition(mTransit);
1675 }
1676
Evan Rosky966759f2019-01-15 10:33:58 -08001677 @VisibleForTesting
1678 AppWindowThumbnail getThumbnail() {
1679 return mThumbnail;
1680 }
1681
Winson Chunge55c0192017-08-24 14:50:48 -07001682 @Override
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001683 void checkAppWindowsReadyToShow() {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001684 if (allDrawn == mLastAllDrawn) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001685 return;
1686 }
1687
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001688 mLastAllDrawn = allDrawn;
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001689 if (!allDrawn) {
1690 return;
1691 }
1692
1693 // The token has now changed state to having all windows shown... what to do, what to do?
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001694 if (mFreezingScreen) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001695 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001696 stopFreezingScreen(false, true);
1697 if (DEBUG_ORIENTATION) Slog.i(TAG,
1698 "Setting mOrientationChangeComplete=true because wtoken " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001699 + " numInteresting=" + mNumInterestingWindows + " numDrawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001700 // This will set mOrientationChangeComplete and cause a pass through layout.
1701 setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001702 "checkAppWindowsReadyToShow: freezingScreen");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001703 } else {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001704 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001705
1706 // We can now show all of the drawn windows!
lumark588a3e82018-07-20 18:53:54 +08001707 if (!getDisplayContent().mOpeningApps.contains(this) && canShowWindows()) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001708 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001709 }
1710 }
1711 }
1712
Matthew Ng5d23afa2017-06-21 16:16:24 -07001713 /**
Bryce Leed390deb2017-06-22 13:14:28 -07001714 * Returns whether the drawn window states of this {@link AppWindowToken} has considered every
1715 * child {@link WindowState}. A child is considered if it has been passed into
1716 * {@link #updateDrawnWindowStates(WindowState)} after being added. This is used to determine
1717 * whether states, such as {@code allDrawn}, can be set, which relies on state variables such as
1718 * {@code mNumInterestingWindows}, which depend on all {@link WindowState}s being considered.
1719 *
1720 * @return {@code true} If all children have been considered, {@code false}.
1721 */
1722 private boolean allDrawnStatesConsidered() {
Bryce Lee6311c4b2017-07-06 14:09:29 -07001723 for (int i = mChildren.size() - 1; i >= 0; --i) {
1724 final WindowState child = mChildren.get(i);
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001725 if (child.mightAffectAllDrawn() && !child.getDrawnStateEvaluated()) {
Bryce Leed390deb2017-06-22 13:14:28 -07001726 return false;
1727 }
1728 }
1729 return true;
1730 }
1731
1732 /**
Matthew Ng5d23afa2017-06-21 16:16:24 -07001733 * Determines if the token has finished drawing. This should only be called from
1734 * {@link DisplayContent#applySurfaceChangesTransaction}
1735 */
Matthew Ng498c71d2017-04-18 13:55:45 -07001736 void updateAllDrawn() {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001737 if (!allDrawn) {
Matthew Ng498c71d2017-04-18 13:55:45 -07001738 // Number of drawn windows can be less when a window is being relaunched, wait for
Bryce Leed390deb2017-06-22 13:14:28 -07001739 // all windows to be launched and drawn for this token be considered all drawn.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001740 final int numInteresting = mNumInterestingWindows;
Bryce Leed390deb2017-06-22 13:14:28 -07001741
1742 // We must make sure that all present children have been considered (determined by
1743 // {@link #allDrawnStatesConsidered}) before evaluating whether everything has been
1744 // drawn.
1745 if (numInteresting > 0 && allDrawnStatesConsidered()
1746 && mNumDrawnWindows >= numInteresting && !isRelaunching()) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001747 if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawn: " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001748 + " interesting=" + numInteresting + " drawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001749 allDrawn = true;
1750 // Force an additional layout pass where
1751 // WindowStateAnimator#commitFinishDrawingLocked() will call performShowLocked().
Matthew Ng498c71d2017-04-18 13:55:45 -07001752 if (mDisplayContent != null) {
1753 mDisplayContent.setLayoutNeeded();
1754 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001755 mWmService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
Robert Carrecc06b32017-04-18 14:25:10 -07001756
Winson Chunge7ba6862017-05-24 12:13:33 -07001757 // Notify the pinned stack upon all windows drawn. If there was an animation in
1758 // progress then this signal will resume that animation.
Wale Ogunwale61911492017-10-11 08:50:50 -07001759 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
Winson Chunge7ba6862017-05-24 12:13:33 -07001760 if (pinnedStack != null) {
1761 pinnedStack.onAllWindowsDrawn();
Robert Carrecc06b32017-04-18 14:25:10 -07001762 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001763 }
1764 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001765 }
1766
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001767 boolean keyDispatchingTimedOut(String reason, int windowPid) {
1768 return mActivityRecord != null && mActivityRecord.keyDispatchingTimedOut(reason, windowPid);
1769 }
1770
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001771 /**
1772 * Updated this app token tracking states for interesting and drawn windows based on the window.
1773 *
1774 * @return Returns true if the input window is considered interesting and drawn while all the
1775 * windows in this app token where not considered drawn as of the last pass.
1776 */
1777 boolean updateDrawnWindowStates(WindowState w) {
Bryce Leed390deb2017-06-22 13:14:28 -07001778 w.setDrawnStateEvaluated(true /*evaluated*/);
1779
Jorim Jaggie4b0f282017-05-17 15:10:29 +02001780 if (DEBUG_STARTING_WINDOW_VERBOSE && w == startingWindow) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001781 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + w.isOnScreen()
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001782 + " allDrawn=" + allDrawn + " freezingScreen=" + mFreezingScreen);
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001783 }
1784
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001785 if (allDrawn && !mFreezingScreen) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001786 return false;
1787 }
1788
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001789 if (mLastTransactionSequence != mWmService.mTransactionSequence) {
1790 mLastTransactionSequence = mWmService.mTransactionSequence;
Matthew Ng53e66b22018-01-12 17:13:13 -08001791 mNumDrawnWindows = 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001792 startingDisplayed = false;
Matthew Ng53e66b22018-01-12 17:13:13 -08001793
1794 // There is the main base application window, even if it is exiting, wait for it
1795 mNumInterestingWindows = findMainWindow(false /* includeStartingApp */) != null ? 1 : 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001796 }
1797
1798 final WindowStateAnimator winAnimator = w.mWinAnimator;
1799
1800 boolean isInterestingAndDrawn = false;
1801
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001802 if (!allDrawn && w.mightAffectAllDrawn()) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001803 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
1804 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001805 + ", isAnimationSet=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001806 if (!w.isDrawnLw()) {
1807 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController
1808 + " pv=" + w.mPolicyVisibility
1809 + " mDrawState=" + winAnimator.drawStateToString()
1810 + " ph=" + w.isParentWindowHidden() + " th=" + hiddenRequested
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001811 + " a=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001812 }
1813 }
1814
1815 if (w != startingWindow) {
1816 if (w.isInteresting()) {
Matthew Ng53e66b22018-01-12 17:13:13 -08001817 // Add non-main window as interesting since the main app has already been added
1818 if (findMainWindow(false /* includeStartingApp */) != w) {
1819 mNumInterestingWindows++;
1820 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001821 if (w.isDrawnLw()) {
1822 mNumDrawnWindows++;
1823
1824 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, "tokenMayBeDrawn: "
1825 + this + " w=" + w + " numInteresting=" + mNumInterestingWindows
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001826 + " freezingScreen=" + mFreezingScreen
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001827 + " mAppFreezing=" + w.mAppFreezing);
1828
1829 isInterestingAndDrawn = true;
1830 }
1831 }
1832 } else if (w.isDrawnLw()) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001833 if (mActivityRecord != null) {
1834 mActivityRecord.onStartingWindowDrawn(SystemClock.uptimeMillis());
Jorim Jaggi3878ca32017-02-02 17:13:05 -08001835 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001836 startingDisplayed = true;
1837 }
1838 }
1839
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001840 return isInterestingAndDrawn;
1841 }
1842
Adrian Roos23df3a32018-03-15 15:41:13 +01001843 void layoutLetterbox(WindowState winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001844 final WindowState w = findMainWindow();
Adrian Roosf93b6d22018-03-21 13:48:26 +01001845 if (w == null || winHint != null && w != winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001846 return;
1847 }
Jorim Jaggia32da382018-03-28 18:01:22 +02001848 final boolean surfaceReady = w.isDrawnLw() // Regular case
Adrian Roosf93b6d22018-03-21 13:48:26 +01001849 || w.mWinAnimator.mSurfaceDestroyDeferred // The preserved surface is still ready.
1850 || w.isDragResizeChanged(); // Waiting for relayoutWindow to call preserveSurface.
1851 final boolean needsLetterbox = w.isLetterboxedAppWindow() && fillsParent() && surfaceReady;
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001852 if (needsLetterbox) {
1853 if (mLetterbox == null) {
1854 mLetterbox = new Letterbox(() -> makeChildSurface(null));
Riddle Hsu192fe762019-01-15 23:41:57 +08001855 mLetterbox.attachInput(w);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001856 }
Adrian Roos7af9d972018-11-30 15:26:27 +01001857 getPosition(mTmpPoint);
1858 mLetterbox.layout(getParent().getBounds(), w.getFrameLw(), mTmpPoint);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001859 } else if (mLetterbox != null) {
Adrian Roos23df3a32018-03-15 15:41:13 +01001860 mLetterbox.hide();
1861 }
1862 }
1863
1864 void updateLetterboxSurface(WindowState winHint) {
1865 final WindowState w = findMainWindow();
1866 if (w != winHint && winHint != null && w != null) {
1867 return;
1868 }
1869 layoutLetterbox(winHint);
1870 if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) {
1871 mLetterbox.applySurfaceChanges(mPendingTransaction);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001872 }
1873 }
1874
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001875 @Override
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001876 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001877 // For legacy reasons we process the TaskStack.mExitingAppTokens first in DisplayContent
1878 // before the non-exiting app tokens. So, we skip the exiting app tokens here.
1879 // TODO: Investigate if we need to continue to do this or if we can just process them
1880 // in-order.
1881 if (mIsExiting && !waitingForReplacement()) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001882 return false;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001883 }
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001884 return forAllWindowsUnchecked(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001885 }
1886
lumark588a3e82018-07-20 18:53:54 +08001887 @Override
1888 void forAllAppWindows(Consumer<AppWindowToken> callback) {
1889 callback.accept(this);
1890 }
1891
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001892 boolean forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback,
1893 boolean traverseTopToBottom) {
1894 return super.forAllWindows(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001895 }
1896
1897 @Override
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07001898 AppWindowToken asAppWindowToken() {
1899 // I am an app window token!
1900 return this;
1901 }
1902
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001903 boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
1904 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
1905 IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
1906 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
1907 // If the display is frozen, we won't do anything until the actual window is
1908 // displayed so there is no reason to put in the starting window.
1909 if (!okToDisplay()) {
1910 return false;
1911 }
1912
1913 if (startingData != null) {
1914 return false;
1915 }
1916
1917 final WindowState mainWin = findMainWindow();
1918 if (mainWin != null && mainWin.mWinAnimator.getShown()) {
1919 // App already has a visible window...why would you want a starting window?
1920 return false;
1921 }
1922
1923 final ActivityManager.TaskSnapshot snapshot =
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001924 mWmService.mTaskSnapshotController.getSnapshot(
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001925 getTask().mTaskId, getTask().mUserId,
1926 false /* restoreFromDisk */, false /* reducedResolution */);
1927 final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
1928 allowTaskSnapshot, activityCreated, fromRecents, snapshot);
1929
1930 if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
1931 return createSnapshot(snapshot);
1932 }
1933
1934 // If this is a translucent window, then don't show a starting window -- the current
1935 // effect (a full-screen opaque starting window that fades away to the real contents
1936 // when it is ready) does not work for this.
1937 if (DEBUG_STARTING_WINDOW) {
1938 Slog.v(TAG, "Checking theme of starting window: 0x" + Integer.toHexString(theme));
1939 }
1940 if (theme != 0) {
1941 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
1942 com.android.internal.R.styleable.Window,
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001943 mWmService.mCurrentUserId);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001944 if (ent == null) {
1945 // Whoops! App doesn't exist. Um. Okay. We'll just pretend like we didn't
1946 // see that.
1947 return false;
1948 }
1949 final boolean windowIsTranslucent = ent.array.getBoolean(
1950 com.android.internal.R.styleable.Window_windowIsTranslucent, false);
1951 final boolean windowIsFloating = ent.array.getBoolean(
1952 com.android.internal.R.styleable.Window_windowIsFloating, false);
1953 final boolean windowShowWallpaper = ent.array.getBoolean(
1954 com.android.internal.R.styleable.Window_windowShowWallpaper, false);
1955 final boolean windowDisableStarting = ent.array.getBoolean(
1956 com.android.internal.R.styleable.Window_windowDisablePreview, false);
1957 if (DEBUG_STARTING_WINDOW) {
1958 Slog.v(TAG, "Translucent=" + windowIsTranslucent
1959 + " Floating=" + windowIsFloating
1960 + " ShowWallpaper=" + windowShowWallpaper);
1961 }
1962 if (windowIsTranslucent) {
1963 return false;
1964 }
1965 if (windowIsFloating || windowDisableStarting) {
1966 return false;
1967 }
1968 if (windowShowWallpaper) {
1969 if (getDisplayContent().mWallpaperController
1970 .getWallpaperTarget() == null) {
1971 // If this theme is requesting a wallpaper, and the wallpaper
1972 // is not currently visible, then this effectively serves as
1973 // an opaque window and our starting window transition animation
1974 // can still work. We just need to make sure the starting window
1975 // is also showing the wallpaper.
1976 windowFlags |= FLAG_SHOW_WALLPAPER;
1977 } else {
1978 return false;
1979 }
1980 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001981 }
Yunfan Chen8a8c0ed2018-12-18 16:46:32 -08001982
1983 if (transferStartingWindow(transferFrom)) {
1984 return true;
1985 }
1986
1987 // There is no existing starting window, and we don't want to create a splash screen, so
1988 // that's it!
1989 if (type != STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
1990 return false;
1991 }
1992
1993 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SplashScreenStartingData");
1994 startingData = new SplashScreenStartingData(mWmService, pkg,
1995 theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
1996 getMergedOverrideConfiguration());
1997 scheduleAddStartingWindow();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001998 return true;
1999 }
2000
2001
2002 private boolean createSnapshot(ActivityManager.TaskSnapshot snapshot) {
2003 if (snapshot == null) {
2004 return false;
2005 }
2006
2007 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SnapshotStartingData");
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002008 startingData = new SnapshotStartingData(mWmService, snapshot);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002009 scheduleAddStartingWindow();
2010 return true;
2011 }
2012
2013 void scheduleAddStartingWindow() {
2014 // Note: we really want to do sendMessageAtFrontOfQueue() because we
2015 // want to process the message ASAP, before any other queued
2016 // messages.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002017 if (!mWmService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002018 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING");
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002019 mWmService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002020 }
2021 }
2022
2023 private final Runnable mAddStartingWindow = new Runnable() {
2024
2025 @Override
2026 public void run() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002027 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002028 // There can only be one adding request, silly caller!
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002029 mWmService.mAnimationHandler.removeCallbacks(this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002030 }
2031
2032 if (startingData == null) {
2033 // Animation has been canceled... do nothing.
2034 if (DEBUG_STARTING_WINDOW) {
2035 Slog.v(TAG, "startingData was nulled out before handling"
2036 + " mAddStartingWindow: " + AppWindowToken.this);
2037 }
2038 return;
2039 }
2040
2041 if (DEBUG_STARTING_WINDOW) {
2042 Slog.v(TAG, "Add starting " + this + ": startingData=" + startingData);
2043 }
2044
2045 WindowManagerPolicy.StartingSurface surface = null;
2046 try {
2047 surface = startingData.createStartingSurface(AppWindowToken.this);
2048 } catch (Exception e) {
2049 Slog.w(TAG, "Exception when adding starting window", e);
2050 }
2051 if (surface != null) {
2052 boolean abort = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002053 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002054 // If the window was successfully added, then
2055 // we need to remove it.
2056 if (removed || startingData == null) {
2057 if (DEBUG_STARTING_WINDOW) {
2058 Slog.v(TAG, "Aborted starting " + AppWindowToken.this
2059 + ": removed=" + removed + " startingData=" + startingData);
2060 }
2061 startingWindow = null;
2062 startingData = null;
2063 abort = true;
2064 } else {
2065 startingSurface = surface;
2066 }
2067 if (DEBUG_STARTING_WINDOW && !abort) {
2068 Slog.v(TAG, "Added starting " + AppWindowToken.this + ": startingWindow="
2069 + startingWindow + " startingView=" + startingSurface);
2070 }
2071 }
2072 if (abort) {
2073 surface.remove();
2074 }
2075 } else if (DEBUG_STARTING_WINDOW) {
2076 Slog.v(TAG, "Surface returned was null: " + AppWindowToken.this);
2077 }
2078 }
2079 };
2080
2081 private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
2082 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents,
2083 ActivityManager.TaskSnapshot snapshot) {
2084 if (getDisplayContent().mAppTransition.getAppTransition()
2085 == TRANSIT_DOCK_TASK_FROM_RECENTS) {
2086 // TODO(b/34099271): Remove this statement to add back the starting window and figure
2087 // out why it causes flickering, the starting window appears over the thumbnail while
2088 // the docked from recents transition occurs
2089 return STARTING_WINDOW_TYPE_NONE;
2090 } else if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
2091 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2092 } else if (taskSwitch && allowTaskSnapshot) {
Kevin716a9db2018-12-18 16:53:39 -08002093 if (mWmService.mLowRamTaskSnapshotsAndRecents) {
Kevin58b47f12018-12-17 14:09:01 -08002094 // For low RAM devices, we use the splash screen starting window instead of the
2095 // task snapshot starting window.
2096 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2097 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002098 return snapshot == null ? STARTING_WINDOW_TYPE_NONE
2099 : snapshotOrientationSameAsTask(snapshot) || fromRecents
2100 ? STARTING_WINDOW_TYPE_SNAPSHOT : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2101 } else {
2102 return STARTING_WINDOW_TYPE_NONE;
2103 }
2104 }
2105
2106
2107 private boolean snapshotOrientationSameAsTask(ActivityManager.TaskSnapshot snapshot) {
2108 if (snapshot == null) {
2109 return false;
2110 }
2111 return getTask().getConfiguration().orientation == snapshot.getOrientation();
2112 }
2113
2114 void removeStartingWindow() {
2115 if (startingWindow == null) {
2116 if (startingData != null) {
2117 // Starting window has not been added yet, but it is scheduled to be added.
2118 // Go ahead and cancel the request.
2119 if (DEBUG_STARTING_WINDOW) {
2120 Slog.v(TAG_WM, "Clearing startingData for token=" + this);
2121 }
2122 startingData = null;
2123 }
2124 return;
2125 }
2126
2127 final WindowManagerPolicy.StartingSurface surface;
2128 if (startingData != null) {
2129 surface = startingSurface;
2130 startingData = null;
2131 startingSurface = null;
2132 startingWindow = null;
2133 startingDisplayed = false;
2134 if (surface == null) {
2135 if (DEBUG_STARTING_WINDOW) {
2136 Slog.v(TAG_WM, "startingWindow was set but startingSurface==null, couldn't "
2137 + "remove");
2138 }
2139 return;
2140 }
2141 } else {
2142 if (DEBUG_STARTING_WINDOW) {
2143 Slog.v(TAG_WM, "Tried to remove starting window but startingWindow was null:"
2144 + this);
2145 }
2146 return;
2147 }
2148
2149 if (DEBUG_STARTING_WINDOW) {
2150 Slog.v(TAG_WM, "Schedule remove starting " + this
2151 + " startingWindow=" + startingWindow
2152 + " startingView=" + startingSurface
2153 + " Callers=" + Debug.getCallers(5));
2154 }
2155
2156 // Use the same thread to remove the window as we used to add it, as otherwise we end up
2157 // with things in the view hierarchy being called from different threads.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002158 mWmService.mAnimationHandler.post(() -> {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002159 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Removing startingView=" + surface);
2160 try {
2161 surface.remove();
2162 } catch (Exception e) {
2163 Slog.w(TAG_WM, "Exception when removing starting window", e);
2164 }
2165 });
2166 }
2167
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002168 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -07002169 boolean fillsParent() {
2170 return mFillsParent;
2171 }
2172
2173 void setFillsParent(boolean fillsParent) {
2174 mFillsParent = fillsParent;
2175 }
2176
Jorim Jaggife762342016-10-13 14:33:27 +02002177 boolean containsDismissKeyguardWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002178 // Window state is transient during relaunch. We are not guaranteed to be frozen during the
2179 // entirety of the relaunch.
2180 if (isRelaunching()) {
2181 return mLastContainsDismissKeyguardWindow;
2182 }
2183
Jorim Jaggife762342016-10-13 14:33:27 +02002184 for (int i = mChildren.size() - 1; i >= 0; i--) {
2185 if ((mChildren.get(i).mAttrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
2186 return true;
2187 }
2188 }
2189 return false;
2190 }
2191
2192 boolean containsShowWhenLockedWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002193 // When we are relaunching, it is possible for us to be unfrozen before our previous
2194 // windows have been added back. Using the cached value ensures that our previous
2195 // showWhenLocked preference is honored until relaunching is complete.
2196 if (isRelaunching()) {
2197 return mLastContainsShowWhenLockedWindow;
2198 }
2199
Jorim Jaggife762342016-10-13 14:33:27 +02002200 for (int i = mChildren.size() - 1; i >= 0; i--) {
2201 if ((mChildren.get(i).mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
2202 return true;
2203 }
2204 }
Bryce Lee081554b2017-05-25 07:52:12 -07002205
Jorim Jaggife762342016-10-13 14:33:27 +02002206 return false;
2207 }
2208
2209 void checkKeyguardFlagsChanged() {
2210 final boolean containsDismissKeyguard = containsDismissKeyguardWindow();
2211 final boolean containsShowWhenLocked = containsShowWhenLockedWindow();
2212 if (containsDismissKeyguard != mLastContainsDismissKeyguardWindow
2213 || containsShowWhenLocked != mLastContainsShowWhenLockedWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002214 mWmService.notifyKeyguardFlagsChanged(null /* callback */,
lumark588a3e82018-07-20 18:53:54 +08002215 getDisplayContent().getDisplayId());
Jorim Jaggife762342016-10-13 14:33:27 +02002216 }
2217 mLastContainsDismissKeyguardWindow = containsDismissKeyguard;
2218 mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
2219 }
2220
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002221 WindowState getImeTargetBelowWindow(WindowState w) {
2222 final int index = mChildren.indexOf(w);
2223 if (index > 0) {
2224 final WindowState target = mChildren.get(index - 1);
2225 if (target.canBeImeTarget()) {
2226 return target;
2227 }
2228 }
2229 return null;
2230 }
2231
2232 WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
2233 WindowState candidate = null;
2234 for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
2235 final WindowState w = mChildren.get(i);
2236 if (w.mRemoved) {
2237 continue;
2238 }
Jorim Jaggi35d328a2018-08-14 17:00:20 +02002239 if (candidate == null) {
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002240 candidate = w;
2241 }
2242 }
2243 return candidate;
2244 }
2245
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002246 /**
2247 * See {@link Activity#setDisablePreviewScreenshots}.
2248 */
2249 void setDisablePreviewScreenshots(boolean disable) {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002250 mDisablePreviewScreenshots = disable;
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002251 }
2252
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002253 /**
chaviwd3bf08d2017-08-01 17:24:59 -07002254 * Sets whether the current launch can turn the screen on. See {@link #canTurnScreenOn()}
2255 */
2256 void setCanTurnScreenOn(boolean canTurnScreenOn) {
2257 mCanTurnScreenOn = canTurnScreenOn;
2258 }
2259
2260 /**
2261 * Indicates whether the current launch can turn the screen on. This is to prevent multiple
2262 * relayouts from turning the screen back on. The screen should only turn on at most
2263 * once per activity resume.
2264 *
2265 * @return true if the screen can be turned on.
2266 */
2267 boolean canTurnScreenOn() {
2268 return mCanTurnScreenOn;
2269 }
2270
2271 /**
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002272 * Retrieves whether we'd like to generate a snapshot that's based solely on the theme. This is
2273 * the case when preview screenshots are disabled {@link #setDisablePreviewScreenshots} or when
2274 * we can't take a snapshot for other reasons, for example, if we have a secure window.
2275 *
2276 * @return True if we need to generate an app theme snapshot, false if we'd like to take a real
2277 * screenshot.
2278 */
2279 boolean shouldUseAppThemeSnapshot() {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002280 return mDisablePreviewScreenshots || forAllWindows(w -> (w.mAttrs.flags & FLAG_SECURE) != 0,
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002281 true /* topToBottom */);
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002282 }
2283
Jorim Jaggibe418292018-03-26 16:14:12 +02002284 SurfaceControl getAppAnimationLayer() {
Jorim Jaggi391790622018-04-18 15:30:44 +02002285 return getAppAnimationLayer(isActivityTypeHome() ? ANIMATION_LAYER_HOME
2286 : needsZBoost() ? ANIMATION_LAYER_BOOSTED
2287 : ANIMATION_LAYER_STANDARD);
Jorim Jaggibe418292018-03-26 16:14:12 +02002288 }
2289
chaviw23ee71c2017-12-18 11:29:41 -08002290 @Override
Jorim Jaggi596a1992017-12-29 14:48:02 +01002291 public SurfaceControl getAnimationLeashParent() {
Robert Carrb9506032018-02-13 13:54:00 -08002292 // All normal app transitions take place in an animation layer which is below the pinned
2293 // stack but may be above the parent stacks of the given animating apps.
2294 // For transitions in the pinned stack (menu activity) we just let them occur as a child
2295 // of the pinned stack.
2296 if (!inPinnedWindowingMode()) {
2297 return getAppAnimationLayer();
2298 } else {
2299 return getStack().getSurfaceControl();
2300 }
chaviw23ee71c2017-12-18 11:29:41 -08002301 }
2302
Jorim Jaggic6976f02018-04-18 16:31:07 +02002303 private boolean shouldAnimate(int transit) {
2304 final boolean isSplitScreenPrimary =
2305 getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
2306 final boolean allowSplitScreenPrimaryAnimation = transit != TRANSIT_WALLPAPER_OPEN;
2307
2308 // We animate always if it's not split screen primary, and only some special cases in split
2309 // screen primary because it causes issues with stack clipping when we run an un-minimize
2310 // animation at the same time.
2311 return !isSplitScreenPrimary || allowSplitScreenPrimaryAnimation;
2312 }
2313
Vishnu Naira2977262018-07-26 13:31:26 -07002314 /**
2315 * Creates a layer to apply crop to an animation.
2316 */
2317 private SurfaceControl createAnimationBoundsLayer(Transaction t) {
2318 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.i(TAG, "Creating animation bounds layer");
2319 final SurfaceControl.Builder builder = makeAnimationLeash()
2320 .setParent(getAnimationLeashParent())
Vishnu Naire86bd982018-11-28 13:23:17 -08002321 .setName(getSurfaceControl() + " - animation-bounds");
Vishnu Naira2977262018-07-26 13:31:26 -07002322 final SurfaceControl boundsLayer = builder.build();
2323 t.show(boundsLayer);
2324 return boundsLayer;
2325 }
2326
Riddle Hsua118b3a2018-10-11 22:05:06 +08002327 /** Get position and crop region of animation. */
2328 @VisibleForTesting
2329 void getAnimationBounds(Point outPosition, Rect outBounds) {
2330 outPosition.set(0, 0);
2331 outBounds.setEmpty();
2332
2333 final TaskStack stack = getStack();
2334 final Task task = getTask();
2335 if (task != null && task.inFreeformWindowingMode()) {
Evan Roskyed6767f2018-10-26 17:21:06 -07002336 task.getRelativeDisplayedPosition(outPosition);
Riddle Hsua118b3a2018-10-11 22:05:06 +08002337 } else if (stack != null) {
Evan Roskyed6767f2018-10-26 17:21:06 -07002338 stack.getRelativeDisplayedPosition(outPosition);
Riddle Hsua118b3a2018-10-11 22:05:06 +08002339 }
2340
2341 // Always use stack bounds in order to have the ability to animate outside the task region.
2342 // It also needs to be consistent when {@link #mNeedsAnimationBoundsLayer} is set that crops
2343 // according to the bounds.
2344 if (stack != null) {
2345 stack.getBounds(outBounds);
2346 }
2347 // We have the relative position so the local position can be removed from bounds.
2348 outBounds.offsetTo(0, 0);
2349 }
2350
Evan Roskyed6767f2018-10-26 17:21:06 -07002351 @Override
2352 Rect getDisplayedBounds() {
2353 final Task task = getTask();
2354 if (task != null) {
2355 final Rect overrideDisplayedBounds = task.getOverrideDisplayedBounds();
2356 if (!overrideDisplayedBounds.isEmpty()) {
2357 return overrideDisplayedBounds;
2358 }
2359 }
2360 return getBounds();
2361 }
2362
Evan Rosky2289ba12018-11-19 18:28:18 -08002363 private static boolean isChangeTransition(int transit) {
2364 return transit == TRANSIT_TASK_CHANGE_WINDOWING_MODE;
2365 }
2366
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002367 boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter,
2368 boolean isVoiceInteraction) {
2369
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002370 if (mWmService.mDisableTransitionAnimation || !shouldAnimate(transit)) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002371 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
Jorim Jaggic6976f02018-04-18 16:31:07 +02002372 Slog.v(TAG_WM, "applyAnimation: transition animation is disabled or skipped."
2373 + " atoken=" + this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002374 }
2375 cancelAnimation();
2376 return false;
2377 }
2378
2379 // Only apply an animation if the display isn't frozen. If it is frozen, there is no reason
2380 // to animate and it can cause strange artifacts when we unfreeze the display if some
2381 // different animation is running.
2382 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#applyAnimationLocked");
2383 if (okToAnimate()) {
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002384 final AnimationAdapter adapter;
Evan Rosky2289ba12018-11-19 18:28:18 -08002385 AnimationAdapter thumbnailAdapter = null;
Riddle Hsua118b3a2018-10-11 22:05:06 +08002386 getAnimationBounds(mTmpPoint, mTmpRect);
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002387
Evan Rosky966759f2019-01-15 10:33:58 -08002388 boolean isChanging = isChangeTransition(transit) && enter;
Evan Rosky2289ba12018-11-19 18:28:18 -08002389
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002390 // Delaying animation start isn't compatible with remote animations at all.
lumark588a3e82018-07-20 18:53:54 +08002391 if (getDisplayContent().mAppTransition.getRemoteAnimationController() != null
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002392 && !mSurfaceAnimator.isAnimationStartDelayed()) {
Evan Rosky2289ba12018-11-19 18:28:18 -08002393 RemoteAnimationRecord adapters =
2394 getDisplayContent().mAppTransition.getRemoteAnimationController()
2395 .createRemoteAnimationRecord(this, mTmpPoint, mTmpRect,
2396 (isChanging ? mTransitStartRect : null));
2397 adapter = adapters.mAdapter;
2398 thumbnailAdapter = adapters.mThumbnailAdapter;
2399 } else if (isChanging) {
Evan Roskycf76bed2019-01-15 10:33:58 -08002400 final float durationScale = mWmService.getTransitionAnimationScaleLocked();
Evan Rosky2289ba12018-11-19 18:28:18 -08002401 mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y);
2402 adapter = new LocalAnimationAdapter(
2403 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
Evan Roskycf76bed2019-01-15 10:33:58 -08002404 getDisplayContent().getDisplayInfo(), durationScale,
Evan Rosky2289ba12018-11-19 18:28:18 -08002405 true /* isAppAnimation */, false /* isThumbnail */),
2406 mWmService.mSurfaceAnimationRunner);
Evan Rosky966759f2019-01-15 10:33:58 -08002407 if (mThumbnail != null) {
2408 thumbnailAdapter = new LocalAnimationAdapter(
2409 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
Evan Roskycf76bed2019-01-15 10:33:58 -08002410 getDisplayContent().getDisplayInfo(), durationScale,
Evan Rosky966759f2019-01-15 10:33:58 -08002411 true /* isAppAnimation */, true /* isThumbnail */),
2412 mWmService.mSurfaceAnimationRunner);
2413 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002414 mTransit = transit;
2415 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002416 } else {
lumark588a3e82018-07-20 18:53:54 +08002417 final int appStackClipMode =
2418 getDisplayContent().mAppTransition.getAppStackClipMode();
Vishnu Naira2977262018-07-26 13:31:26 -07002419 mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM);
2420
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002421 final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
2422 if (a != null) {
2423 adapter = new LocalAnimationAdapter(
2424 new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
lumark588a3e82018-07-20 18:53:54 +08002425 getDisplayContent().mAppTransition.canSkipFirstFrame(),
Vishnu Naira2977262018-07-26 13:31:26 -07002426 appStackClipMode,
Jorim Jaggiaa763cd2018-03-22 23:20:36 +01002427 true /* isAppAnimation */),
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002428 mWmService.mSurfaceAnimationRunner);
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002429 if (a.getZAdjustment() == Animation.ZORDER_TOP) {
2430 mNeedsZBoost = true;
2431 }
2432 mTransit = transit;
lumark588a3e82018-07-20 18:53:54 +08002433 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002434 } else {
2435 adapter = null;
chaviw23ee71c2017-12-18 11:29:41 -08002436 }
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002437 }
2438 if (adapter != null) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002439 startAnimation(getPendingTransaction(), adapter, !isVisible());
Jorim Jaggi82c17862018-02-21 17:50:18 +01002440 if (adapter.getShowWallpaper()) {
2441 mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2442 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002443 if (thumbnailAdapter != null) {
2444 mThumbnail.startAnimation(
2445 getPendingTransaction(), thumbnailAdapter, !isVisible());
2446 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002447 }
2448 } else {
2449 cancelAnimation();
2450 }
2451 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2452
2453 return isReallyAnimating();
2454 }
2455
2456 private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
2457 boolean isVoiceInteraction) {
2458 final DisplayContent displayContent = getTask().getDisplayContent();
2459 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2460 final int width = displayInfo.appWidth;
2461 final int height = displayInfo.appHeight;
2462 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG_WM,
2463 "applyAnimation: atoken=" + this);
2464
2465 // Determine the visible rect to calculate the thumbnail clip
2466 final WindowState win = findMainWindow();
2467 final Rect frame = new Rect(0, 0, width, height);
2468 final Rect displayFrame = new Rect(0, 0,
2469 displayInfo.logicalWidth, displayInfo.logicalHeight);
2470 final Rect insets = new Rect();
2471 final Rect stableInsets = new Rect();
2472 Rect surfaceInsets = null;
2473 final boolean freeform = win != null && win.inFreeformWindowingMode();
2474 if (win != null) {
2475 // Containing frame will usually cover the whole screen, including dialog windows.
2476 // For freeform workspace windows it will not cover the whole screen and it also
2477 // won't exactly match the final freeform window frame (e.g. when overlapping with
2478 // the status bar). In that case we need to use the final frame.
2479 if (freeform) {
chaviw492139a2018-07-16 16:07:35 -07002480 frame.set(win.getFrameLw());
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002481 } else if (win.isLetterboxedAppWindow()) {
2482 frame.set(getTask().getBounds());
Winson Chungc1674272018-02-21 10:15:17 -08002483 } else if (win.isDockedResizing()) {
2484 // If we are animating while docked resizing, then use the stack bounds as the
2485 // animation target (which will be different than the task bounds)
2486 frame.set(getTask().getParent().getBounds());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002487 } else {
chaviw553b0212018-07-12 13:37:01 -07002488 frame.set(win.getContainingFrame());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002489 }
2490 surfaceInsets = win.getAttrs().surfaceInsets;
Adrian Roos20e07892018-02-23 19:12:01 +01002491 // XXX(b/72757033): These are insets relative to the window frame, but we're really
2492 // interested in the insets relative to the frame we chose in the if-blocks above.
chaviw9c81e632018-07-31 11:17:52 -07002493 win.getContentInsets(insets);
2494 win.getStableInsets(stableInsets);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002495 }
2496
2497 if (mLaunchTaskBehind) {
2498 // Differentiate the two animations. This one which is briefly on the screen
2499 // gets the !enter animation, and the other activity which remains on the
2500 // screen gets the enter animation. Both appear in the mOpeningApps set.
2501 enter = false;
2502 }
2503 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "Loading animation for app transition."
2504 + " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter
2505 + " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets);
2506 final Configuration displayConfig = displayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08002507 final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002508 displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
2509 surfaceInsets, stableInsets, isVoiceInteraction, freeform, getTask().mTaskId);
2510 if (a != null) {
2511 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
2512 final int containingWidth = frame.width();
2513 final int containingHeight = frame.height();
2514 a.initialize(containingWidth, containingHeight, width, height);
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002515 a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002516 }
2517 return a;
2518 }
2519
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002520 @Override
Jorim Jaggi6de61012018-03-19 14:53:23 +01002521 public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
2522 return mAnimatingAppWindowTokenRegistry != null
2523 && mAnimatingAppWindowTokenRegistry.notifyAboutToFinish(
2524 this, endDeferFinishCallback);
2525 }
2526
2527 @Override
2528 public void onAnimationLeashDestroyed(Transaction t) {
2529 super.onAnimationLeashDestroyed(t);
Vishnu Naira2977262018-07-26 13:31:26 -07002530 if (mAnimationBoundsLayer != null) {
Robert Carr71200f22019-02-05 09:44:53 -08002531 t.remove(mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002532 mAnimationBoundsLayer = null;
2533 }
2534
Jorim Jaggi6de61012018-03-19 14:53:23 +01002535 if (mAnimatingAppWindowTokenRegistry != null) {
2536 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
2537 }
2538 }
2539
2540 @Override
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002541 protected void setLayer(Transaction t, int layer) {
2542 if (!mSurfaceAnimator.hasLeash()) {
2543 t.setLayer(mSurfaceControl, layer);
2544 }
2545 }
2546
2547 @Override
2548 protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
2549 if (!mSurfaceAnimator.hasLeash()) {
2550 t.setRelativeLayer(mSurfaceControl, relativeTo, layer);
2551 }
2552 }
2553
2554 @Override
2555 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
2556 if (!mSurfaceAnimator.hasLeash()) {
Robert Carr10584fa2019-01-14 15:55:19 -08002557 t.reparent(mSurfaceControl, newParent);
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002558 }
2559 }
2560
2561 @Override
2562 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002563 // The leash is parented to the animation layer. We need to preserve the z-order by using
2564 // the prefix order index, but we boost if necessary.
Robert Carrb9506032018-02-13 13:54:00 -08002565 int layer = 0;
2566 if (!inPinnedWindowingMode()) {
2567 layer = getPrefixOrderIndex();
2568 } else {
2569 // Pinned stacks have animations take place within themselves rather than an animation
2570 // layer so we need to preserve the order relative to the stack (e.g. the order of our
2571 // task/parent).
2572 layer = getParent().getPrefixOrderIndex();
2573 }
2574
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002575 if (mNeedsZBoost) {
2576 layer += Z_BOOST_BASE;
2577 }
2578 leash.setLayer(layer);
Robert Carr2f8aa392018-01-31 14:46:51 -08002579
2580 final DisplayContent dc = getDisplayContent();
Jorim Jaggibe418292018-03-26 16:14:12 +02002581 dc.assignStackOrdering();
Evan Rosky2289ba12018-11-19 18:28:18 -08002582
2583 if (leash == mTransitChangeLeash) {
2584 // This is a temporary state so skip any animation notifications
2585 return;
2586 } else if (mTransitChangeLeash != null) {
2587 // unparent mTransitChangeLeash for clean-up
Evan Rosky25b56192019-02-06 16:10:56 -08002588 clearChangeLeash(t, false /* cancel */);
Evan Rosky2289ba12018-11-19 18:28:18 -08002589 }
2590
Jorim Jaggi6de61012018-03-19 14:53:23 +01002591 if (mAnimatingAppWindowTokenRegistry != null) {
2592 mAnimatingAppWindowTokenRegistry.notifyStarting(this);
2593 }
Vishnu Naira2977262018-07-26 13:31:26 -07002594
2595 // If the animation needs to be cropped then an animation bounds layer is created as a child
2596 // of the pinned stack or animation layer. The leash is then reparented to this new layer.
2597 if (mNeedsAnimationBoundsLayer) {
2598 final TaskStack stack = getStack();
2599 if (stack == null) {
2600 return;
2601 }
2602 mAnimationBoundsLayer = createAnimationBoundsLayer(t);
2603
2604 // Set clip rect to stack bounds.
2605 mTmpRect.setEmpty();
2606 stack.getBounds(mTmpRect);
2607
2608 // Crop to stack bounds.
2609 t.setWindowCrop(mAnimationBoundsLayer, mTmpRect);
2610
2611 // Reparent leash to animation bounds layer.
Robert Carr10584fa2019-01-14 15:55:19 -08002612 t.reparent(leash, mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002613 }
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002614 }
2615
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002616 /**
2617 * This must be called while inside a transaction.
2618 */
2619 void showAllWindowsLocked() {
2620 forAllWindows(windowState -> {
2621 if (DEBUG_VISIBILITY) Slog.v(TAG, "performing show on: " + windowState);
2622 windowState.performShowLocked();
2623 }, false /* traverseTopToBottom */);
Jorim Jaggia5e10572017-11-15 14:36:26 +01002624 }
2625
2626 @Override
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002627 protected void onAnimationFinished() {
2628 super.onAnimationFinished();
2629
2630 mTransit = TRANSIT_UNSET;
2631 mTransitFlags = 0;
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002632 mNeedsZBoost = false;
Vishnu Naira2977262018-07-26 13:31:26 -07002633 mNeedsAnimationBoundsLayer = false;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002634
2635 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER,
2636 "AppWindowToken");
2637
Jorim Jaggi988f6682017-11-17 17:46:43 +01002638 clearThumbnail();
Jorim Jaggi752cd822018-03-29 16:29:18 +02002639 setClientHidden(isHidden() && hiddenRequested);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002640
lumarkff0ab692018-11-05 20:32:30 +08002641 getDisplayContent().computeImeTargetIfNeeded(this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002642
2643 if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + this
2644 + ": reportedVisible=" + reportedVisible
2645 + " okToDisplay=" + okToDisplay()
2646 + " okToAnimate=" + okToAnimate()
2647 + " startingDisplayed=" + startingDisplayed);
2648
Evan Rosky2289ba12018-11-19 18:28:18 -08002649 // clean up thumbnail window
2650 if (mThumbnail != null) {
2651 mThumbnail.destroy();
2652 mThumbnail = null;
2653 }
2654
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002655 // WindowState.onExitAnimationDone might modify the children list, so make a copy and then
2656 // traverse the copy.
2657 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
2658 children.forEach(WindowState::onExitAnimationDone);
2659
lumark588a3e82018-07-20 18:53:54 +08002660 getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002661 scheduleAnimation();
2662 }
2663
2664 @Override
2665 boolean isAppAnimating() {
2666 return isSelfAnimating();
2667 }
2668
2669 @Override
2670 boolean isSelfAnimating() {
2671 // If we are about to start a transition, we also need to be considered animating.
2672 return isWaitingForTransitionStart() || isReallyAnimating();
2673 }
2674
2675 /**
2676 * @return True if and only if we are actually running an animation. Note that
2677 * {@link #isSelfAnimating} also returns true if we are waiting for an animation to
2678 * start.
2679 */
2680 private boolean isReallyAnimating() {
2681 return super.isSelfAnimating();
2682 }
2683
Evan Rosky25b56192019-02-06 16:10:56 -08002684 /**
2685 * @param cancel {@code true} if clearing the leash due to cancelling instead of transferring
2686 * to another leash.
2687 */
2688 private void clearChangeLeash(Transaction t, boolean cancel) {
2689 if (mTransitChangeLeash == null) {
2690 return;
2691 }
2692 if (cancel) {
2693 clearThumbnail();
2694 SurfaceControl sc = getSurfaceControl();
2695 SurfaceControl parentSc = getParentSurfaceControl();
2696 // Don't reparent if surface is getting destroyed
2697 if (parentSc != null && sc != null) {
2698 t.reparent(sc, getParentSurfaceControl());
2699 }
2700 }
2701 t.hide(mTransitChangeLeash);
2702 t.reparent(mTransitChangeLeash, null);
2703 mTransitChangeLeash = null;
2704 if (cancel) {
2705 onAnimationLeashDestroyed(t);
2706 }
2707 }
2708
Jorim Jaggi988f6682017-11-17 17:46:43 +01002709 @Override
2710 void cancelAnimation() {
Evan Rosky2289ba12018-11-19 18:28:18 -08002711 cancelAnimationOnly();
Jorim Jaggi988f6682017-11-17 17:46:43 +01002712 clearThumbnail();
Evan Rosky25b56192019-02-06 16:10:56 -08002713 clearChangeLeash(getPendingTransaction(), true /* cancel */);
Evan Rosky2289ba12018-11-19 18:28:18 -08002714 }
2715
2716 /**
2717 * This only cancels the animation. It doesn't do other teardown like cleaning-up thumbnail
2718 * or interim leashes.
2719 * <p>
2720 * Used when canceling in preparation for starting a new animation.
2721 */
2722 void cancelAnimationOnly() {
2723 super.cancelAnimation();
Jorim Jaggi988f6682017-11-17 17:46:43 +01002724 }
2725
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002726 boolean isWaitingForTransitionStart() {
lumark588a3e82018-07-20 18:53:54 +08002727 return getDisplayContent().mAppTransition.isTransitionSet()
2728 && (getDisplayContent().mOpeningApps.contains(this)
Evan Rosky2289ba12018-11-19 18:28:18 -08002729 || getDisplayContent().mClosingApps.contains(this)
2730 || getDisplayContent().mChangingApps.contains(this));
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002731 }
2732
2733 public int getTransit() {
2734 return mTransit;
2735 }
2736
2737 int getTransitFlags() {
2738 return mTransitFlags;
2739 }
2740
Jorim Jaggi988f6682017-11-17 17:46:43 +01002741 void attachThumbnailAnimation() {
2742 if (!isReallyAnimating()) {
2743 return;
2744 }
2745 final int taskId = getTask().mTaskId;
2746 final GraphicBuffer thumbnailHeader =
lumark588a3e82018-07-20 18:53:54 +08002747 getDisplayContent().mAppTransition.getAppTransitionThumbnailHeader(taskId);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002748 if (thumbnailHeader == null) {
2749 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG, "No thumbnail header bitmap for: " + taskId);
2750 return;
2751 }
2752 clearThumbnail();
2753 mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnailHeader);
2754 mThumbnail.startAnimation(getPendingTransaction(), loadThumbnailAnimation(thumbnailHeader));
2755 }
2756
Tony Mak64b8d562017-12-28 17:44:02 +00002757 /**
2758 * Attaches a surface with a thumbnail for the
2759 * {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation.
2760 */
2761 void attachCrossProfileAppsThumbnailAnimation() {
2762 if (!isReallyAnimating()) {
2763 return;
2764 }
2765 clearThumbnail();
2766
2767 final WindowState win = findMainWindow();
2768 if (win == null) {
2769 return;
2770 }
chaviw492139a2018-07-16 16:07:35 -07002771 final Rect frame = win.getFrameLw();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002772 final int thumbnailDrawableRes = getTask().mUserId == mWmService.mCurrentUserId
Tony Mak64b8d562017-12-28 17:44:02 +00002773 ? R.drawable.ic_account_circle
Tony Makda4af232018-04-27 11:01:10 +01002774 : R.drawable.ic_corp_badge;
Tony Mak64b8d562017-12-28 17:44:02 +00002775 final GraphicBuffer thumbnail =
lumark588a3e82018-07-20 18:53:54 +08002776 getDisplayContent().mAppTransition
Tony Mak64b8d562017-12-28 17:44:02 +00002777 .createCrossProfileAppsThumbnail(thumbnailDrawableRes, frame);
2778 if (thumbnail == null) {
2779 return;
2780 }
2781 mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnail);
2782 final Animation animation =
lumark588a3e82018-07-20 18:53:54 +08002783 getDisplayContent().mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(
chaviw492139a2018-07-16 16:07:35 -07002784 win.getFrameLw());
Tony Mak64b8d562017-12-28 17:44:02 +00002785 mThumbnail.startAnimation(getPendingTransaction(), animation, new Point(frame.left,
2786 frame.top));
2787 }
2788
Jorim Jaggi988f6682017-11-17 17:46:43 +01002789 private Animation loadThumbnailAnimation(GraphicBuffer thumbnailHeader) {
2790 final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
2791
2792 // If this is a multi-window scenario, we use the windows frame as
2793 // destination of the thumbnail header animation. If this is a full screen
2794 // window scenario, we use the whole display as the target.
2795 WindowState win = findMainWindow();
2796 Rect appRect = win != null ? win.getContentFrameLw() :
2797 new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
chaviw9c81e632018-07-31 11:17:52 -07002798 final Rect insets = win != null ? win.getContentInsets() : null;
Jorim Jaggi988f6682017-11-17 17:46:43 +01002799 final Configuration displayConfig = mDisplayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08002800 return getDisplayContent().mAppTransition.createThumbnailAspectScaleAnimationLocked(
Jorim Jaggi988f6682017-11-17 17:46:43 +01002801 appRect, insets, thumbnailHeader, getTask().mTaskId, displayConfig.uiMode,
2802 displayConfig.orientation);
2803 }
2804
2805 private void clearThumbnail() {
2806 if (mThumbnail == null) {
2807 return;
2808 }
2809 mThumbnail.destroy();
2810 mThumbnail = null;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002811 }
2812
Jorim Jaggif84e2f62018-01-16 14:17:59 +01002813 void registerRemoteAnimations(RemoteAnimationDefinition definition) {
2814 mRemoteAnimationDefinition = definition;
2815 }
2816
2817 RemoteAnimationDefinition getRemoteAnimationDefinition() {
2818 return mRemoteAnimationDefinition;
2819 }
2820
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002821 @Override
2822 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
2823 super.dump(pw, prefix, dumpAll);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002824 if (appToken != null) {
Wale Ogunwale72919d22016-12-08 18:58:50 -08002825 pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002826 }
Winson Chung48b25652018-10-22 14:04:30 -07002827 pw.println(prefix + "component=" + mActivityComponent.flattenToShortString());
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08002828 pw.print(prefix); pw.print("task="); pw.println(getTask());
Wale Ogunwale51362492016-09-08 17:49:17 -07002829 pw.print(prefix); pw.print(" mFillsParent="); pw.print(mFillsParent);
2830 pw.print(" mOrientation="); pw.println(mOrientation);
Wale Ogunwale89973222017-04-23 18:39:45 -07002831 pw.println(prefix + "hiddenRequested=" + hiddenRequested + " mClientHidden=" + mClientHidden
2832 + ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "")
2833 + " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible);
Craig Mautner59431632012-04-04 11:56:44 -07002834 if (paused) {
2835 pw.print(prefix); pw.print("paused="); pw.println(paused);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002836 }
Wale Ogunwale9017ec02016-02-25 08:55:25 -08002837 if (mAppStopped) {
2838 pw.print(prefix); pw.print("mAppStopped="); pw.println(mAppStopped);
2839 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002840 if (mNumInterestingWindows != 0 || mNumDrawnWindows != 0
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002841 || allDrawn || mLastAllDrawn) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002842 pw.print(prefix); pw.print("mNumInterestingWindows=");
2843 pw.print(mNumInterestingWindows);
2844 pw.print(" mNumDrawnWindows="); pw.print(mNumDrawnWindows);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002845 pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
Craig Mautner6fbda632012-07-03 09:26:39 -07002846 pw.print(" allDrawn="); pw.print(allDrawn);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002847 pw.print(" lastAllDrawn="); pw.print(mLastAllDrawn);
Craig Mautner6fbda632012-07-03 09:26:39 -07002848 pw.println(")");
2849 }
2850 if (inPendingTransaction) {
2851 pw.print(prefix); pw.print("inPendingTransaction=");
2852 pw.println(inPendingTransaction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002853 }
Craig Mautner799bc1d2015-01-14 10:33:48 -08002854 if (startingData != null || removed || firstWindowDrawn || mIsExiting) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002855 pw.print(prefix); pw.print("startingData="); pw.print(startingData);
2856 pw.print(" removed="); pw.print(removed);
Craig Mautner3d7ca312015-01-08 10:56:00 -08002857 pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
Craig Mautner799bc1d2015-01-14 10:33:48 -08002858 pw.print(" mIsExiting="); pw.println(mIsExiting);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002859 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08002860 if (startingWindow != null || startingSurface != null
Wale Ogunwale6c459212017-05-17 08:56:03 -07002861 || startingDisplayed || startingMoved || mHiddenSetFromTransferredStartingWindow) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002862 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08002863 pw.print(" startingSurface="); pw.print(startingSurface);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002864 pw.print(" startingDisplayed="); pw.print(startingDisplayed);
Wale Ogunwale6c459212017-05-17 08:56:03 -07002865 pw.print(" startingMoved="); pw.print(startingMoved);
2866 pw.println(" mHiddenSetFromTransferredStartingWindow="
2867 + mHiddenSetFromTransferredStartingWindow);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002868 }
Jorim Jaggi0429f352015-12-22 16:29:16 +01002869 if (!mFrozenBounds.isEmpty()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08002870 pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
Jorim Jaggi26c8c422016-05-09 19:57:25 -07002871 pw.print(prefix); pw.print("mFrozenMergedConfig="); pw.println(mFrozenMergedConfig);
Chong Zhangd78ddb42016-03-02 17:01:14 -08002872 }
2873 if (mPendingRelaunchCount != 0) {
2874 pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount);
Jorim Jaggi0429f352015-12-22 16:29:16 +01002875 }
Wale Ogunwalee287e192017-04-21 09:30:12 -07002876 if (mRemovingFromDisplay) {
2877 pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay);
2878 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002879 }
2880
2881 @Override
2882 void setHidden(boolean hidden) {
2883 super.setHidden(hidden);
Winson Chunge55c0192017-08-24 14:50:48 -07002884
2885 if (hidden) {
2886 // Once the app window is hidden, reset the last saved PiP snap fraction
2887 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(this);
2888 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002889 scheduleAnimation();
2890 }
2891
2892 @Override
2893 void prepareSurfaces() {
2894 // isSelfAnimating also returns true when we are about to start a transition, so we need
2895 // to check super here.
2896 final boolean reallyAnimating = super.isSelfAnimating();
2897 final boolean show = !isHidden() || reallyAnimating;
Robert Carrd8e4fb72019-01-31 11:14:30 -08002898
2899 if (mSurfaceControl != null) {
2900 if (show && !mLastSurfaceShowing) {
2901 mPendingTransaction.show(mSurfaceControl);
2902 } else if (!show && mLastSurfaceShowing) {
2903 mPendingTransaction.hide(mSurfaceControl);
2904 }
Jorim Jaggi4d1835d2017-08-31 17:28:27 +02002905 }
Jorim Jaggi988f6682017-11-17 17:46:43 +01002906 if (mThumbnail != null) {
2907 mThumbnail.setShowing(mPendingTransaction, show);
2908 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002909 mLastSurfaceShowing = show;
2910 super.prepareSurfaces();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002911 }
2912
Jorim Jaggi77d0f36c2018-03-16 17:49:49 +01002913 /**
2914 * @return Whether our {@link #getSurfaceControl} is currently showing.
2915 */
2916 boolean isSurfaceShowing() {
2917 return mLastSurfaceShowing;
2918 }
2919
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002920 boolean isFreezingScreen() {
2921 return mFreezingScreen;
2922 }
2923
2924 @Override
2925 boolean needsZBoost() {
2926 return mNeedsZBoost || super.needsZBoost();
2927 }
2928
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07002929 @CallSuper
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002930 @Override
Nataniel Borges023ecb52019-01-16 14:15:43 -08002931 public void writeToProto(ProtoOutputStream proto, long fieldId,
2932 @WindowTraceLogLevel int logLevel) {
2933 // Critical log level logs only visible elements to mitigate performance overheard
2934 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
2935 return;
2936 }
2937
Steven Timotiusaf03df62017-07-18 16:56:43 -07002938 final long token = proto.start(fieldId);
2939 writeNameToProto(proto, NAME);
Nataniel Borges023ecb52019-01-16 14:15:43 -08002940 super.writeToProto(proto, WINDOW_TOKEN, logLevel);
Vishnu Nair04ab4392018-01-10 11:00:06 -08002941 proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing);
2942 proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart());
2943 proto.write(IS_REALLY_ANIMATING, isReallyAnimating());
2944 if (mThumbnail != null){
2945 mThumbnail.writeToProto(proto, THUMBNAIL);
2946 }
2947 proto.write(FILLS_PARENT, mFillsParent);
2948 proto.write(APP_STOPPED, mAppStopped);
2949 proto.write(HIDDEN_REQUESTED, hiddenRequested);
2950 proto.write(CLIENT_HIDDEN, mClientHidden);
2951 proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient);
2952 proto.write(REPORTED_DRAWN, reportedDrawn);
2953 proto.write(REPORTED_VISIBLE, reportedVisible);
2954 proto.write(NUM_INTERESTING_WINDOWS, mNumInterestingWindows);
2955 proto.write(NUM_DRAWN_WINDOWS, mNumDrawnWindows);
2956 proto.write(ALL_DRAWN, allDrawn);
2957 proto.write(LAST_ALL_DRAWN, mLastAllDrawn);
2958 proto.write(REMOVED, removed);
Nataniel Borges023ecb52019-01-16 14:15:43 -08002959 if (startingWindow != null) {
Vishnu Nair04ab4392018-01-10 11:00:06 -08002960 startingWindow.writeIdentifierToProto(proto, STARTING_WINDOW);
2961 }
2962 proto.write(STARTING_DISPLAYED, startingDisplayed);
2963 proto.write(STARTING_MOVED, startingMoved);
2964 proto.write(HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW,
2965 mHiddenSetFromTransferredStartingWindow);
2966 for (Rect bounds : mFrozenBounds) {
2967 bounds.writeToProto(proto, FROZEN_BOUNDS);
2968 }
Steven Timotiusaf03df62017-07-18 16:56:43 -07002969 proto.end(token);
2970 }
2971
2972 void writeNameToProto(ProtoOutputStream proto, long fieldId) {
2973 if (appToken == null) {
2974 return;
2975 }
2976 try {
2977 proto.write(fieldId, appToken.getName());
2978 } catch (RemoteException e) {
2979 // This shouldn't happen, but in this case fall back to outputting nothing
2980 Slog.e(TAG, e.toString());
2981 }
2982 }
2983
2984 @Override
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002985 public String toString() {
2986 if (stringName == null) {
2987 StringBuilder sb = new StringBuilder();
2988 sb.append("AppWindowToken{");
2989 sb.append(Integer.toHexString(System.identityHashCode(this)));
2990 sb.append(" token="); sb.append(token); sb.append('}');
2991 stringName = sb.toString();
2992 }
Wale Ogunwaleba51ca22016-09-23 06:06:54 -07002993 return stringName + ((mIsExiting) ? " mIsExiting=" : "");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002994 }
Adrian Roos20e07892018-02-23 19:12:01 +01002995
2996 Rect getLetterboxInsets() {
2997 if (mLetterbox != null) {
2998 return mLetterbox.getInsets();
2999 } else {
3000 return new Rect();
3001 }
3002 }
Adrian Roos23df3a32018-03-15 15:41:13 +01003003
3004 /**
3005 * @eturn true if there is a letterbox and any part of that letterbox overlaps with
3006 * the given {@code rect}.
3007 */
3008 boolean isLetterboxOverlappingWith(Rect rect) {
3009 return mLetterbox != null && mLetterbox.isOverlappingWith(rect);
3010 }
chaviw4ad54912018-05-30 11:05:44 -07003011
3012 /**
3013 * Sets if this AWT is in the process of closing or entering PIP.
3014 * {@link #mWillCloseOrEnterPip}}
3015 */
3016 void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
3017 mWillCloseOrEnterPip = willCloseOrEnterPip;
3018 }
3019
3020 /**
3021 * Returns whether this AWT is considered closing. Conditions are either
3022 * 1. Is this app animating and was requested to be hidden
3023 * 2. App is delayed closing since it might enter PIP.
3024 */
3025 boolean isClosingOrEnteringPip() {
3026 return (isAnimating() && hiddenRequested) || mWillCloseOrEnterPip;
3027 }
Jorim Jaggiaf0d6d22018-06-08 15:25:35 +02003028
3029 /**
3030 * @return Whether we are allowed to show non-starting windows at the moment. We disallow
3031 * showing windows during transitions in case we have windows that have wide-color-gamut
3032 * color mode set to avoid jank in the middle of the transition.
3033 */
3034 boolean canShowWindows() {
3035 return allDrawn && !(isReallyAnimating() && hasNonDefaultColorWindow());
3036 }
3037
3038 /**
3039 * @return true if we have a window that has a non-default color mode set; false otherwise.
3040 */
3041 private boolean hasNonDefaultColorWindow() {
3042 return forAllWindows(ws -> ws.mAttrs.getColorMode() != COLOR_MODE_DEFAULT,
3043 true /* topToBottom */);
3044 }
lumark588a3e82018-07-20 18:53:54 +08003045
3046 void removeFromPendingTransition() {
3047 if (isWaitingForTransitionStart() && mDisplayContent != null) {
3048 mDisplayContent.mOpeningApps.remove(this);
Evan Rosky25b56192019-02-06 16:10:56 -08003049 if (mDisplayContent.mChangingApps.remove(this)) {
3050 clearChangeLeash(getPendingTransaction(), true /* cancel */);
3051 }
lumark588a3e82018-07-20 18:53:54 +08003052 mDisplayContent.mClosingApps.remove(this);
3053 }
3054 }
chaviwdcf76ec2019-01-11 16:48:46 -08003055
3056 private void updateColorTransform() {
3057 if (mSurfaceControl != null && mLastAppSaturationInfo != null) {
3058 mPendingTransaction.setColorTransform(mSurfaceControl, mLastAppSaturationInfo.mMatrix,
3059 mLastAppSaturationInfo.mTranslation);
3060 mWmService.scheduleAnimationLocked();
3061 }
3062 }
3063
3064 private static class AppSaturationInfo {
3065 float[] mMatrix = new float[9];
3066 float[] mTranslation = new float[3];
3067
3068 void setSaturation(@Size(9) float[] matrix, @Size(3) float[] translation) {
3069 System.arraycopy(matrix, 0, mMatrix, 0, mMatrix.length);
3070 System.arraycopy(translation, 0, mTranslation, 0, mTranslation.length);
3071 }
3072 }
Jeff Browne9bdb312012-04-05 15:30:10 -07003073}