blob: fc350cd900c11e9481a495f6c597445d5a13ba4b [file] [log] [blame]
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.wm;
18
Evan Rosky2289ba12018-11-19 18:28:18 -080019import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
Winson Chunge55c0192017-08-24 14:50:48 -070020import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
Jorim Jaggic6976f02018-04-18 16:31:07 +020021import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
Winson Chunge55c0192017-08-24 14:50:48 -070022import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
Jorim Jaggiaf0d6d22018-06-08 15:25:35 +020023import static android.content.pm.ActivityInfo.COLOR_MODE_DEFAULT;
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -070024import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
Wale Ogunwale51362492016-09-08 17:49:17 -070025import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
Jorim Jaggif5f9e122017-10-24 18:21:09 +020026import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
Jorim Jaggife762342016-10-13 14:33:27 +020027import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
Jorim Jaggid635a4a2017-05-03 15:21:26 +020028import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080029import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
Jorim Jaggife762342016-10-13 14:33:27 +020030import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
Wale Ogunwaled1c37912016-08-16 03:19:39 -070031import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080032import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -070033import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080034import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
Evan Rosky2289ba12018-11-19 18:28:18 -080035import static android.view.WindowManager.TRANSIT_TASK_CHANGE_WINDOWING_MODE;
Louis Chang37317152019-05-09 09:53:58 +080036import static android.view.WindowManager.TRANSIT_TASK_OPEN_BEHIND;
chaviw9c81e632018-07-31 11:17:52 -070037import static android.view.WindowManager.TRANSIT_UNSET;
Jorim Jaggic6976f02018-04-18 16:31:07 +020038import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
chaviw9c81e632018-07-31 11:17:52 -070039
Adrian Roose99bc052017-11-20 17:55:31 +010040import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
41import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070042import static com.android.server.wm.AppWindowTokenProto.ALL_DRAWN;
43import static com.android.server.wm.AppWindowTokenProto.APP_STOPPED;
44import static com.android.server.wm.AppWindowTokenProto.CLIENT_HIDDEN;
45import static com.android.server.wm.AppWindowTokenProto.DEFER_HIDING_CLIENT;
46import static com.android.server.wm.AppWindowTokenProto.FILLS_PARENT;
47import static com.android.server.wm.AppWindowTokenProto.FROZEN_BOUNDS;
48import static com.android.server.wm.AppWindowTokenProto.HIDDEN_REQUESTED;
49import static com.android.server.wm.AppWindowTokenProto.HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW;
50import static com.android.server.wm.AppWindowTokenProto.IS_REALLY_ANIMATING;
51import static com.android.server.wm.AppWindowTokenProto.IS_WAITING_FOR_TRANSITION_START;
52import static com.android.server.wm.AppWindowTokenProto.LAST_ALL_DRAWN;
53import static com.android.server.wm.AppWindowTokenProto.LAST_SURFACE_SHOWING;
54import static com.android.server.wm.AppWindowTokenProto.NAME;
55import static com.android.server.wm.AppWindowTokenProto.NUM_DRAWN_WINDOWS;
56import static com.android.server.wm.AppWindowTokenProto.NUM_INTERESTING_WINDOWS;
57import static com.android.server.wm.AppWindowTokenProto.REMOVED;
58import static com.android.server.wm.AppWindowTokenProto.REPORTED_DRAWN;
59import static com.android.server.wm.AppWindowTokenProto.REPORTED_VISIBLE;
60import static com.android.server.wm.AppWindowTokenProto.STARTING_DISPLAYED;
61import static com.android.server.wm.AppWindowTokenProto.STARTING_MOVED;
62import static com.android.server.wm.AppWindowTokenProto.STARTING_WINDOW;
63import static com.android.server.wm.AppWindowTokenProto.THUMBNAIL;
64import static com.android.server.wm.AppWindowTokenProto.WINDOW_TOKEN;
chaviw9c81e632018-07-31 11:17:52 -070065import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
66import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
67import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
68import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
69import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
70import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
71import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
72import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
73import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
74import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
75import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
76import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
77import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
78import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN;
79import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
80import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
81import static com.android.server.wm.WindowManagerService.logWithStack;
chaviw15ad49f2019-04-24 15:05:39 -070082import static com.android.server.wm.WindowState.LEGACY_POLICY_VISIBILITY;
Jorim Jaggi6ec52d42019-07-03 15:45:59 +020083import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
Vishnu Naira2977262018-07-26 13:31:26 -070084import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
Evan Rosky641daea2019-04-24 14:45:24 -070085import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080086
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070087import android.annotation.CallSuper;
chaviwdcf76ec2019-01-11 16:48:46 -080088import android.annotation.Size;
Jorim Jaggid635a4a2017-05-03 15:21:26 +020089import android.app.Activity;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080090import android.app.ActivityManager;
Winson Chung48b25652018-10-22 14:04:30 -070091import android.content.ComponentName;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080092import android.content.res.CompatibilityInfo;
Jorim Jaggi26c8c422016-05-09 19:57:25 -070093import android.content.res.Configuration;
Jorim Jaggi988f6682017-11-17 17:46:43 +010094import android.graphics.GraphicBuffer;
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -070095import android.graphics.PixelFormat;
Jorim Jaggif5f9e122017-10-24 18:21:09 +020096import android.graphics.Point;
Jorim Jaggi0429f352015-12-22 16:29:16 +010097import android.graphics.Rect;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -070098import android.os.Binder;
Tiger Huang51c5a1d2018-12-11 20:24:51 +080099import android.os.Build;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800100import android.os.Debug;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700101import android.os.IBinder;
Steven Timotiusaf03df62017-07-18 16:56:43 -0700102import android.os.RemoteException;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800103import android.os.SystemClock;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200104import android.os.Trace;
Evan Rosky2289ba12018-11-19 18:28:18 -0800105import android.util.ArraySet;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800106import android.util.Slog;
Steven Timotiusaf03df62017-07-18 16:56:43 -0700107import android.util.proto.ProtoOutputStream;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200108import android.view.DisplayInfo;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800109import android.view.IApplicationToken;
Robert Carr788f5742018-07-30 17:46:45 -0700110import android.view.InputApplicationHandle;
Evan Rosky966759f2019-01-15 10:33:58 -0800111import android.view.RemoteAnimationAdapter;
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100112import android.view.RemoteAnimationDefinition;
Robert Carr6914f082017-03-20 19:04:30 -0700113import android.view.SurfaceControl;
Tony Mak64b8d562017-12-28 17:44:02 +0000114import android.view.SurfaceControl.Transaction;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800115import android.view.WindowManager;
Jorim Jaggi87fdbcb2017-08-17 13:41:11 +0200116import android.view.WindowManager.LayoutParams;
Tony Mak64b8d562017-12-28 17:44:02 +0000117import android.view.animation.Animation;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800118
Tony Mak64b8d562017-12-28 17:44:02 +0000119import com.android.internal.R;
Riddle Hsua118b3a2018-10-11 22:05:06 +0800120import com.android.internal.annotations.VisibleForTesting;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800121import com.android.internal.util.ToBooleanFunction;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800122import com.android.server.AttributeCache;
chaviwdcf76ec2019-01-11 16:48:46 -0800123import com.android.server.LocalServices;
Christine Franks0ada2772019-02-25 13:54:57 -0800124import com.android.server.display.color.ColorDisplayService;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800125import com.android.server.policy.WindowManagerPolicy;
Adrian Roose99bc052017-11-20 17:55:31 +0100126import com.android.server.policy.WindowManagerPolicy.StartingSurface;
Evan Rosky2289ba12018-11-19 18:28:18 -0800127import com.android.server.wm.RemoteAnimationController.RemoteAnimationRecord;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800128import com.android.server.wm.WindowManagerService.H;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800129
130import java.io.PrintWriter;
chaviwdcf76ec2019-01-11 16:48:46 -0800131import java.lang.ref.WeakReference;
Jorim Jaggi0429f352015-12-22 16:29:16 +0100132import java.util.ArrayDeque;
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800133import java.util.ArrayList;
lumark588a3e82018-07-20 18:53:54 +0800134import java.util.function.Consumer;
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800135
136class AppTokenList extends ArrayList<AppWindowToken> {
137}
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800138
139/**
140 * Version of WindowToken that is specifically for a particular application (or
141 * really activity) that is displaying windows.
142 */
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800143class AppWindowToken extends WindowToken implements WindowManagerService.AppFreezeListener,
144 ConfigurationContainerListener {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800145 private static final String TAG = TAG_WITH_CLASS_NAME ? "AppWindowToken" : TAG_WM;
146
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100147 /**
148 * Value to increment the z-layer when boosting a layer during animations. BOOST in l33tsp34k.
149 */
Jorim Jaggi9cd99132019-04-24 17:41:35 +0200150 @VisibleForTesting static final int Z_BOOST_BASE = 800570000;
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100151
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800152 // Non-null only for application tokens.
153 final IApplicationToken appToken;
Winson Chung48b25652018-10-22 14:04:30 -0700154 final ComponentName mActivityComponent;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800155 final boolean mVoiceInteraction;
Dianne Hackborne30e02f2014-05-27 18:24:45 -0700156
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -0700157 /**
158 * The activity is opaque and fills the entire space of this task.
159 * @see WindowContainer#fillsParent()
160 */
161 private boolean mOccludesParent;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800162 boolean mShowForAllUsers;
163 int mTargetSdk;
Craig Mautnera2c77052012-03-26 12:14:43 -0700164
Bryce Lee6d410262017-02-28 15:30:17 -0800165 // Flag set while reparenting to prevent actions normally triggered by an individual parent
166 // change.
167 private boolean mReparenting;
168
Wale Ogunwalee287e192017-04-21 09:30:12 -0700169 // True if we are current in the process of removing this app token from the display
170 private boolean mRemovingFromDisplay = false;
171
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800172 // The input dispatching timeout for this application token in nanoseconds.
Wale Ogunwale72919d22016-12-08 18:58:50 -0800173 long mInputDispatchingTimeoutNanos;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800174
175 // These are used for determining when all windows associated with
176 // an activity have been drawn, so they can be made visible together
177 // at the same time.
Craig Mautner764983d2012-03-22 11:37:36 -0700178 // initialize so that it doesn't match mTransactionSequence which is an int.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700179 private long mLastTransactionSequence = Long.MIN_VALUE;
180 private int mNumInterestingWindows;
181 private int mNumDrawnWindows;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800182 boolean inPendingTransaction;
183 boolean allDrawn;
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000184 private boolean mLastAllDrawn;
Tiger Huangc9d0d002019-05-29 22:55:29 +0800185 private boolean mUseTransferredAnimation;
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000186
Craig Mautner7636dfb2012-11-16 15:24:11 -0800187 // Set to true when this app creates a surface while in the middle of an animation. In that
188 // case do not clear allDrawn until the animation completes.
189 boolean deferClearAllDrawn;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800190
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800191 // Is this window's surface needed? This is almost like hidden, except
192 // it will sometimes be true a little earlier: when the token has
193 // been shown, but is still waiting for its app transition to execute
194 // before making its windows shown.
195 boolean hiddenRequested;
196
197 // Have we told the window clients to hide themselves?
Wale Ogunwale89973222017-04-23 18:39:45 -0700198 private boolean mClientHidden;
199
200 // If true we will defer setting mClientHidden to true and reporting to the client that it is
201 // hidden.
202 boolean mDeferHidingClient;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800203
204 // Last visibility state we reported to the app token.
205 boolean reportedVisible;
206
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700207 // Last drawn state we reported to the app token.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700208 private boolean reportedDrawn;
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700209
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800210 // Set to true when the token has been removed from the window mgr.
211 boolean removed;
212
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800213 // Information about an application starting window if displayed.
Tarandeep Singh69ab1042019-07-30 13:30:03 -0700214 // Note: these are de-referenced before the starting window animates away.
chaviwa8f07a72019-05-01 16:25:39 -0700215 StartingData mStartingData;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800216 WindowState startingWindow;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800217 StartingSurface startingSurface;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800218 boolean startingDisplayed;
219 boolean startingMoved;
Jorim Jaggi60f9c972018-02-01 19:21:07 +0100220
Wale Ogunwale6c459212017-05-17 08:56:03 -0700221 // True if the hidden state of this token was forced to false due to a transferred starting
222 // window.
223 private boolean mHiddenSetFromTransferredStartingWindow;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800224 boolean firstWindowDrawn;
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700225 private final WindowState.UpdateReportedVisibilityResults mReportedVisibilityResults =
226 new WindowState.UpdateReportedVisibilityResults();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800227
228 // Input application handle used by the input dispatcher.
Jeff Brown9302c872011-07-13 22:51:29 -0700229 final InputApplicationHandle mInputApplicationHandle;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800230
Wale Ogunwale571771c2016-08-26 13:18:50 -0700231 // TODO: Have a WindowContainer state for tracking exiting/deferred removal.
Craig Mautner799bc1d2015-01-14 10:33:48 -0800232 boolean mIsExiting;
Craig Mautner9ef471f2014-02-07 13:11:47 -0800233
Craig Mautnerbb742462014-07-07 15:28:55 -0700234 boolean mLaunchTaskBehind;
Craig Mautner8746a472014-07-24 15:12:54 -0700235 boolean mEnteringAnimation;
Craig Mautnerbb742462014-07-07 15:28:55 -0700236
Wale Ogunwale72919d22016-12-08 18:58:50 -0800237 private boolean mAlwaysFocusable;
Wale Ogunwale6cae7652015-12-26 07:36:26 -0800238
Robert Carre12aece2016-02-02 22:43:27 -0800239 boolean mAppStopped;
Robert Carrfd10cd12016-06-29 16:41:50 -0700240 int mRotationAnimationHint;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700241 private int mPendingRelaunchCount;
Robert Carre12aece2016-02-02 22:43:27 -0800242
Jorim Jaggife762342016-10-13 14:33:27 +0200243 private boolean mLastContainsShowWhenLockedWindow;
244 private boolean mLastContainsDismissKeyguardWindow;
245
Jorim Jaggi0429f352015-12-22 16:29:16 +0100246 ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
Jorim Jaggi26c8c422016-05-09 19:57:25 -0700247 ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
Jorim Jaggi0429f352015-12-22 16:29:16 +0100248
Riddle Hsub398da32019-01-21 21:48:16 +0800249 /**
250 * The scale to fit at least one side of the activity to its parent. If the activity uses
251 * 1920x1080, and the actually size on the screen is 960x540, then the scale is 0.5.
252 */
253 private float mSizeCompatScale = 1f;
254 /**
255 * The bounds in global coordinates for activity in size compatibility mode.
256 * @see ActivityRecord#inSizeCompatMode
257 */
258 private Rect mSizeCompatBounds;
259
Wale Ogunwale6c459212017-05-17 08:56:03 -0700260 private boolean mDisablePreviewScreenshots;
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +0100261
Wale Ogunwale034a8ec2017-09-02 17:14:40 -0700262 private Task mLastParent;
Robert Carred3e83b2017-04-21 13:26:55 -0700263
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800264 // TODO: Remove after unification
265 ActivityRecord mActivityRecord;
266
chaviwd3bf08d2017-08-01 17:24:59 -0700267 /**
Riddle Hsu4bb06be2019-07-02 01:03:07 +0800268 * @see #currentLaunchCanTurnScreenOn()
chaviwd3bf08d2017-08-01 17:24:59 -0700269 */
Riddle Hsu4bb06be2019-07-02 01:03:07 +0800270 private boolean mCurrentLaunchCanTurnScreenOn = true;
chaviwd3bf08d2017-08-01 17:24:59 -0700271
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200272 /**
273 * If we are running an animation, this determines the transition type. Must be one of
274 * AppTransition.TRANSIT_* constants.
275 */
276 private int mTransit;
277
278 /**
279 * If we are running an animation, this determines the flags during this animation. Must be a
280 * bitwise combination of AppTransition.TRANSIT_FLAG_* constants.
281 */
282 private int mTransitFlags;
283
284 /** Whether our surface was set to be showing in the last call to {@link #prepareSurfaces} */
Jorim Jaggifd1891462017-12-29 15:41:36 +0100285 private boolean mLastSurfaceShowing = true;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200286
Evan Rosky2289ba12018-11-19 18:28:18 -0800287 /**
288 * This gets used during some open/close transitions as well as during a change transition
289 * where it represents the starting-state snapshot.
290 */
Jorim Jaggi988f6682017-11-17 17:46:43 +0100291 private AppWindowThumbnail mThumbnail;
Evan Rosky2289ba12018-11-19 18:28:18 -0800292 private final Rect mTransitStartRect = new Rect();
293
294 /**
295 * This leash is used to "freeze" the app surface in place after the state change, but before
296 * the animation is ready to start.
297 */
298 private SurfaceControl mTransitChangeLeash = null;
Jorim Jaggi988f6682017-11-17 17:46:43 +0100299
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000300 /** Have we been asked to have this token keep the screen frozen? */
301 private boolean mFreezingScreen;
302
303 /** Whether this token should be boosted at the top of all app window tokens. */
Jorim Jaggi9cd99132019-04-24 17:41:35 +0200304 @VisibleForTesting boolean mNeedsZBoost;
Adrian Roos4d18a2e2017-12-19 19:08:05 +0100305 private Letterbox mLetterbox;
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000306
chaviw23ee71c2017-12-18 11:29:41 -0800307 private final Point mTmpPoint = new Point();
chaviw23012112017-12-20 15:29:04 -0800308 private final Rect mTmpRect = new Rect();
Evan Rosky2289ba12018-11-19 18:28:18 -0800309 private final Rect mTmpPrevBounds = new Rect();
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100310 private RemoteAnimationDefinition mRemoteAnimationDefinition;
Jorim Jaggi6de61012018-03-19 14:53:23 +0100311 private AnimatingAppWindowTokenRegistry mAnimatingAppWindowTokenRegistry;
chaviw23ee71c2017-12-18 11:29:41 -0800312
chaviw4ad54912018-05-30 11:05:44 -0700313 /**
314 * A flag to determine if this AWT is in the process of closing or entering PIP. This is needed
315 * to help AWT know that the app is in the process of closing but hasn't yet started closing on
316 * the WM side.
317 */
318 private boolean mWillCloseOrEnterPip;
319
Vishnu Naira2977262018-07-26 13:31:26 -0700320 /** Layer used to constrain the animation to a token's stack bounds. */
321 SurfaceControl mAnimationBoundsLayer;
322
323 /** Whether this token needs to create mAnimationBoundsLayer for cropping animations. */
324 boolean mNeedsAnimationBoundsLayer;
325
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800326 private static final int STARTING_WINDOW_TYPE_NONE = 0;
327 private static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
328 private static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
329
chaviwdcf76ec2019-01-11 16:48:46 -0800330 private AppSaturationInfo mLastAppSaturationInfo;
331
332 private final ColorDisplayService.ColorTransformController mColorTransformController =
333 (matrix, translation) -> mWmService.mH.post(() -> {
334 synchronized (mWmService.mGlobalLock) {
335 if (mLastAppSaturationInfo == null) {
336 mLastAppSaturationInfo = new AppSaturationInfo();
337 }
338
339 mLastAppSaturationInfo.setSaturation(matrix, translation);
340 updateColorTransform();
341 }
342 });
343
Winson Chung48b25652018-10-22 14:04:30 -0700344 AppWindowToken(WindowManagerService service, IApplicationToken token,
345 ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
346 long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers,
Jorim Jaggi91d382a2019-03-27 17:00:48 +0100347 int targetSdk, int orientation, int rotationAnimationHint,
Winson Chung48b25652018-10-22 14:04:30 -0700348 boolean launchTaskBehind, boolean alwaysFocusable,
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800349 ActivityRecord activityRecord) {
Winson Chung48b25652018-10-22 14:04:30 -0700350 this(service, token, activityComponent, voiceInteraction, dc, fullscreen);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800351 // TODO: remove after unification
352 mActivityRecord = activityRecord;
353 mActivityRecord.registerConfigurationChangeListener(this);
Wale Ogunwale72919d22016-12-08 18:58:50 -0800354 mInputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800355 mShowForAllUsers = showForAllUsers;
356 mTargetSdk = targetSdk;
357 mOrientation = orientation;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800358 mLaunchTaskBehind = launchTaskBehind;
359 mAlwaysFocusable = alwaysFocusable;
360 mRotationAnimationHint = rotationAnimationHint;
361
362 // Application tokens start out hidden.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200363 setHidden(true);
Wale Ogunwale72919d22016-12-08 18:58:50 -0800364 hiddenRequested = true;
chaviwdcf76ec2019-01-11 16:48:46 -0800365
366 ColorDisplayService.ColorDisplayServiceInternal cds = LocalServices.getService(
367 ColorDisplayService.ColorDisplayServiceInternal.class);
368 cds.attachColorTransformController(activityRecord.packageName, activityRecord.mUserId,
369 new WeakReference<>(mColorTransformController));
Wale Ogunwale72919d22016-12-08 18:58:50 -0800370 }
371
Winson Chung48b25652018-10-22 14:04:30 -0700372 AppWindowToken(WindowManagerService service, IApplicationToken token,
373 ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
374 boolean fillsParent) {
Wale Ogunwale5cd907d2017-01-26 14:14:08 -0800375 super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true, dc,
376 false /* ownerCanManageAppTokens */);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700377 appToken = token;
Winson Chung48b25652018-10-22 14:04:30 -0700378 mActivityComponent = activityComponent;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800379 mVoiceInteraction = voiceInteraction;
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -0700380 mOccludesParent = fillsParent;
Robert Carr0bcbe642018-10-11 19:07:43 -0700381 mInputApplicationHandle = new InputApplicationHandle(appToken.asBinder());
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800382 }
383
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800384 void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
385 firstWindowDrawn = true;
386
387 // We now have a good window to show, remove dead placeholders
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700388 removeDeadWindows();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800389
Jorim Jaggi02886a82016-12-06 09:10:06 -0800390 if (startingWindow != null) {
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800391 if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Slog.v(TAG, "Finish starting "
392 + win.mToken + ": first real window is shown, no animation");
393 // If this initial window is animating, stop it -- we will do an animation to reveal
394 // it from behind the starting window, so there is no need for it to also be doing its
395 // own stuff.
Jorim Jaggia5e10572017-11-15 14:36:26 +0100396 win.cancelAnimation();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800397 }
chaviwa8f07a72019-05-01 16:25:39 -0700398 removeStartingWindow();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800399 updateReportedVisibilityLocked();
400 }
401
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800402 void updateReportedVisibilityLocked() {
403 if (appToken == null) {
404 return;
405 }
406
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700407 if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700408 final int count = mChildren.size();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800409
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700410 mReportedVisibilityResults.reset();
411
412 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700413 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700414 win.updateReportedVisibility(mReportedVisibilityResults);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800415 }
416
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700417 int numInteresting = mReportedVisibilityResults.numInteresting;
418 int numVisible = mReportedVisibilityResults.numVisible;
419 int numDrawn = mReportedVisibilityResults.numDrawn;
420 boolean nowGone = mReportedVisibilityResults.nowGone;
421
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700422 boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200423 boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting && !isHidden();
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700424 if (!nowGone) {
425 // If the app is not yet gone, then it can only become visible/drawn.
426 if (!nowDrawn) {
427 nowDrawn = reportedDrawn;
428 }
429 if (!nowVisible) {
430 nowVisible = reportedVisible;
431 }
432 }
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800433 if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800434 + numInteresting + " visible=" + numVisible);
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700435 if (nowDrawn != reportedDrawn) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800436 if (mActivityRecord != null) {
437 mActivityRecord.onWindowsDrawn(nowDrawn, SystemClock.uptimeMillis());
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700438 }
439 reportedDrawn = nowDrawn;
440 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800441 if (nowVisible != reportedVisible) {
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700442 if (DEBUG_VISIBILITY) Slog.v(TAG,
443 "Visibility changed in " + this + ": vis=" + nowVisible);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800444 reportedVisible = nowVisible;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800445 if (mActivityRecord != null) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800446 if (nowVisible) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800447 onWindowsVisible();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800448 } else {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800449 onWindowsGone();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800450 }
451 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800452 }
453 }
454
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800455 private void onWindowsGone() {
456 if (mActivityRecord == null) {
457 return;
458 }
459 if (DEBUG_VISIBILITY) {
460 Slog.v(TAG_WM, "Reporting gone in " + mActivityRecord.appToken);
461 }
462 mActivityRecord.onWindowsGone();
463 }
464
465 private void onWindowsVisible() {
466 if (mActivityRecord == null) {
467 return;
468 }
469 if (DEBUG_VISIBILITY) {
470 Slog.v(TAG_WM, "Reporting visible in " + mActivityRecord.appToken);
471 }
472 mActivityRecord.onWindowsVisible();
473 }
474
Wale Ogunwale89973222017-04-23 18:39:45 -0700475 boolean isClientHidden() {
476 return mClientHidden;
477 }
478
479 void setClientHidden(boolean hideClient) {
480 if (mClientHidden == hideClient || (hideClient && mDeferHidingClient)) {
481 return;
482 }
Jorim Jaggi067b5bf2018-02-23 17:42:39 +0100483 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "setClientHidden: " + this
484 + " clientHidden=" + hideClient + " Callers=" + Debug.getCallers(5));
Wale Ogunwale89973222017-04-23 18:39:45 -0700485 mClientHidden = hideClient;
486 sendAppVisibilityToClients();
487 }
488
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800489 void setVisibility(boolean visible, boolean deferHidingClient) {
490 final AppTransition appTransition = getDisplayContent().mAppTransition;
491
492 // Don't set visibility to false if we were already not visible. This prevents WM from
493 // adding the app to the closing app list which doesn't make sense for something that is
494 // already not visible. However, set visibility to true even if we are already visible.
495 // This makes sure the app is added to the opening apps list so that the right
496 // transition can be selected.
497 // TODO: Probably a good idea to separate the concept of opening/closing apps from the
498 // concept of setting visibility...
499 if (!visible && hiddenRequested) {
500
501 if (!deferHidingClient && mDeferHidingClient) {
502 // We previously deferred telling the client to hide itself when visibility was
503 // initially set to false. Now we would like it to hide, so go ahead and set it.
504 mDeferHidingClient = deferHidingClient;
505 setClientHidden(true);
506 }
507 return;
508 }
509
510 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) {
511 Slog.v(TAG_WM, "setAppVisibility("
512 + appToken + ", visible=" + visible + "): " + appTransition
513 + " hidden=" + isHidden() + " hiddenRequested="
514 + hiddenRequested + " Callers=" + Debug.getCallers(6));
515 }
516
517 final DisplayContent displayContent = getDisplayContent();
518 displayContent.mOpeningApps.remove(this);
519 displayContent.mClosingApps.remove(this);
Evan Roskyb1e75f72019-04-26 20:23:26 -0700520 if (isInChangeTransition()) {
521 clearChangeLeash(getPendingTransaction(), true /* cancel */);
522 }
523 displayContent.mChangingApps.remove(this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800524 waitingToShow = false;
525 hiddenRequested = !visible;
526 mDeferHidingClient = deferHidingClient;
527
528 if (!visible) {
529 // If the app is dead while it was visible, we kept its dead window on screen.
530 // Now that the app is going invisible, we can remove it. It will be restarted
531 // if made visible again.
532 removeDeadWindows();
533 } else {
534 if (!appTransition.isTransitionSet()
535 && appTransition.isReady()) {
536 // Add the app mOpeningApps if transition is unset but ready. This means
537 // we're doing a screen freeze, and the unfreeze will wait for all opening
538 // apps to be ready.
539 displayContent.mOpeningApps.add(this);
540 }
541 startingMoved = false;
542 // If the token is currently hidden (should be the common case), or has been
543 // stopped, then we need to set up to wait for its windows to be ready.
544 if (isHidden() || mAppStopped) {
545 clearAllDrawn();
546
547 // If the app was already visible, don't reset the waitingToShow state.
548 if (isHidden()) {
549 waitingToShow = true;
Jorim Jaggi6ec52d42019-07-03 15:45:59 +0200550
wilsonshih78e55422019-09-10 09:44:51 +0800551 // If the client isn't hidden, we don't need to reset the drawing state.
552 if (isClientHidden()) {
553 // Let's reset the draw state in order to prevent the starting window to be
554 // immediately dismissed when the app still has the surface.
555 forAllWindows(w -> {
556 if (w.mWinAnimator.mDrawState == HAS_DRAWN) {
557 w.mWinAnimator.resetDrawState();
Jorim Jaggi6ec52d42019-07-03 15:45:59 +0200558
wilsonshih78e55422019-09-10 09:44:51 +0800559 // Force add to mResizingWindows, so that we are guaranteed to get
560 // another reportDrawn callback.
561 w.resetLastContentInsets();
562 }
563 }, true /* traverseTopToBottom */);
564 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800565 }
566 }
567
568 // In the case where we are making an app visible but holding off for a transition,
569 // we still need to tell the client to make its windows visible so they get drawn.
570 // Otherwise, we will wait on performing the transition until all windows have been
571 // drawn, they never will be, and we are sad.
572 setClientHidden(false);
573
574 requestUpdateWallpaperIfNeeded();
575
576 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "No longer Stopped: " + this);
577 mAppStopped = false;
578
579 transferStartingWindowFromHiddenAboveTokenIfNeeded();
580 }
581
582 // If we are preparing an app transition, then delay changing
583 // the visibility of this token until we execute that transition.
584 if (okToAnimate() && appTransition.isTransitionSet()) {
585 inPendingTransaction = true;
586 if (visible) {
587 displayContent.mOpeningApps.add(this);
588 mEnteringAnimation = true;
589 } else {
590 displayContent.mClosingApps.add(this);
591 mEnteringAnimation = false;
592 }
Louis Chang37317152019-05-09 09:53:58 +0800593 if (appTransition.getAppTransition() == TRANSIT_TASK_OPEN_BEHIND) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800594 // We're launchingBehind, add the launching activity to mOpeningApps.
595 final WindowState win = getDisplayContent().findFocusedWindow();
596 if (win != null) {
597 final AppWindowToken focusedToken = win.mAppToken;
598 if (focusedToken != null) {
599 if (DEBUG_APP_TRANSITIONS) {
600 Slog.d(TAG_WM, "TRANSIT_TASK_OPEN_BEHIND, "
601 + " adding " + focusedToken + " to mOpeningApps");
602 }
603 // Force animation to be loaded.
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800604 displayContent.mOpeningApps.add(focusedToken);
605 }
606 }
607 }
Garfield Tanb6776602019-02-20 14:44:26 -0800608 // Changes in opening apps and closing apps may cause orientation change.
609 reportDescendantOrientationChangeIfNeeded();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800610 return;
611 }
612
613 commitVisibility(null, visible, TRANSIT_UNSET, true, mVoiceInteraction);
614 updateReportedVisibilityLocked();
615 }
616
617 boolean commitVisibility(WindowManager.LayoutParams lp,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700618 boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
619
620 boolean delayed = false;
621 inPendingTransaction = false;
Wale Ogunwale9e4721f2017-05-23 19:37:30 -0700622 // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually
623 // been set by the app now.
624 mHiddenSetFromTransferredStartingWindow = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700625
626 // Allow for state changes and animation to be applied if:
627 // * token is transitioning visibility state
628 // * or the token was marked as hidden and is exiting before we had a chance to play the
629 // transition animation
Louis Chang37317152019-05-09 09:53:58 +0800630 // * or this is an opening app and windows are being replaced
631 // * or the token is the opening app and visible while opening task behind existing one.
632 final DisplayContent displayContent = getDisplayContent();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700633 boolean visibilityChanged = false;
Louis Chang37317152019-05-09 09:53:58 +0800634 if (isHidden() == visible || (isHidden() && mIsExiting)
635 || (visible && waitingForReplacement())
636 || (visible && displayContent.mOpeningApps.contains(this)
637 && displayContent.mAppTransition.getAppTransition() == TRANSIT_TASK_OPEN_BEHIND)) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800638 final AccessibilityController accessibilityController =
639 mWmService.mAccessibilityController;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700640 boolean changed = false;
641 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM,
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200642 "Changing app " + this + " hidden=" + isHidden() + " performLayout=" + performLayout);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700643
644 boolean runningAppAnimation = false;
645
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100646 if (transit != WindowManager.TRANSIT_UNSET) {
Tiger Huangc9d0d002019-05-29 22:55:29 +0800647 if (mUseTransferredAnimation) {
648 runningAppAnimation = isReallyAnimating();
649 } else if (applyAnimationLocked(lp, transit, visible, isVoiceInteraction)) {
650 runningAppAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700651 }
Tiger Huangc9d0d002019-05-29 22:55:29 +0800652 delayed = runningAppAnimation;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700653 final WindowState window = findMainWindow();
Rhed Jao02655dc2018-10-30 20:44:52 +0800654 if (window != null && accessibilityController != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700655 accessibilityController.onAppWindowTransitionLocked(window, transit);
656 }
657 changed = true;
658 }
659
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700660 final int windowsCount = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700661 for (int i = 0; i < windowsCount; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700662 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700663 changed |= win.onAppVisibilityChanged(visible, runningAppAnimation);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700664 }
665
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200666 setHidden(!visible);
667 hiddenRequested = !visible;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700668 visibilityChanged = true;
669 if (!visible) {
670 stopFreezingScreen(true, true);
671 } else {
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700672 // If we are being set visible, and the starting window is not yet displayed,
673 // then make sure it doesn't get displayed.
674 if (startingWindow != null && !startingWindow.isDrawnLw()) {
chaviw15ad49f2019-04-24 15:05:39 -0700675 startingWindow.clearPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY);
676 startingWindow.mLegacyPolicyVisibilityAfterAnim = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700677 }
Jorim Jaggi38d44ec2017-06-14 16:04:59 -0700678
679 // We are becoming visible, so better freeze the screen with the windows that are
680 // getting visible so we also wait for them.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800681 forAllWindows(mWmService::makeWindowFreezingScreenIfNeededLocked, true);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700682 }
683
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800684 if (DEBUG_APP_TRANSITIONS) {
685 Slog.v(TAG_WM, "commitVisibility: " + this
686 + ": hidden=" + isHidden() + " hiddenRequested=" + hiddenRequested);
687 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700688
689 if (changed) {
Louis Chang37317152019-05-09 09:53:58 +0800690 displayContent.getInputMonitor().setUpdateInputWindowsNeededLw();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700691 if (performLayout) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800692 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700693 false /*updateInputWindows*/);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800694 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700695 }
Louis Chang37317152019-05-09 09:53:58 +0800696 displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700697 }
698 }
Tiger Huangc9d0d002019-05-29 22:55:29 +0800699 mUseTransferredAnimation = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700700
lumarkd14173e2019-03-27 19:14:33 +0800701 if (isReallyAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700702 delayed = true;
Jorim Jaggiab9fcb22018-03-15 23:46:12 +0100703 } else {
704
705 // We aren't animating anything, but exiting windows rely on the animation finished
706 // callback being called in case the AppWindowToken was pretending to be animating,
707 // which we might have done because we were in closing/opening apps list.
708 onAnimationFinished();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700709 }
710
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700711 for (int i = mChildren.size() - 1; i >= 0 && !delayed; i--) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100712 if ((mChildren.get(i)).isSelfOrChildAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700713 delayed = true;
714 }
715 }
716
717 if (visibilityChanged) {
718 if (visible && !delayed) {
719 // The token was made immediately visible, there will be no entrance animation.
720 // We need to inform the client the enter animation was finished.
721 mEnteringAnimation = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800722 mWmService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(
723 token);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700724 }
Robert Carr61b81112017-07-17 18:08:15 -0700725
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800726 // If we're becoming visible, immediately change client visibility as well. there seem
727 // to be some edge cases where we change our visibility but client visibility never gets
728 // updated.
Jorim Jaggi110839b2018-01-22 12:49:04 +0100729 // If we're becoming invisible, update the client visibility if we are not running an
730 // animation. Otherwise, we'll update client visibility in onAnimationFinished.
Jorim Jaggi3cad57f2018-02-20 18:32:01 +0100731 if (visible || !isReallyAnimating()) {
Jorim Jaggi110839b2018-01-22 12:49:04 +0100732 setClientHidden(!visible);
Jorim Jaggi4876b4a2018-01-11 15:43:49 +0100733 }
734
Louis Chang37317152019-05-09 09:53:58 +0800735 if (!displayContent.mClosingApps.contains(this)
736 && !displayContent.mOpeningApps.contains(this)) {
chaviwa953fcf2018-03-01 12:00:39 -0800737 // The token is not closing nor opening, so even if there is an animation set, that
738 // doesn't mean that it goes through the normal app transition cycle so we have
739 // to inform the docked controller about visibility change.
740 // TODO(multi-display): notify docked divider on all displays where visibility was
741 // affected.
Louis Chang37317152019-05-09 09:53:58 +0800742 displayContent.getDockedDividerController().notifyAppVisibilityChanged();
chaviwa953fcf2018-03-01 12:00:39 -0800743
744 // Take the screenshot before possibly hiding the WSA, otherwise the screenshot
745 // will not be taken.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800746 mWmService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible);
chaviwa953fcf2018-03-01 12:00:39 -0800747 }
748
Robert Carre7cc44d2017-03-20 19:04:30 -0700749 // If we are hidden but there is no delay needed we immediately
750 // apply the Surface transaction so that the ActivityManager
Robert Carr61b81112017-07-17 18:08:15 -0700751 // can have some guarantee on the Surface state following
752 // setting the visibility. This captures cases like dismissing
753 // the docked or pinned stack where there is no app transition.
754 //
755 // In the case of a "Null" animation, there will be
756 // no animation but there will still be a transition set.
757 // We still need to delay hiding the surface such that it
758 // can be synchronized with showing the next surface in the transition.
Louis Chang37317152019-05-09 09:53:58 +0800759 if (isHidden() && !delayed && !displayContent.mAppTransition.isTransitionSet()) {
Robert Carr6914f082017-03-20 19:04:30 -0700760 SurfaceControl.openTransaction();
761 for (int i = mChildren.size() - 1; i >= 0; i--) {
762 mChildren.get(i).mWinAnimator.hide("immediately hidden");
763 }
764 SurfaceControl.closeTransaction();
765 }
Garfield Tanb6776602019-02-20 14:44:26 -0800766
767 // Visibility changes may cause orientation request change.
768 reportDescendantOrientationChangeIfNeeded();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700769 }
770
771 return delayed;
772 }
773
Garfield Tanb6776602019-02-20 14:44:26 -0800774 private void reportDescendantOrientationChangeIfNeeded() {
775 // Orientation request is exposed only when we're visible. Therefore visibility change
776 // will change requested orientation. Notify upward the hierarchy ladder to adjust
777 // configuration. This is important to cases where activities with incompatible
778 // orientations launch, or user goes back from an activity of bi-orientation to an
779 // activity with specified orientation.
780 if (mActivityRecord.getRequestedConfigurationOrientation() == getConfiguration().orientation
781 || getOrientationIgnoreVisibility() == SCREEN_ORIENTATION_UNSET) {
782 return;
783 }
784
785 final IBinder freezeToken =
786 mActivityRecord.mayFreezeScreenLocked(mActivityRecord.app)
787 ? mActivityRecord.appToken : null;
788 onDescendantOrientationChanged(freezeToken, mActivityRecord);
789 }
790
Jorim Jaggi87fdbcb2017-08-17 13:41:11 +0200791 /**
792 * @return The to top most child window for which {@link LayoutParams#isFullscreen()} returns
793 * true.
794 */
795 WindowState getTopFullscreenWindow() {
796 for (int i = mChildren.size() - 1; i >= 0; i--) {
797 final WindowState win = mChildren.get(i);
798 if (win != null && win.mAttrs.isFullscreen()) {
799 return win;
800 }
801 }
802 return null;
803 }
804
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800805 WindowState findMainWindow() {
Matthew Ng53e66b22018-01-12 17:13:13 -0800806 return findMainWindow(true);
807 }
808
809 /**
810 * Finds the main window that either has type base application or application starting if
811 * requested.
812 *
813 * @param includeStartingApp Allow to search application-starting windows to also be returned.
814 * @return The main window of type base application or application starting if requested.
815 */
816 WindowState findMainWindow(boolean includeStartingApp) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700817 WindowState candidate = null;
Matthew Ng53e66b22018-01-12 17:13:13 -0800818 for (int j = mChildren.size() - 1; j >= 0; --j) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700819 final WindowState win = mChildren.get(j);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700820 final int type = win.mAttrs.type;
821 // No need to loop through child window as base application and starting types can't be
822 // child windows.
Matthew Ng53e66b22018-01-12 17:13:13 -0800823 if (type == TYPE_BASE_APPLICATION
824 || (includeStartingApp && type == TYPE_APPLICATION_STARTING)) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700825 // In cases where there are multiple windows, we prefer the non-exiting window. This
Sungsoo Lim0d3d1f82015-12-02 14:47:59 +0900826 // happens for example when replacing windows during an activity relaunch. When
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700827 // constructing the animation, we want the new window, not the exiting one.
Wale Ogunwalec48a3542016-02-19 15:18:45 -0800828 if (win.mAnimatingExit) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700829 candidate = win;
830 } else {
831 return win;
832 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800833 }
834 }
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700835 return candidate;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800836 }
837
Wale Ogunwale6cae7652015-12-26 07:36:26 -0800838 boolean windowsAreFocusable() {
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800839 if (mTargetSdk < Build.VERSION_CODES.Q) {
840 final int pid = mActivityRecord != null
841 ? (mActivityRecord.app != null ? mActivityRecord.app.getPid() : 0) : 0;
842 final AppWindowToken topFocusedAppOfMyProcess =
843 mWmService.mRoot.mTopFocusedAppByProcess.get(pid);
844 if (topFocusedAppOfMyProcess != null && topFocusedAppOfMyProcess != this) {
845 // For the apps below Q, there can be only one app which has the focused window per
846 // process, because legacy apps may not be ready for a multi-focus system.
847 return false;
848 }
849 }
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700850 return getWindowConfiguration().canReceiveKeys() || mAlwaysFocusable;
Wale Ogunwaled045c822015-12-02 09:14:28 -0800851 }
852
Wale Ogunwale571771c2016-08-26 13:18:50 -0700853 @Override
Wale Ogunwale44f21802016-09-02 12:49:48 -0700854 boolean isVisible() {
Wale Ogunwalee471be62016-10-03 07:53:55 -0700855 // If the app token isn't hidden then it is considered visible and there is no need to check
856 // its children windows to see if they are visible.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200857 return !isHidden();
Wale Ogunwale44f21802016-09-02 12:49:48 -0700858 }
859
860 @Override
Wale Ogunwalee287e192017-04-21 09:30:12 -0700861 void removeImmediately() {
862 onRemovedFromDisplay();
Yunfan Chen3a77f282018-12-12 15:47:52 -0800863 if (mActivityRecord != null) {
864 mActivityRecord.unregisterConfigurationChangeListener(this);
865 }
Wale Ogunwalee287e192017-04-21 09:30:12 -0700866 super.removeImmediately();
867 }
868
869 @Override
Wale Ogunwale571771c2016-08-26 13:18:50 -0700870 void removeIfPossible() {
Craig Mautnere3119b72015-01-20 15:02:36 -0800871 mIsExiting = false;
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800872 removeAllWindowsIfPossible();
Bryce Lee6d410262017-02-28 15:30:17 -0800873 removeImmediately();
Craig Mautnere3119b72015-01-20 15:02:36 -0800874 }
875
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700876 @Override
877 boolean checkCompleteDeferredRemoval() {
878 if (mIsExiting) {
879 removeIfPossible();
880 }
881 return super.checkCompleteDeferredRemoval();
882 }
883
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700884 void onRemovedFromDisplay() {
Wale Ogunwalee287e192017-04-21 09:30:12 -0700885 if (mRemovingFromDisplay) {
886 return;
887 }
888 mRemovingFromDisplay = true;
889
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700890 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app token: " + this);
891
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800892 boolean delayed = commitVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700893
lumark588a3e82018-07-20 18:53:54 +0800894 getDisplayContent().mOpeningApps.remove(this);
Evan Rosky2289ba12018-11-19 18:28:18 -0800895 getDisplayContent().mChangingApps.remove(this);
lumark588a3e82018-07-20 18:53:54 +0800896 getDisplayContent().mUnknownAppVisibilityController.appRemovedOrHidden(this);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800897 mWmService.mTaskSnapshotController.onAppRemoved(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700898 waitingToShow = false;
lumark588a3e82018-07-20 18:53:54 +0800899 if (getDisplayContent().mClosingApps.contains(this)) {
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700900 delayed = true;
lumark588a3e82018-07-20 18:53:54 +0800901 } else if (getDisplayContent().mAppTransition.isTransitionSet()) {
902 getDisplayContent().mClosingApps.add(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700903 delayed = true;
904 }
905
906 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app " + this + " delayed=" + delayed
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200907 + " animation=" + getAnimation() + " animating=" + isSelfAnimating());
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700908
909 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: "
910 + this + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
911
chaviwa8f07a72019-05-01 16:25:39 -0700912 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800913 removeStartingWindow();
Jorim Jaggi19be6052017-08-03 18:33:43 +0200914 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800915
Winson Chung87e5d552017-04-05 11:49:38 -0700916 // If this window was animating, then we need to ensure that the app transition notifies
lumark588a3e82018-07-20 18:53:54 +0800917 // that animations have completed in DisplayContent.handleAnimatingStoppedAndTransition(),
918 // so add to that list now
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200919 if (isSelfAnimating()) {
lumark588a3e82018-07-20 18:53:54 +0800920 getDisplayContent().mNoAnimationNotifyOnTransitionFinished.add(token);
Winson Chung87e5d552017-04-05 11:49:38 -0700921 }
922
Wale Ogunwalee287e192017-04-21 09:30:12 -0700923 final TaskStack stack = getStack();
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700924 if (delayed && !isEmpty()) {
925 // set the token aside because it has an active animation to be finished
926 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM,
927 "removeAppToken make exiting: " + this);
Wale Ogunwalee287e192017-04-21 09:30:12 -0700928 if (stack != null) {
929 stack.mExitingAppTokens.add(this);
930 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700931 mIsExiting = true;
932 } else {
933 // Make sure there is no animation running on this token, so any windows associated
934 // with it will be removed as soon as their animations are complete
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200935 cancelAnimation();
Wale Ogunwale3106ae012017-05-16 08:56:37 -0700936 if (stack != null) {
937 stack.mExitingAppTokens.remove(this);
938 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700939 removeIfPossible();
940 }
941
942 removed = true;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700943 stopFreezingScreen(true, true);
Bryce Lee6d410262017-02-28 15:30:17 -0800944
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800945 final DisplayContent dc = getDisplayContent();
946 if (dc.mFocusedApp == this) {
947 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + this
948 + " displayId=" + dc.getDisplayId());
949 dc.setFocusedApp(null);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800950 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700951 }
Riddle Hsu192fe762019-01-15 23:41:57 +0800952 if (mLetterbox != null) {
953 mLetterbox.destroy();
954 mLetterbox = null;
955 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700956
957 if (!delayed) {
958 updateReportedVisibilityLocked();
959 }
Wale Ogunwalee287e192017-04-21 09:30:12 -0700960
Hongwei Wang75b6e6c2019-09-17 10:07:56 -0700961 // Reset the last saved PiP snap fraction on removal.
962 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(mActivityComponent);
963
Wale Ogunwalee287e192017-04-21 09:30:12 -0700964 mRemovingFromDisplay = false;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700965 }
966
Chong Zhange05bcb12016-07-26 17:47:29 -0700967 void clearAnimatingFlags() {
Chong Zhangb0d26702016-08-12 16:03:29 -0700968 boolean wallpaperMightChange = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700969 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700970 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700971 wallpaperMightChange |= win.clearAnimatingFlags();
Chong Zhange05bcb12016-07-26 17:47:29 -0700972 }
Chong Zhangb0d26702016-08-12 16:03:29 -0700973 if (wallpaperMightChange) {
974 requestUpdateWallpaperIfNeeded();
975 }
Chong Zhange05bcb12016-07-26 17:47:29 -0700976 }
977
Robert Carre12aece2016-02-02 22:43:27 -0800978 void destroySurfaces() {
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700979 destroySurfaces(false /*cleanupOnResume*/);
980 }
981
982 /**
983 * Destroy surfaces which have been marked as eligible by the animator, taking care to ensure
984 * the client has finished with them.
985 *
986 * @param cleanupOnResume whether this is done when app is resumed without fully stopped. If
987 * set to true, destroy only surfaces of removed windows, and clear relevant flags of the
988 * others so that they are ready to be reused. If set to false (common case), destroy all
989 * surfaces that's eligible, if the app is already stopped.
990 */
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700991 private void destroySurfaces(boolean cleanupOnResume) {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700992 boolean destroyedSomething = false;
Jorim Jaggia5e10572017-11-15 14:36:26 +0100993
994 // Copying to a different list as multiple children can be removed.
Jorim Jaggi59f3e922018-01-05 15:40:32 +0100995 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
Jorim Jaggia5e10572017-11-15 14:36:26 +0100996 for (int i = children.size() - 1; i >= 0; i--) {
997 final WindowState win = children.get(i);
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700998 destroyedSomething |= win.destroySurface(cleanupOnResume, mAppStopped);
Robert Carre12aece2016-02-02 22:43:27 -0800999 }
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001000 if (destroyedSomething) {
1001 final DisplayContent dc = getDisplayContent();
Wale Ogunwalec69694a2016-10-18 13:51:15 -07001002 dc.assignWindowLayers(true /*setLayoutNeeded*/);
Adrian Roos23df3a32018-03-15 15:41:13 +01001003 updateLetterboxSurface(null);
Robert Carre12aece2016-02-02 22:43:27 -08001004 }
1005 }
1006
Wale Ogunwale8d5a5422016-03-03 18:28:21 -08001007 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001008 * Notify that the app is now resumed, and it was not stopped before, perform a clean
1009 * up of the surfaces
Wale Ogunwale8d5a5422016-03-03 18:28:21 -08001010 */
Jorim Jaggibae01b12017-04-11 16:29:10 -07001011 void notifyAppResumed(boolean wasStopped) {
Chong Zhangad24f962016-08-25 12:12:33 -07001012 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppResumed: wasStopped=" + wasStopped
Jorim Jaggibae01b12017-04-11 16:29:10 -07001013 + " " + this);
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001014 mAppStopped = false;
chaviwd3bf08d2017-08-01 17:24:59 -07001015 // Allow the window to turn the screen on once the app is resumed again.
Riddle Hsu4bb06be2019-07-02 01:03:07 +08001016 setCurrentLaunchCanTurnScreenOn(true);
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001017 if (!wasStopped) {
1018 destroySurfaces(true /*cleanupOnResume*/);
Wale Ogunwale8d5a5422016-03-03 18:28:21 -08001019 }
Robert Carre12aece2016-02-02 22:43:27 -08001020 }
1021
Chong Zhangbef461f2015-10-27 11:38:24 -07001022 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001023 * Notify that the app has stopped, and it is okay to destroy any surfaces which were
1024 * keeping alive in case they were still being used.
1025 */
1026 void notifyAppStopped() {
1027 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: " + this);
1028 mAppStopped = true;
Hongwei Wanga5799f82019-07-01 15:52:50 -07001029 // Reset the last saved PiP snap fraction on app stop.
Hongwei Wang43a752b2019-09-17 20:20:30 +00001030 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(mActivityComponent);
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001031 destroySurfaces();
1032 // Remove any starting window that was added for this app if they are still around.
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001033 removeStartingWindow();
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001034 }
1035
Chong Zhang92147042016-05-09 12:47:11 -07001036 void clearAllDrawn() {
1037 allDrawn = false;
1038 deferClearAllDrawn = false;
Chong Zhangbef461f2015-10-27 11:38:24 -07001039 }
1040
Bryce Lee6d410262017-02-28 15:30:17 -08001041 Task getTask() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001042 return (Task) getParent();
Bryce Lee6d410262017-02-28 15:30:17 -08001043 }
1044
Jorim Jaggi3878ca32017-02-02 17:13:05 -08001045 TaskStack getStack() {
1046 final Task task = getTask();
1047 if (task != null) {
1048 return task.mStack;
1049 } else {
1050 return null;
1051 }
1052 }
1053
Bryce Lee6d410262017-02-28 15:30:17 -08001054 @Override
Riddle Hsu3a4bb612019-01-31 00:02:22 +08001055 void onParentChanged() {
1056 super.onParentChanged();
Bryce Lee6d410262017-02-28 15:30:17 -08001057
Robert Carred3e83b2017-04-21 13:26:55 -07001058 final Task task = getTask();
1059
Bryce Lee6d410262017-02-28 15:30:17 -08001060 // When the associated task is {@code null}, the {@link AppWindowToken} can no longer
1061 // access visual elements like the {@link DisplayContent}. We must remove any associations
1062 // such as animations.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001063 if (!mReparenting) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001064 if (task == null) {
1065 // It is possible we have been marked as a closing app earlier. We must remove ourselves
1066 // from this list so we do not participate in any future animations.
lumark588a3e82018-07-20 18:53:54 +08001067 getDisplayContent().mClosingApps.remove(this);
Robert Carred3e83b2017-04-21 13:26:55 -07001068 } else if (mLastParent != null && mLastParent.mStack != null) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001069 task.mStack.mExitingAppTokens.remove(this);
1070 }
Bryce Lee6d410262017-02-28 15:30:17 -08001071 }
Jorim Jaggi6de61012018-03-19 14:53:23 +01001072 final TaskStack stack = getStack();
1073
1074 // If we reparent, make sure to remove ourselves from the old animation registry.
1075 if (mAnimatingAppWindowTokenRegistry != null) {
1076 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
1077 }
1078 mAnimatingAppWindowTokenRegistry = stack != null
1079 ? stack.getAnimatingAppWindowTokenRegistry()
1080 : null;
1081
Robert Carred3e83b2017-04-21 13:26:55 -07001082 mLastParent = task;
chaviwdcf76ec2019-01-11 16:48:46 -08001083
1084 updateColorTransform();
Bryce Lee6d410262017-02-28 15:30:17 -08001085 }
1086
Wale Ogunwalefa854eb2016-09-20 13:43:52 -07001087 void postWindowRemoveStartingWindowCleanup(WindowState win) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001088 // TODO: Something smells about the code below...Is there a better way?
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001089 if (startingWindow == win) {
1090 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Notify removed startingWindow " + win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001091 removeStartingWindow();
Wale Ogunwale6c459212017-05-17 08:56:03 -07001092 } else if (mChildren.size() == 0) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001093 // If this is the last window and we had requested a starting transition window,
1094 // well there is no point now.
Jorim Jaggi02886a82016-12-06 09:10:06 -08001095 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Nulling last startingData");
chaviwa8f07a72019-05-01 16:25:39 -07001096 mStartingData = null;
Wale Ogunwale6c459212017-05-17 08:56:03 -07001097 if (mHiddenSetFromTransferredStartingWindow) {
1098 // We set the hidden state to false for the token from a transferred starting window.
1099 // We now reset it back to true since the starting window was the last window in the
1100 // token.
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001101 setHidden(true);
Wale Ogunwale6c459212017-05-17 08:56:03 -07001102 }
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01001103 } else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001104 // If this is the last window except for a starting transition window,
1105 // we need to get rid of the starting transition.
Jorim Jaggie4b0f282017-05-17 15:10:29 +02001106 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Last window, removing starting window "
1107 + win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001108 removeStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001109 }
1110 }
1111
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001112 void removeDeadWindows() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001113 for (int winNdx = mChildren.size() - 1; winNdx >= 0; --winNdx) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001114 WindowState win = mChildren.get(winNdx);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001115 if (win.mAppDied) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001116 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.w(TAG,
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001117 "removeDeadWindows: " + win);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001118 // Set mDestroying, we don't want any animation or delayed removal here.
1119 win.mDestroying = true;
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001120 // Also removes child windows.
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001121 win.removeIfPossible();
Chong Zhang112eb8c2015-11-02 11:17:00 -08001122 }
1123 }
1124 }
1125
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001126 boolean hasWindowsAlive() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001127 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001128 // No need to loop through child windows as the answer should be the same as that of the
1129 // parent window.
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001130 if (!(mChildren.get(i)).mAppDied) {
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001131 return true;
1132 }
1133 }
1134 return false;
1135 }
1136
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001137 void setWillReplaceWindows(boolean animate) {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001138 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
1139 "Marking app token " + this + " with replacing windows.");
Robert Carra1eb4392015-12-10 12:43:51 -08001140
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001141 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001142 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001143 w.setWillReplaceWindow(animate);
Robert Carra1eb4392015-12-10 12:43:51 -08001144 }
Robert Carra1eb4392015-12-10 12:43:51 -08001145 }
1146
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001147 void setWillReplaceChildWindows() {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001148 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Marking app token " + this
Robert Carr23fa16b2016-01-13 13:19:58 -08001149 + " with replacing child windows.");
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001150 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001151 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001152 w.setWillReplaceChildWindows();
Robert Carr23fa16b2016-01-13 13:19:58 -08001153 }
1154 }
1155
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001156 void clearWillReplaceWindows() {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001157 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
1158 "Resetting app token " + this + " of replacing window marks.");
Chong Zhangf596cd52016-01-05 13:42:44 -08001159
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001160 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001161 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001162 w.clearWillReplaceWindow();
Chong Zhangf596cd52016-01-05 13:42:44 -08001163 }
1164 }
1165
Chong Zhang4d7369a2016-04-25 16:09:14 -07001166 void requestUpdateWallpaperIfNeeded() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001167 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001168 final WindowState w = mChildren.get(i);
Chong Zhang4d7369a2016-04-25 16:09:14 -07001169 w.requestUpdateWallpaperIfNeeded();
1170 }
1171 }
1172
Chong Zhangd78ddb42016-03-02 17:01:14 -08001173 boolean isRelaunching() {
1174 return mPendingRelaunchCount > 0;
1175 }
1176
Robert Carr68375192017-06-13 12:41:53 -07001177 boolean shouldFreezeBounds() {
1178 final Task task = getTask();
1179
1180 // For freeform windows, we can't freeze the bounds at the moment because this would make
1181 // the resizing unresponsive.
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001182 if (task == null || task.inFreeformWindowingMode()) {
Robert Carr68375192017-06-13 12:41:53 -07001183 return false;
1184 }
1185
1186 // We freeze the bounds while drag resizing to deal with the time between
1187 // the divider/drag handle being released, and the handling it's new
1188 // configuration. If we are relaunched outside of the drag resizing state,
1189 // we need to be careful not to do this.
1190 return getTask().isDragResizing();
1191 }
1192
Chong Zhangd78ddb42016-03-02 17:01:14 -08001193 void startRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001194 if (shouldFreezeBounds()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08001195 freezeBounds();
1196 }
Robert Carrd5c7dd62017-03-08 10:39:30 -08001197
1198 // In the process of tearing down before relaunching, the app will
1199 // try and clean up it's child surfaces. We need to prevent this from
1200 // happening, so we sever the children, transfering their ownership
1201 // from the client it-self to the parent surface (owned by us).
Robert Carr29daa922018-04-27 11:56:48 -07001202 detachChildren();
1203
1204 mPendingRelaunchCount++;
1205 }
1206
1207 void detachChildren() {
Robert Carrfd8e93b2018-05-10 13:40:25 -07001208 SurfaceControl.openTransaction();
Robert Carrd5c7dd62017-03-08 10:39:30 -08001209 for (int i = mChildren.size() - 1; i >= 0; i--) {
1210 final WindowState w = mChildren.get(i);
1211 w.mWinAnimator.detachChildren();
1212 }
Robert Carrfd8e93b2018-05-10 13:40:25 -07001213 SurfaceControl.closeTransaction();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001214 }
1215
1216 void finishRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001217 unfreezeBounds();
1218
Chong Zhangd78ddb42016-03-02 17:01:14 -08001219 if (mPendingRelaunchCount > 0) {
1220 mPendingRelaunchCount--;
Bryce Lee081554b2017-05-25 07:52:12 -07001221 } else {
1222 // Update keyguard flags upon finishing relaunch.
1223 checkKeyguardFlagsChanged();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001224 }
1225 }
1226
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001227 void clearRelaunching() {
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001228 if (mPendingRelaunchCount == 0) {
1229 return;
1230 }
Robert Carr68375192017-06-13 12:41:53 -07001231 unfreezeBounds();
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001232 mPendingRelaunchCount = 0;
1233 }
1234
Wale Ogunwale07bcab72016-10-14 15:30:09 -07001235 /**
1236 * Returns true if the new child window we are adding to this token is considered greater than
1237 * the existing child window in this token in terms of z-order.
1238 */
1239 @Override
1240 protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
1241 WindowState existingWindow) {
1242 final int type1 = newWindow.mAttrs.type;
1243 final int type2 = existingWindow.mAttrs.type;
1244
1245 // Base application windows should be z-ordered BELOW all other windows in the app token.
1246 if (type1 == TYPE_BASE_APPLICATION && type2 != TYPE_BASE_APPLICATION) {
1247 return false;
1248 } else if (type1 != TYPE_BASE_APPLICATION && type2 == TYPE_BASE_APPLICATION) {
1249 return true;
1250 }
1251
1252 // Starting windows should be z-ordered ABOVE all other windows in the app token.
1253 if (type1 == TYPE_APPLICATION_STARTING && type2 != TYPE_APPLICATION_STARTING) {
1254 return true;
1255 } else if (type1 != TYPE_APPLICATION_STARTING && type2 == TYPE_APPLICATION_STARTING) {
1256 return false;
1257 }
1258
1259 // Otherwise the new window is greater than the existing window.
1260 return true;
1261 }
1262
Tarandeep Singh69ab1042019-07-30 13:30:03 -07001263 /**
1264 * @return {@code true} if starting window is in app's hierarchy.
1265 */
1266 boolean hasStartingWindow() {
1267 if (startingDisplayed || mStartingData != null) {
1268 return true;
1269 }
1270 for (int i = mChildren.size() - 1; i >= 0; i--) {
1271 if (getChildAt(i).mAttrs.type == TYPE_APPLICATION_STARTING) {
1272 return true;
1273 }
1274 }
1275 return false;
1276 }
1277
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001278 @Override
Robert Carra1eb4392015-12-10 12:43:51 -08001279 void addWindow(WindowState w) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001280 super.addWindow(w);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001281
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001282 boolean gotReplacementWindow = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001283 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001284 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001285 gotReplacementWindow |= candidate.setReplacementWindowIfNeeded(w);
1286 }
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001287
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001288 // if we got a replacement window, reset the timeout to give drawing more time
1289 if (gotReplacementWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001290 mWmService.scheduleWindowReplacementTimeouts(this);
Robert Carra1eb4392015-12-10 12:43:51 -08001291 }
Jorim Jaggife762342016-10-13 14:33:27 +02001292 checkKeyguardFlagsChanged();
1293 }
1294
1295 @Override
1296 void removeChild(WindowState child) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001297 if (!mChildren.contains(child)) {
1298 // This can be true when testing.
1299 return;
1300 }
Jorim Jaggife762342016-10-13 14:33:27 +02001301 super.removeChild(child);
1302 checkKeyguardFlagsChanged();
Adrian Roos23df3a32018-03-15 15:41:13 +01001303 updateLetterboxSurface(child);
Robert Carra1eb4392015-12-10 12:43:51 -08001304 }
1305
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001306 private boolean waitingForReplacement() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001307 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001308 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001309 if (candidate.waitingForReplacement()) {
Robert Carra1eb4392015-12-10 12:43:51 -08001310 return true;
1311 }
1312 }
1313 return false;
1314 }
1315
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001316 void onWindowReplacementTimeout() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001317 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001318 (mChildren.get(i)).onWindowReplacementTimeout();
Robert Carra1eb4392015-12-10 12:43:51 -08001319 }
1320 }
1321
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001322 void reparent(Task task, int position) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001323 if (DEBUG_ADD_REMOVE) {
1324 Slog.i(TAG_WM, "reparent: moving app token=" + this
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001325 + " to task=" + task.mTaskId + " at " + position);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001326 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001327 if (task == null) {
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001328 throw new IllegalArgumentException("reparent: could not find task");
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001329 }
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001330 final Task currentTask = getTask();
1331 if (task == currentTask) {
Winson Chung30480042017-01-26 10:55:34 -08001332 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001333 "window token=" + this + " already child of task=" + currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001334 }
Bryce Lee6d410262017-02-28 15:30:17 -08001335
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001336 if (currentTask.mStack != task.mStack) {
Bryce Lee6d410262017-02-28 15:30:17 -08001337 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001338 "window token=" + this + " current task=" + currentTask
Bryce Lee6d410262017-02-28 15:30:17 -08001339 + " belongs to a different stack than " + task);
1340 }
1341
Winson Chung30480042017-01-26 10:55:34 -08001342 if (DEBUG_ADD_REMOVE) Slog.i(TAG, "reParentWindowToken: removing window token=" + this
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001343 + " from task=" + currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001344 final DisplayContent prevDisplayContent = getDisplayContent();
1345
Bryce Lee6d410262017-02-28 15:30:17 -08001346 mReparenting = true;
1347
Winson Chung30480042017-01-26 10:55:34 -08001348 getParent().removeChild(this);
1349 task.addChild(this, position);
1350
Bryce Lee6d410262017-02-28 15:30:17 -08001351 mReparenting = false;
1352
Winson Chung30480042017-01-26 10:55:34 -08001353 // Relayout display(s).
1354 final DisplayContent displayContent = task.getDisplayContent();
1355 displayContent.setLayoutNeeded();
1356 if (prevDisplayContent != displayContent) {
1357 onDisplayChanged(displayContent);
1358 prevDisplayContent.setLayoutNeeded();
1359 }
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001360 getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
Winson Chung30480042017-01-26 10:55:34 -08001361 }
1362
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001363 @Override
1364 void onDisplayChanged(DisplayContent dc) {
1365 DisplayContent prevDc = mDisplayContent;
1366 super.onDisplayChanged(dc);
Evan Roskyb1e75f72019-04-26 20:23:26 -07001367 if (prevDc == null || prevDc == mDisplayContent) {
Evan Rosky25b56192019-02-06 16:10:56 -08001368 return;
1369 }
Wale Ogunwaleb8e6b632019-06-28 15:19:25 +00001370
1371 if (prevDc.mOpeningApps.remove(this)) {
1372 // Transfer opening transition to new display.
1373 mDisplayContent.mOpeningApps.add(this);
1374 mDisplayContent.prepareAppTransition(prevDc.mAppTransition.getAppTransition(), true);
1375 mDisplayContent.executeAppTransition();
1376 }
1377
1378 if (prevDc.mChangingApps.remove(this)) {
Evan Rosky25b56192019-02-06 16:10:56 -08001379 // This gets called *after* the AppWindowToken has been reparented to the new display.
1380 // That reparenting resulted in this window changing modes (eg. FREEFORM -> FULLSCREEN),
1381 // so this token is now "frozen" while waiting for the animation to start on prevDc
1382 // (which will be cancelled since the window is no-longer a child). However, since this
1383 // is no longer a child of prevDc, this won't be notified of the cancelled animation,
1384 // so we need to cancel the change transition here.
1385 clearChangeLeash(getPendingTransaction(), true /* cancel */);
1386 }
Wale Ogunwaleb8e6b632019-06-28 15:19:25 +00001387 prevDc.mClosingApps.remove(this);
1388
Evan Rosky25b56192019-02-06 16:10:56 -08001389 if (prevDc.mFocusedApp == this) {
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001390 prevDc.setFocusedApp(null);
lumarkbf844642018-11-23 17:11:36 +08001391 final TaskStack stack = dc.getTopStack();
1392 if (stack != null) {
1393 final Task task = stack.getTopChild();
1394 if (task != null && task.getTopChild() == this) {
1395 dc.setFocusedApp(this);
1396 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001397 }
1398 }
Riddle Hsu192fe762019-01-15 23:41:57 +08001399
Evan Roskyb1e75f72019-04-26 20:23:26 -07001400 if (mLetterbox != null) {
Riddle Hsu192fe762019-01-15 23:41:57 +08001401 mLetterbox.onMovedToDisplay(mDisplayContent.getDisplayId());
1402 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001403 }
1404
Jorim Jaggi0429f352015-12-22 16:29:16 +01001405 /**
1406 * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds
1407 * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even
1408 * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen
1409 * with a queue.
1410 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001411 private void freezeBounds() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001412 final Task task = getTask();
1413 mFrozenBounds.offer(new Rect(task.mPreparedFrozenBounds));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001414
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001415 if (task.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001416 // We didn't call prepareFreezingBounds on the task, so use the current value.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001417 mFrozenMergedConfig.offer(new Configuration(task.getConfiguration()));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001418 } else {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001419 mFrozenMergedConfig.offer(new Configuration(task.mPreparedFrozenMergedConfig));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001420 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001421 // Calling unset() to make it equal to Configuration.EMPTY.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001422 task.mPreparedFrozenMergedConfig.unset();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001423 }
1424
1425 /**
1426 * Unfreezes the previously frozen bounds. See {@link #freezeBounds}.
1427 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001428 private void unfreezeBounds() {
Robert Carr68375192017-06-13 12:41:53 -07001429 if (mFrozenBounds.isEmpty()) {
1430 return;
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001431 }
Robert Carr68375192017-06-13 12:41:53 -07001432 mFrozenBounds.remove();
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001433 if (!mFrozenMergedConfig.isEmpty()) {
1434 mFrozenMergedConfig.remove();
1435 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001436 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001437 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001438 win.onUnfreezeBounds();
Jorim Jaggi4846ee32016-01-07 17:39:12 +01001439 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001440 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001441 }
1442
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001443 void setAppLayoutChanges(int changes, String reason) {
1444 if (!mChildren.isEmpty()) {
1445 final DisplayContent dc = getDisplayContent();
1446 dc.pendingLayoutChanges |= changes;
1447 if (DEBUG_LAYOUT_REPEATS) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001448 mWmService.mWindowPlacerLocked.debugLayoutRepeats(reason, dc.pendingLayoutChanges);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001449 }
1450 }
1451 }
1452
1453 void removeReplacedWindowIfNeeded(WindowState replacement) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001454 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001455 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001456 if (win.removeReplacedWindowIfNeeded(replacement)) {
1457 return;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001458 }
1459 }
1460 }
1461
1462 void startFreezingScreen() {
1463 if (DEBUG_ORIENTATION) logWithStack(TAG, "Set freezing of " + appToken + ": hidden="
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001464 + isHidden() + " freezing=" + mFreezingScreen + " hiddenRequested="
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001465 + hiddenRequested);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001466 if (!hiddenRequested) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001467 if (!mFreezingScreen) {
1468 mFreezingScreen = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001469 mWmService.registerAppFreezeListener(this);
1470 mWmService.mAppsFreezingScreen++;
1471 if (mWmService.mAppsFreezingScreen == 1) {
1472 mWmService.startFreezingDisplayLocked(0, 0, getDisplayContent());
1473 mWmService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
1474 mWmService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001475 }
1476 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001477 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001478 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001479 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001480 w.onStartFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001481 }
1482 }
1483 }
1484
1485 void stopFreezingScreen(boolean unfreezeSurfaceNow, boolean force) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001486 if (!mFreezingScreen) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001487 return;
1488 }
1489 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + this + " force=" + force);
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001490 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001491 boolean unfrozeWindows = false;
1492 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001493 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001494 unfrozeWindows |= w.onStopFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001495 }
1496 if (force || unfrozeWindows) {
1497 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "No longer freezing: " + this);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001498 mFreezingScreen = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001499 mWmService.unregisterAppFreezeListener(this);
1500 mWmService.mAppsFreezingScreen--;
1501 mWmService.mLastFinishedFreezeSource = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001502 }
1503 if (unfreezeSurfaceNow) {
1504 if (unfrozeWindows) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001505 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001506 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001507 mWmService.stopFreezingDisplayLocked();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001508 }
1509 }
1510
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001511 @Override
1512 public void onAppFreezeTimeout() {
1513 Slog.w(TAG_WM, "Force clearing freeze: " + this);
1514 stopFreezingScreen(true, true);
1515 }
1516
Jorim Jaggi60f9c972018-02-01 19:21:07 +01001517 /**
1518 * Tries to transfer the starting window from a token that's above ourselves in the task but
1519 * not visible anymore. This is a common scenario apps use: Trampoline activity T start main
1520 * activity M in the same task. Now, when reopening the task, T starts on top of M but then
1521 * immediately finishes after, so we have to transfer T to M.
1522 */
1523 void transferStartingWindowFromHiddenAboveTokenIfNeeded() {
1524 final Task task = getTask();
1525 for (int i = task.mChildren.size() - 1; i >= 0; i--) {
1526 final AppWindowToken fromToken = task.mChildren.get(i);
1527 if (fromToken == this) {
1528 return;
1529 }
1530 if (fromToken.hiddenRequested && transferStartingWindow(fromToken.token)) {
1531 return;
1532 }
1533 }
1534 }
1535
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001536 boolean transferStartingWindow(IBinder transferFrom) {
Wale Ogunwale02319a62016-09-26 15:21:22 -07001537 final AppWindowToken fromToken = getDisplayContent().getAppWindowToken(transferFrom);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001538 if (fromToken == null) {
1539 return false;
1540 }
1541
1542 final WindowState tStartingWindow = fromToken.startingWindow;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08001543 if (tStartingWindow != null && fromToken.startingSurface != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001544 // In this case, the starting icon has already been displayed, so start
1545 // letting windows get shown immediately without any more transitions.
lumark588a3e82018-07-20 18:53:54 +08001546 getDisplayContent().mSkipAppTransitionAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001547
1548 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Moving existing starting " + tStartingWindow
1549 + " from " + fromToken + " to " + this);
1550
1551 final long origId = Binder.clearCallingIdentity();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001552 try {
1553 // Transfer the starting window over to the new token.
chaviwa8f07a72019-05-01 16:25:39 -07001554 mStartingData = fromToken.mStartingData;
Peter Visontay3556a3b2017-11-01 17:23:17 +00001555 startingSurface = fromToken.startingSurface;
1556 startingDisplayed = fromToken.startingDisplayed;
1557 fromToken.startingDisplayed = false;
1558 startingWindow = tStartingWindow;
1559 reportedVisible = fromToken.reportedVisible;
chaviwa8f07a72019-05-01 16:25:39 -07001560 fromToken.mStartingData = null;
Peter Visontay3556a3b2017-11-01 17:23:17 +00001561 fromToken.startingSurface = null;
1562 fromToken.startingWindow = null;
1563 fromToken.startingMoved = true;
1564 tStartingWindow.mToken = this;
1565 tStartingWindow.mAppToken = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001566
Peter Visontay3556a3b2017-11-01 17:23:17 +00001567 if (DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
1568 "Removing starting " + tStartingWindow + " from " + fromToken);
1569 fromToken.removeChild(tStartingWindow);
1570 fromToken.postWindowRemoveStartingWindowCleanup(tStartingWindow);
1571 fromToken.mHiddenSetFromTransferredStartingWindow = false;
1572 addWindow(tStartingWindow);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001573
Peter Visontay3556a3b2017-11-01 17:23:17 +00001574 // Propagate other interesting state between the tokens. If the old token is displayed,
1575 // we should immediately force the new one to be displayed. If it is animating, we need
1576 // to move that animation to the new one.
1577 if (fromToken.allDrawn) {
1578 allDrawn = true;
1579 deferClearAllDrawn = fromToken.deferClearAllDrawn;
1580 }
1581 if (fromToken.firstWindowDrawn) {
1582 firstWindowDrawn = true;
1583 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001584 if (!fromToken.isHidden()) {
1585 setHidden(false);
Peter Visontay3556a3b2017-11-01 17:23:17 +00001586 hiddenRequested = false;
1587 mHiddenSetFromTransferredStartingWindow = true;
1588 }
1589 setClientHidden(fromToken.mClientHidden);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001590
Jorim Jaggi980c9de2017-11-17 01:41:37 +01001591 transferAnimation(fromToken);
1592
1593 // When transferring an animation, we no longer need to apply an animation to the
Tiger Huangc9d0d002019-05-29 22:55:29 +08001594 // the token we transfer the animation over. Thus, set this flag to indicate we've
1595 // transferred the animation.
1596 mUseTransferredAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001597
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001598 mWmService.updateFocusedWindowLocked(
Peter Visontay3556a3b2017-11-01 17:23:17 +00001599 UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/);
1600 getDisplayContent().setLayoutNeeded();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001601 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001602 } finally {
1603 Binder.restoreCallingIdentity(origId);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001604 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001605 return true;
chaviwa8f07a72019-05-01 16:25:39 -07001606 } else if (fromToken.mStartingData != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001607 // The previous app was getting ready to show a
1608 // starting window, but hasn't yet done so. Steal it!
1609 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
1610 "Moving pending starting from " + fromToken + " to " + this);
chaviwa8f07a72019-05-01 16:25:39 -07001611 mStartingData = fromToken.mStartingData;
1612 fromToken.mStartingData = null;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001613 fromToken.startingMoved = true;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001614 scheduleAddStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001615 return true;
1616 }
1617
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001618 // TODO: Transfer thumbnail
1619
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001620 return false;
1621 }
1622
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001623 boolean isLastWindow(WindowState win) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001624 return mChildren.size() == 1 && mChildren.get(0) == win;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001625 }
1626
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001627 @Override
1628 void onAppTransitionDone() {
1629 sendingToBottom = false;
1630 }
1631
Wale Ogunwale51362492016-09-08 17:49:17 -07001632 /**
1633 * We override because this class doesn't want its children affecting its reported orientation
1634 * in anyway.
1635 */
1636 @Override
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001637 int getOrientation(int candidate) {
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001638 if (candidate == SCREEN_ORIENTATION_BEHIND) {
1639 // Allow app to specify orientation regardless of its visibility state if the current
1640 // candidate want us to use orientation behind. I.e. the visible app on-top of this one
1641 // wants us to use the orientation of the app behind it.
1642 return mOrientation;
1643 }
1644
Bryce Lee61fbcbc2017-03-10 14:14:03 -08001645 // The {@link AppWindowToken} should only specify an orientation when it is not closing or
1646 // going to the bottom. Allowing closing {@link AppWindowToken} to participate can lead to
1647 // an Activity in another task being started in the wrong orientation during the transition.
lumark588a3e82018-07-20 18:53:54 +08001648 if (!(sendingToBottom || getDisplayContent().mClosingApps.contains(this))
1649 && (isVisible() || getDisplayContent().mOpeningApps.contains(this))) {
Bryce Leea163b762017-01-24 11:05:01 -08001650 return mOrientation;
Wale Ogunwale51362492016-09-08 17:49:17 -07001651 }
Bryce Leea163b762017-01-24 11:05:01 -08001652
1653 return SCREEN_ORIENTATION_UNSET;
Wale Ogunwale51362492016-09-08 17:49:17 -07001654 }
1655
Wale Ogunwaleb198b742016-12-01 08:44:09 -08001656 /** Returns the app's preferred orientation regardless of its currently visibility state. */
1657 int getOrientationIgnoreVisibility() {
1658 return mOrientation;
1659 }
1660
Riddle Hsub398da32019-01-21 21:48:16 +08001661 /** @return {@code true} if the compatibility bounds is taking effect. */
1662 boolean inSizeCompatMode() {
1663 return mSizeCompatBounds != null;
1664 }
1665
1666 @Override
1667 float getSizeCompatScale() {
1668 return inSizeCompatMode() ? mSizeCompatScale : super.getSizeCompatScale();
1669 }
1670
1671 /**
1672 * @return Non-empty bounds if the activity has override bounds.
1673 * @see ActivityRecord#resolveOverrideConfiguration(Configuration)
1674 */
1675 Rect getResolvedOverrideBounds() {
1676 // Get bounds from resolved override configuration because it is computed with orientation.
1677 return getResolvedOverrideConfiguration().windowConfiguration.getBounds();
1678 }
1679
Craig Mautnerdbb79912012-03-01 18:59:14 -08001680 @Override
Winson Chunge55c0192017-08-24 14:50:48 -07001681 public void onConfigurationChanged(Configuration newParentConfig) {
1682 final int prevWinMode = getWindowingMode();
Evan Rosky2289ba12018-11-19 18:28:18 -08001683 mTmpPrevBounds.set(getBounds());
Winson Chunge55c0192017-08-24 14:50:48 -07001684 super.onConfigurationChanged(newParentConfig);
Riddle Hsub398da32019-01-21 21:48:16 +08001685
1686 final Task task = getTask();
1687 final Rect overrideBounds = getResolvedOverrideBounds();
1688 if (task != null && !overrideBounds.isEmpty()
1689 // If the changes come from change-listener, the incoming parent configuration is
1690 // still the old one. Make sure their orientations are the same to reduce computing
1691 // the compatibility bounds for the intermediate state.
Riddle Hsu04164182019-03-07 18:03:27 +08001692 && (task.mTaskRecord == null || task.mTaskRecord
1693 .getConfiguration().orientation == newParentConfig.orientation)) {
Riddle Hsub398da32019-01-21 21:48:16 +08001694 final Rect taskBounds = task.getBounds();
1695 // Since we only center the activity horizontally, if only the fixed height is smaller
1696 // than its container, the override bounds don't need to take effect.
1697 if ((overrideBounds.width() != taskBounds.width()
1698 || overrideBounds.height() > taskBounds.height())) {
1699 calculateCompatBoundsTransformation(newParentConfig);
1700 updateSurfacePosition();
1701 } else if (mSizeCompatBounds != null) {
1702 mSizeCompatBounds = null;
1703 mSizeCompatScale = 1f;
1704 updateSurfacePosition();
1705 }
1706 }
1707
Winson Chunge55c0192017-08-24 14:50:48 -07001708 final int winMode = getWindowingMode();
1709
1710 if (prevWinMode == winMode) {
1711 return;
1712 }
1713
Hongwei Wang43a752b2019-09-17 20:20:30 +00001714 if (prevWinMode == WINDOWING_MODE_PINNED && winMode != WINDOWING_MODE_UNDEFINED
Winson Chung82267ce2018-04-06 16:38:26 -07001715 && !isHidden()) {
Winson Chunge55c0192017-08-24 14:50:48 -07001716 // Leaving PiP to fullscreen, save the snap fraction based on the pre-animation bounds
1717 // for the next re-entry into PiP (assuming the activity is not hidden or destroyed)
1718 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
1719 if (pinnedStack != null) {
Winson Chung8efa1652018-06-06 09:34:23 -07001720 final Rect stackBounds;
1721 if (pinnedStack.lastAnimatingBoundsWasToFullscreen()) {
1722 // We are animating the bounds, use the pre-animation bounds to save the snap
1723 // fraction
1724 stackBounds = pinnedStack.mPreAnimationBounds;
1725 } else {
1726 // We skip the animation if the fullscreen configuration is not compatible, so
1727 // use the current bounds to calculate the saved snap fraction instead
1728 // (see PinnedActivityStack.skipResizeAnimation())
1729 stackBounds = mTmpRect;
1730 pinnedStack.getBounds(stackBounds);
1731 }
Hongwei Wang43a752b2019-09-17 20:20:30 +00001732 mDisplayContent.mPinnedStackControllerLocked.saveReentrySnapFraction(
1733 mActivityComponent, stackBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001734 }
Evan Rosky2289ba12018-11-19 18:28:18 -08001735 } else if (shouldStartChangeTransition(prevWinMode, winMode)) {
1736 initializeChangeTransition(mTmpPrevBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001737 }
1738 }
1739
Evan Rosky2289ba12018-11-19 18:28:18 -08001740 private boolean shouldStartChangeTransition(int prevWinMode, int newWinMode) {
Evan Rosky25b56192019-02-06 16:10:56 -08001741 if (mWmService.mDisableTransitionAnimation
1742 || !isVisible()
1743 || getDisplayContent().mAppTransition.isTransitionSet()
1744 || getSurfaceControl() == null) {
Evan Rosky2289ba12018-11-19 18:28:18 -08001745 return false;
1746 }
1747 // Only do an animation into and out-of freeform mode for now. Other mode
1748 // transition animations are currently handled by system-ui.
1749 return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
1750 }
1751
1752 /**
1753 * Initializes a change transition. Because the app is visible already, there is a small period
1754 * of time where the user can see the app content/window update before the transition starts.
1755 * To prevent this, we immediately take a snapshot and place the app/snapshot into a leash which
1756 * "freezes" the location/crop until the transition starts.
1757 * <p>
1758 * Here's a walk-through of the process:
1759 * 1. Create a temporary leash ("interim-change-leash") and reparent the app to it.
1760 * 2. Set the temporary leash's position/crop to the current state.
1761 * 3. Create a snapshot and place that at the top of the leash to cover up content changes.
1762 * 4. Once the transition is ready, it will reparent the app to the animation leash.
1763 * 5. Detach the interim-change-leash.
1764 */
1765 private void initializeChangeTransition(Rect startBounds) {
1766 mDisplayContent.prepareAppTransition(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
1767 false /* alwaysKeepCurrent */, 0, false /* forceOverride */);
1768 mDisplayContent.mChangingApps.add(this);
1769 mTransitStartRect.set(startBounds);
1770
1771 final SurfaceControl.Builder builder = makeAnimationLeash()
1772 .setParent(getAnimationLeashParent())
1773 .setName(getSurfaceControl() + " - interim-change-leash");
1774 mTransitChangeLeash = builder.build();
1775 Transaction t = getPendingTransaction();
1776 t.setWindowCrop(mTransitChangeLeash, startBounds.width(), startBounds.height());
1777 t.setPosition(mTransitChangeLeash, startBounds.left, startBounds.top);
1778 t.show(mTransitChangeLeash);
1779 t.reparent(getSurfaceControl(), mTransitChangeLeash);
1780 onAnimationLeashCreated(t, mTransitChangeLeash);
1781
Evan Rosky966759f2019-01-15 10:33:58 -08001782 // Skip creating snapshot if this transition is controlled by a remote animator which
1783 // doesn't need it.
1784 ArraySet<Integer> activityTypes = new ArraySet<>();
1785 activityTypes.add(getActivityType());
1786 RemoteAnimationAdapter adapter =
1787 mDisplayContent.mAppTransitionController.getRemoteAnimationOverride(
1788 this, TRANSIT_TASK_CHANGE_WINDOWING_MODE, activityTypes);
1789 if (adapter != null && !adapter.getChangeNeedsSnapshot()) {
1790 return;
1791 }
1792
Evan Rosky08e20932019-05-14 10:54:07 -07001793 Task task = getTask();
1794 if (mThumbnail == null && task != null && !hasCommittedReparentToAnimationLeash()) {
1795 SurfaceControl.ScreenshotGraphicBuffer snapshot =
1796 mWmService.mTaskSnapshotController.createTaskSnapshot(
1797 task, 1 /* scaleFraction */);
Yunfan Chendcb1fcf2019-02-07 19:08:41 +09001798 if (snapshot != null) {
Vishnu Nair33197392019-08-30 10:29:37 -07001799 mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory, t, this,
1800 snapshot.getGraphicBuffer(), true /* relative */);
Yunfan Chendcb1fcf2019-02-07 19:08:41 +09001801 }
Evan Rosky2289ba12018-11-19 18:28:18 -08001802 }
1803 }
1804
1805 boolean isInChangeTransition() {
Evan Roskyec9488c2019-03-01 19:32:12 -08001806 return mTransitChangeLeash != null || AppTransition.isChangeTransit(mTransit);
Evan Rosky2289ba12018-11-19 18:28:18 -08001807 }
1808
Evan Rosky966759f2019-01-15 10:33:58 -08001809 @VisibleForTesting
1810 AppWindowThumbnail getThumbnail() {
1811 return mThumbnail;
1812 }
1813
Riddle Hsub398da32019-01-21 21:48:16 +08001814 /**
1815 * Calculates the scale and offset to horizontal center the size compatibility bounds into the
1816 * region which is available to application.
1817 */
1818 private void calculateCompatBoundsTransformation(Configuration newParentConfig) {
1819 final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds();
Riddle Hsu74826262019-04-17 14:57:42 +08001820 final Rect parentBounds = newParentConfig.windowConfiguration.getBounds();
1821 final Rect viewportBounds = parentAppBounds != null ? parentAppBounds : parentBounds;
Riddle Hsu04164182019-03-07 18:03:27 +08001822 final Rect appBounds = getWindowConfiguration().getAppBounds();
1823 final Rect contentBounds = appBounds != null ? appBounds : getResolvedOverrideBounds();
Riddle Hsub398da32019-01-21 21:48:16 +08001824 final float contentW = contentBounds.width();
1825 final float contentH = contentBounds.height();
1826 final float viewportW = viewportBounds.width();
1827 final float viewportH = viewportBounds.height();
1828 // Only allow to scale down.
1829 mSizeCompatScale = (contentW <= viewportW && contentH <= viewportH)
1830 ? 1 : Math.min(viewportW / contentW, viewportH / contentH);
1831 final int offsetX = (int) ((viewportW - contentW * mSizeCompatScale + 1) * 0.5f)
1832 + viewportBounds.left;
1833
1834 if (mSizeCompatBounds == null) {
1835 mSizeCompatBounds = new Rect();
1836 }
1837 mSizeCompatBounds.set(contentBounds);
1838 mSizeCompatBounds.offsetTo(0, 0);
1839 mSizeCompatBounds.scale(mSizeCompatScale);
Riddle Hsu74826262019-04-17 14:57:42 +08001840 // Ensure to align the top with the parent.
1841 mSizeCompatBounds.top = parentBounds.top;
Riddle Hsu04164182019-03-07 18:03:27 +08001842 // The decor inset is included in height.
1843 mSizeCompatBounds.bottom += viewportBounds.top;
Riddle Hsub398da32019-01-21 21:48:16 +08001844 mSizeCompatBounds.left += offsetX;
1845 mSizeCompatBounds.right += offsetX;
1846 }
1847
1848 @Override
1849 public Rect getBounds() {
1850 if (mSizeCompatBounds != null) {
1851 return mSizeCompatBounds;
1852 }
1853 return super.getBounds();
1854 }
1855
1856 @Override
1857 public boolean matchParentBounds() {
1858 if (super.matchParentBounds()) {
1859 return true;
1860 }
1861 // An activity in size compatibility mode may have override bounds which equals to its
1862 // parent bounds, so the exact bounds should also be checked.
1863 final WindowContainer parent = getParent();
1864 return parent == null || parent.getBounds().equals(getResolvedOverrideBounds());
1865 }
1866
Winson Chunge55c0192017-08-24 14:50:48 -07001867 @Override
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001868 void checkAppWindowsReadyToShow() {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001869 if (allDrawn == mLastAllDrawn) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001870 return;
1871 }
1872
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001873 mLastAllDrawn = allDrawn;
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001874 if (!allDrawn) {
1875 return;
1876 }
1877
1878 // The token has now changed state to having all windows shown... what to do, what to do?
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001879 if (mFreezingScreen) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001880 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001881 stopFreezingScreen(false, true);
1882 if (DEBUG_ORIENTATION) Slog.i(TAG,
1883 "Setting mOrientationChangeComplete=true because wtoken " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001884 + " numInteresting=" + mNumInterestingWindows + " numDrawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001885 // This will set mOrientationChangeComplete and cause a pass through layout.
1886 setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001887 "checkAppWindowsReadyToShow: freezingScreen");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001888 } else {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001889 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001890
1891 // We can now show all of the drawn windows!
lumark588a3e82018-07-20 18:53:54 +08001892 if (!getDisplayContent().mOpeningApps.contains(this) && canShowWindows()) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001893 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001894 }
1895 }
1896 }
1897
Matthew Ng5d23afa2017-06-21 16:16:24 -07001898 /**
Bryce Leed390deb2017-06-22 13:14:28 -07001899 * Returns whether the drawn window states of this {@link AppWindowToken} has considered every
1900 * child {@link WindowState}. A child is considered if it has been passed into
1901 * {@link #updateDrawnWindowStates(WindowState)} after being added. This is used to determine
1902 * whether states, such as {@code allDrawn}, can be set, which relies on state variables such as
1903 * {@code mNumInterestingWindows}, which depend on all {@link WindowState}s being considered.
1904 *
1905 * @return {@code true} If all children have been considered, {@code false}.
1906 */
1907 private boolean allDrawnStatesConsidered() {
Bryce Lee6311c4b2017-07-06 14:09:29 -07001908 for (int i = mChildren.size() - 1; i >= 0; --i) {
1909 final WindowState child = mChildren.get(i);
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001910 if (child.mightAffectAllDrawn() && !child.getDrawnStateEvaluated()) {
Bryce Leed390deb2017-06-22 13:14:28 -07001911 return false;
1912 }
1913 }
1914 return true;
1915 }
1916
1917 /**
Matthew Ng5d23afa2017-06-21 16:16:24 -07001918 * Determines if the token has finished drawing. This should only be called from
1919 * {@link DisplayContent#applySurfaceChangesTransaction}
1920 */
Matthew Ng498c71d2017-04-18 13:55:45 -07001921 void updateAllDrawn() {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001922 if (!allDrawn) {
Matthew Ng498c71d2017-04-18 13:55:45 -07001923 // Number of drawn windows can be less when a window is being relaunched, wait for
Bryce Leed390deb2017-06-22 13:14:28 -07001924 // all windows to be launched and drawn for this token be considered all drawn.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001925 final int numInteresting = mNumInterestingWindows;
Bryce Leed390deb2017-06-22 13:14:28 -07001926
1927 // We must make sure that all present children have been considered (determined by
1928 // {@link #allDrawnStatesConsidered}) before evaluating whether everything has been
1929 // drawn.
1930 if (numInteresting > 0 && allDrawnStatesConsidered()
1931 && mNumDrawnWindows >= numInteresting && !isRelaunching()) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001932 if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawn: " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001933 + " interesting=" + numInteresting + " drawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001934 allDrawn = true;
1935 // Force an additional layout pass where
1936 // WindowStateAnimator#commitFinishDrawingLocked() will call performShowLocked().
Matthew Ng498c71d2017-04-18 13:55:45 -07001937 if (mDisplayContent != null) {
1938 mDisplayContent.setLayoutNeeded();
1939 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001940 mWmService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
Robert Carrecc06b32017-04-18 14:25:10 -07001941
Winson Chunge7ba6862017-05-24 12:13:33 -07001942 // Notify the pinned stack upon all windows drawn. If there was an animation in
1943 // progress then this signal will resume that animation.
Wale Ogunwale61911492017-10-11 08:50:50 -07001944 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
Winson Chunge7ba6862017-05-24 12:13:33 -07001945 if (pinnedStack != null) {
1946 pinnedStack.onAllWindowsDrawn();
Robert Carrecc06b32017-04-18 14:25:10 -07001947 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001948 }
1949 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001950 }
1951
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001952 boolean keyDispatchingTimedOut(String reason, int windowPid) {
1953 return mActivityRecord != null && mActivityRecord.keyDispatchingTimedOut(reason, windowPid);
1954 }
1955
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001956 /**
1957 * Updated this app token tracking states for interesting and drawn windows based on the window.
1958 *
1959 * @return Returns true if the input window is considered interesting and drawn while all the
1960 * windows in this app token where not considered drawn as of the last pass.
1961 */
1962 boolean updateDrawnWindowStates(WindowState w) {
Bryce Leed390deb2017-06-22 13:14:28 -07001963 w.setDrawnStateEvaluated(true /*evaluated*/);
1964
Jorim Jaggie4b0f282017-05-17 15:10:29 +02001965 if (DEBUG_STARTING_WINDOW_VERBOSE && w == startingWindow) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001966 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + w.isOnScreen()
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001967 + " allDrawn=" + allDrawn + " freezingScreen=" + mFreezingScreen);
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001968 }
1969
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001970 if (allDrawn && !mFreezingScreen) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001971 return false;
1972 }
1973
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001974 if (mLastTransactionSequence != mWmService.mTransactionSequence) {
1975 mLastTransactionSequence = mWmService.mTransactionSequence;
Matthew Ng53e66b22018-01-12 17:13:13 -08001976 mNumDrawnWindows = 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001977 startingDisplayed = false;
Matthew Ng53e66b22018-01-12 17:13:13 -08001978
1979 // There is the main base application window, even if it is exiting, wait for it
1980 mNumInterestingWindows = findMainWindow(false /* includeStartingApp */) != null ? 1 : 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001981 }
1982
1983 final WindowStateAnimator winAnimator = w.mWinAnimator;
1984
1985 boolean isInterestingAndDrawn = false;
1986
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001987 if (!allDrawn && w.mightAffectAllDrawn()) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001988 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
1989 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001990 + ", isAnimationSet=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001991 if (!w.isDrawnLw()) {
1992 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController
chaviw15ad49f2019-04-24 15:05:39 -07001993 + " pv=" + w.isVisibleByPolicy()
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001994 + " mDrawState=" + winAnimator.drawStateToString()
1995 + " ph=" + w.isParentWindowHidden() + " th=" + hiddenRequested
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001996 + " a=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001997 }
1998 }
1999
2000 if (w != startingWindow) {
2001 if (w.isInteresting()) {
Matthew Ng53e66b22018-01-12 17:13:13 -08002002 // Add non-main window as interesting since the main app has already been added
2003 if (findMainWindow(false /* includeStartingApp */) != w) {
2004 mNumInterestingWindows++;
2005 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002006 if (w.isDrawnLw()) {
2007 mNumDrawnWindows++;
2008
2009 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, "tokenMayBeDrawn: "
2010 + this + " w=" + w + " numInteresting=" + mNumInterestingWindows
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002011 + " freezingScreen=" + mFreezingScreen
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002012 + " mAppFreezing=" + w.mAppFreezing);
2013
2014 isInterestingAndDrawn = true;
2015 }
2016 }
2017 } else if (w.isDrawnLw()) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002018 if (mActivityRecord != null) {
2019 mActivityRecord.onStartingWindowDrawn(SystemClock.uptimeMillis());
Jorim Jaggi3878ca32017-02-02 17:13:05 -08002020 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002021 startingDisplayed = true;
2022 }
2023 }
2024
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002025 return isInterestingAndDrawn;
2026 }
2027
Adrian Roos23df3a32018-03-15 15:41:13 +01002028 void layoutLetterbox(WindowState winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002029 final WindowState w = findMainWindow();
Adrian Roosf93b6d22018-03-21 13:48:26 +01002030 if (w == null || winHint != null && w != winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002031 return;
2032 }
Jorim Jaggia32da382018-03-28 18:01:22 +02002033 final boolean surfaceReady = w.isDrawnLw() // Regular case
Adrian Roosf93b6d22018-03-21 13:48:26 +01002034 || w.mWinAnimator.mSurfaceDestroyDeferred // The preserved surface is still ready.
2035 || w.isDragResizeChanged(); // Waiting for relayoutWindow to call preserveSurface.
Jorim Jaggi4981f152019-03-26 18:58:45 +01002036 final boolean needsLetterbox = surfaceReady && w.isLetterboxedAppWindow() && fillsParent();
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002037 if (needsLetterbox) {
2038 if (mLetterbox == null) {
Vishnu Nair33197392019-08-30 10:29:37 -07002039 mLetterbox = new Letterbox(() -> makeChildSurface(null),
2040 mWmService.mTransactionFactory);
Riddle Hsu192fe762019-01-15 23:41:57 +08002041 mLetterbox.attachInput(w);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002042 }
Adrian Roos7af9d972018-11-30 15:26:27 +01002043 getPosition(mTmpPoint);
Evan Rosky67c15642019-04-24 13:17:28 -07002044 // Get the bounds of the "space-to-fill". In multi-window mode, the task-level
2045 // represents this. In fullscreen-mode, the stack does (since the orientation letterbox
2046 // is also applied to the task).
2047 Rect spaceToFill = (inMultiWindowMode() || getStack() == null)
2048 ? getTask().getDisplayedBounds() : getStack().getDisplayedBounds();
Evan Rosky4fb1e912019-03-06 13:54:43 -08002049 mLetterbox.layout(spaceToFill, w.getFrameLw(), mTmpPoint);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002050 } else if (mLetterbox != null) {
Adrian Roos23df3a32018-03-15 15:41:13 +01002051 mLetterbox.hide();
2052 }
2053 }
2054
2055 void updateLetterboxSurface(WindowState winHint) {
2056 final WindowState w = findMainWindow();
2057 if (w != winHint && winHint != null && w != null) {
2058 return;
2059 }
2060 layoutLetterbox(winHint);
2061 if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) {
Tiger Huanged6794e2019-05-07 20:07:59 +08002062 mLetterbox.applySurfaceChanges(getPendingTransaction());
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002063 }
2064 }
2065
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07002066 @Override
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002067 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002068 // For legacy reasons we process the TaskStack.mExitingAppTokens first in DisplayContent
2069 // before the non-exiting app tokens. So, we skip the exiting app tokens here.
2070 // TODO: Investigate if we need to continue to do this or if we can just process them
2071 // in-order.
2072 if (mIsExiting && !waitingForReplacement()) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002073 return false;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002074 }
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002075 return forAllWindowsUnchecked(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002076 }
2077
lumark588a3e82018-07-20 18:53:54 +08002078 @Override
2079 void forAllAppWindows(Consumer<AppWindowToken> callback) {
2080 callback.accept(this);
2081 }
2082
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002083 boolean forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback,
2084 boolean traverseTopToBottom) {
2085 return super.forAllWindows(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002086 }
2087
2088 @Override
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002089 AppWindowToken asAppWindowToken() {
2090 // I am an app window token!
2091 return this;
2092 }
2093
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002094 boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
2095 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
2096 IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
2097 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
2098 // If the display is frozen, we won't do anything until the actual window is
2099 // displayed so there is no reason to put in the starting window.
2100 if (!okToDisplay()) {
2101 return false;
2102 }
2103
chaviwa8f07a72019-05-01 16:25:39 -07002104 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002105 return false;
2106 }
2107
2108 final WindowState mainWin = findMainWindow();
2109 if (mainWin != null && mainWin.mWinAnimator.getShown()) {
2110 // App already has a visible window...why would you want a starting window?
2111 return false;
2112 }
2113
2114 final ActivityManager.TaskSnapshot snapshot =
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002115 mWmService.mTaskSnapshotController.getSnapshot(
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002116 getTask().mTaskId, getTask().mUserId,
2117 false /* restoreFromDisk */, false /* reducedResolution */);
2118 final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
2119 allowTaskSnapshot, activityCreated, fromRecents, snapshot);
2120
2121 if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
2122 return createSnapshot(snapshot);
2123 }
2124
2125 // If this is a translucent window, then don't show a starting window -- the current
2126 // effect (a full-screen opaque starting window that fades away to the real contents
2127 // when it is ready) does not work for this.
2128 if (DEBUG_STARTING_WINDOW) {
2129 Slog.v(TAG, "Checking theme of starting window: 0x" + Integer.toHexString(theme));
2130 }
2131 if (theme != 0) {
2132 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
2133 com.android.internal.R.styleable.Window,
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002134 mWmService.mCurrentUserId);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002135 if (ent == null) {
2136 // Whoops! App doesn't exist. Um. Okay. We'll just pretend like we didn't
2137 // see that.
2138 return false;
2139 }
2140 final boolean windowIsTranslucent = ent.array.getBoolean(
2141 com.android.internal.R.styleable.Window_windowIsTranslucent, false);
2142 final boolean windowIsFloating = ent.array.getBoolean(
2143 com.android.internal.R.styleable.Window_windowIsFloating, false);
2144 final boolean windowShowWallpaper = ent.array.getBoolean(
2145 com.android.internal.R.styleable.Window_windowShowWallpaper, false);
2146 final boolean windowDisableStarting = ent.array.getBoolean(
2147 com.android.internal.R.styleable.Window_windowDisablePreview, false);
2148 if (DEBUG_STARTING_WINDOW) {
2149 Slog.v(TAG, "Translucent=" + windowIsTranslucent
2150 + " Floating=" + windowIsFloating
2151 + " ShowWallpaper=" + windowShowWallpaper);
2152 }
2153 if (windowIsTranslucent) {
2154 return false;
2155 }
2156 if (windowIsFloating || windowDisableStarting) {
2157 return false;
2158 }
2159 if (windowShowWallpaper) {
2160 if (getDisplayContent().mWallpaperController
2161 .getWallpaperTarget() == null) {
2162 // If this theme is requesting a wallpaper, and the wallpaper
2163 // is not currently visible, then this effectively serves as
2164 // an opaque window and our starting window transition animation
2165 // can still work. We just need to make sure the starting window
2166 // is also showing the wallpaper.
2167 windowFlags |= FLAG_SHOW_WALLPAPER;
2168 } else {
2169 return false;
2170 }
2171 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002172 }
Yunfan Chen8a8c0ed2018-12-18 16:46:32 -08002173
2174 if (transferStartingWindow(transferFrom)) {
2175 return true;
2176 }
2177
2178 // There is no existing starting window, and we don't want to create a splash screen, so
2179 // that's it!
2180 if (type != STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
2181 return false;
2182 }
2183
2184 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SplashScreenStartingData");
chaviwa8f07a72019-05-01 16:25:39 -07002185 mStartingData = new SplashScreenStartingData(mWmService, pkg,
Yunfan Chen8a8c0ed2018-12-18 16:46:32 -08002186 theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
2187 getMergedOverrideConfiguration());
2188 scheduleAddStartingWindow();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002189 return true;
2190 }
2191
2192
2193 private boolean createSnapshot(ActivityManager.TaskSnapshot snapshot) {
2194 if (snapshot == null) {
2195 return false;
2196 }
2197
2198 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SnapshotStartingData");
chaviwa8f07a72019-05-01 16:25:39 -07002199 mStartingData = new SnapshotStartingData(mWmService, snapshot);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002200 scheduleAddStartingWindow();
2201 return true;
2202 }
2203
2204 void scheduleAddStartingWindow() {
2205 // Note: we really want to do sendMessageAtFrontOfQueue() because we
2206 // want to process the message ASAP, before any other queued
2207 // messages.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002208 if (!mWmService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002209 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING");
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002210 mWmService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002211 }
2212 }
2213
2214 private final Runnable mAddStartingWindow = new Runnable() {
2215
2216 @Override
2217 public void run() {
chaviwa8f07a72019-05-01 16:25:39 -07002218 // Can be accessed without holding the global lock
2219 final StartingData startingData;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002220 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002221 // There can only be one adding request, silly caller!
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002222 mWmService.mAnimationHandler.removeCallbacks(this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002223
chaviwa8f07a72019-05-01 16:25:39 -07002224 if (mStartingData == null) {
2225 // Animation has been canceled... do nothing.
2226 if (DEBUG_STARTING_WINDOW) {
2227 Slog.v(TAG, "startingData was nulled out before handling"
2228 + " mAddStartingWindow: " + AppWindowToken.this);
2229 }
2230 return;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002231 }
chaviwa8f07a72019-05-01 16:25:39 -07002232 startingData = mStartingData;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002233 }
2234
2235 if (DEBUG_STARTING_WINDOW) {
2236 Slog.v(TAG, "Add starting " + this + ": startingData=" + startingData);
2237 }
2238
2239 WindowManagerPolicy.StartingSurface surface = null;
2240 try {
2241 surface = startingData.createStartingSurface(AppWindowToken.this);
2242 } catch (Exception e) {
2243 Slog.w(TAG, "Exception when adding starting window", e);
2244 }
2245 if (surface != null) {
2246 boolean abort = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002247 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002248 // If the window was successfully added, then
2249 // we need to remove it.
chaviwa8f07a72019-05-01 16:25:39 -07002250 if (removed || mStartingData == null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002251 if (DEBUG_STARTING_WINDOW) {
2252 Slog.v(TAG, "Aborted starting " + AppWindowToken.this
chaviwa8f07a72019-05-01 16:25:39 -07002253 + ": removed=" + removed + " startingData=" + mStartingData);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002254 }
2255 startingWindow = null;
chaviwa8f07a72019-05-01 16:25:39 -07002256 mStartingData = null;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002257 abort = true;
2258 } else {
2259 startingSurface = surface;
2260 }
2261 if (DEBUG_STARTING_WINDOW && !abort) {
chaviwa8f07a72019-05-01 16:25:39 -07002262 Slog.v(TAG,
2263 "Added starting " + AppWindowToken.this + ": startingWindow="
2264 + startingWindow + " startingView=" + startingSurface);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002265 }
2266 }
2267 if (abort) {
2268 surface.remove();
2269 }
2270 } else if (DEBUG_STARTING_WINDOW) {
2271 Slog.v(TAG, "Surface returned was null: " + AppWindowToken.this);
2272 }
2273 }
2274 };
2275
2276 private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
2277 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents,
2278 ActivityManager.TaskSnapshot snapshot) {
2279 if (getDisplayContent().mAppTransition.getAppTransition()
2280 == TRANSIT_DOCK_TASK_FROM_RECENTS) {
2281 // TODO(b/34099271): Remove this statement to add back the starting window and figure
2282 // out why it causes flickering, the starting window appears over the thumbnail while
2283 // the docked from recents transition occurs
2284 return STARTING_WINDOW_TYPE_NONE;
2285 } else if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
2286 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2287 } else if (taskSwitch && allowTaskSnapshot) {
Kevin716a9db2018-12-18 16:53:39 -08002288 if (mWmService.mLowRamTaskSnapshotsAndRecents) {
Kevin58b47f12018-12-17 14:09:01 -08002289 // For low RAM devices, we use the splash screen starting window instead of the
2290 // task snapshot starting window.
2291 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2292 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002293 return snapshot == null ? STARTING_WINDOW_TYPE_NONE
2294 : snapshotOrientationSameAsTask(snapshot) || fromRecents
2295 ? STARTING_WINDOW_TYPE_SNAPSHOT : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2296 } else {
2297 return STARTING_WINDOW_TYPE_NONE;
2298 }
2299 }
2300
2301
2302 private boolean snapshotOrientationSameAsTask(ActivityManager.TaskSnapshot snapshot) {
2303 if (snapshot == null) {
2304 return false;
2305 }
2306 return getTask().getConfiguration().orientation == snapshot.getOrientation();
2307 }
2308
2309 void removeStartingWindow() {
2310 if (startingWindow == null) {
chaviwa8f07a72019-05-01 16:25:39 -07002311 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002312 // Starting window has not been added yet, but it is scheduled to be added.
2313 // Go ahead and cancel the request.
2314 if (DEBUG_STARTING_WINDOW) {
2315 Slog.v(TAG_WM, "Clearing startingData for token=" + this);
2316 }
chaviwa8f07a72019-05-01 16:25:39 -07002317 mStartingData = null;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002318 }
2319 return;
2320 }
2321
2322 final WindowManagerPolicy.StartingSurface surface;
chaviwa8f07a72019-05-01 16:25:39 -07002323 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002324 surface = startingSurface;
chaviwa8f07a72019-05-01 16:25:39 -07002325 mStartingData = null;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002326 startingSurface = null;
2327 startingWindow = null;
2328 startingDisplayed = false;
2329 if (surface == null) {
2330 if (DEBUG_STARTING_WINDOW) {
2331 Slog.v(TAG_WM, "startingWindow was set but startingSurface==null, couldn't "
2332 + "remove");
2333 }
2334 return;
2335 }
2336 } else {
2337 if (DEBUG_STARTING_WINDOW) {
2338 Slog.v(TAG_WM, "Tried to remove starting window but startingWindow was null:"
2339 + this);
2340 }
2341 return;
2342 }
2343
2344 if (DEBUG_STARTING_WINDOW) {
2345 Slog.v(TAG_WM, "Schedule remove starting " + this
2346 + " startingWindow=" + startingWindow
2347 + " startingView=" + startingSurface
2348 + " Callers=" + Debug.getCallers(5));
2349 }
2350
2351 // Use the same thread to remove the window as we used to add it, as otherwise we end up
2352 // with things in the view hierarchy being called from different threads.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002353 mWmService.mAnimationHandler.post(() -> {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002354 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Removing startingView=" + surface);
2355 try {
2356 surface.remove();
2357 } catch (Exception e) {
2358 Slog.w(TAG_WM, "Exception when removing starting window", e);
2359 }
2360 });
2361 }
2362
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002363 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -07002364 boolean fillsParent() {
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -07002365 return occludesParent();
Wale Ogunwale51362492016-09-08 17:49:17 -07002366 }
2367
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -07002368 /** Returns true if this activity is opaque and fills the entire space of this task. */
2369 boolean occludesParent() {
2370 return mOccludesParent;
2371 }
2372
2373 boolean setOccludesParent(boolean occludesParent) {
2374 final boolean changed = occludesParent != mOccludesParent;
2375 mOccludesParent = occludesParent;
2376 setMainWindowOpaque(occludesParent);
2377 mWmService.mWindowPlacerLocked.requestTraversal();
2378 return changed;
2379 }
2380
2381 void setMainWindowOpaque(boolean isOpaque) {
2382 final WindowState win = findMainWindow();
2383 if (win == null) {
2384 return;
2385 }
2386 isOpaque = isOpaque & !PixelFormat.formatHasAlpha(win.getAttrs().format);
2387 win.mWinAnimator.setOpaqueLocked(isOpaque);
Wale Ogunwale51362492016-09-08 17:49:17 -07002388 }
2389
Jorim Jaggife762342016-10-13 14:33:27 +02002390 boolean containsDismissKeyguardWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002391 // Window state is transient during relaunch. We are not guaranteed to be frozen during the
2392 // entirety of the relaunch.
2393 if (isRelaunching()) {
2394 return mLastContainsDismissKeyguardWindow;
2395 }
2396
Jorim Jaggife762342016-10-13 14:33:27 +02002397 for (int i = mChildren.size() - 1; i >= 0; i--) {
2398 if ((mChildren.get(i).mAttrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
2399 return true;
2400 }
2401 }
2402 return false;
2403 }
2404
2405 boolean containsShowWhenLockedWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002406 // When we are relaunching, it is possible for us to be unfrozen before our previous
2407 // windows have been added back. Using the cached value ensures that our previous
2408 // showWhenLocked preference is honored until relaunching is complete.
2409 if (isRelaunching()) {
2410 return mLastContainsShowWhenLockedWindow;
2411 }
2412
Jorim Jaggife762342016-10-13 14:33:27 +02002413 for (int i = mChildren.size() - 1; i >= 0; i--) {
2414 if ((mChildren.get(i).mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
2415 return true;
2416 }
2417 }
Bryce Lee081554b2017-05-25 07:52:12 -07002418
Jorim Jaggife762342016-10-13 14:33:27 +02002419 return false;
2420 }
2421
2422 void checkKeyguardFlagsChanged() {
2423 final boolean containsDismissKeyguard = containsDismissKeyguardWindow();
2424 final boolean containsShowWhenLocked = containsShowWhenLockedWindow();
2425 if (containsDismissKeyguard != mLastContainsDismissKeyguardWindow
2426 || containsShowWhenLocked != mLastContainsShowWhenLockedWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002427 mWmService.notifyKeyguardFlagsChanged(null /* callback */,
lumark588a3e82018-07-20 18:53:54 +08002428 getDisplayContent().getDisplayId());
Jorim Jaggife762342016-10-13 14:33:27 +02002429 }
2430 mLastContainsDismissKeyguardWindow = containsDismissKeyguard;
2431 mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
2432 }
2433
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002434 WindowState getImeTargetBelowWindow(WindowState w) {
2435 final int index = mChildren.indexOf(w);
2436 if (index > 0) {
2437 final WindowState target = mChildren.get(index - 1);
2438 if (target.canBeImeTarget()) {
2439 return target;
2440 }
2441 }
2442 return null;
2443 }
2444
2445 WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
2446 WindowState candidate = null;
2447 for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
2448 final WindowState w = mChildren.get(i);
2449 if (w.mRemoved) {
2450 continue;
2451 }
Jorim Jaggi35d328a2018-08-14 17:00:20 +02002452 if (candidate == null) {
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002453 candidate = w;
2454 }
2455 }
2456 return candidate;
2457 }
2458
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002459 /**
2460 * See {@link Activity#setDisablePreviewScreenshots}.
2461 */
2462 void setDisablePreviewScreenshots(boolean disable) {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002463 mDisablePreviewScreenshots = disable;
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002464 }
2465
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002466 /**
Riddle Hsu4bb06be2019-07-02 01:03:07 +08002467 * Sets whether the current launch can turn the screen on.
2468 * @see #currentLaunchCanTurnScreenOn()
chaviwd3bf08d2017-08-01 17:24:59 -07002469 */
Riddle Hsu4bb06be2019-07-02 01:03:07 +08002470 void setCurrentLaunchCanTurnScreenOn(boolean currentLaunchCanTurnScreenOn) {
2471 mCurrentLaunchCanTurnScreenOn = currentLaunchCanTurnScreenOn;
chaviwd3bf08d2017-08-01 17:24:59 -07002472 }
2473
2474 /**
2475 * Indicates whether the current launch can turn the screen on. This is to prevent multiple
2476 * relayouts from turning the screen back on. The screen should only turn on at most
2477 * once per activity resume.
Riddle Hsu4bb06be2019-07-02 01:03:07 +08002478 * <p>
2479 * Note this flag is only meaningful when {@link WindowManager.LayoutParams#FLAG_TURN_SCREEN_ON}
2480 * or {@link ActivityRecord#canTurnScreenOn} is set.
chaviwd3bf08d2017-08-01 17:24:59 -07002481 *
Riddle Hsu4bb06be2019-07-02 01:03:07 +08002482 * @return {@code true} if the activity is ready to turn on the screen.
chaviwd3bf08d2017-08-01 17:24:59 -07002483 */
Riddle Hsu4bb06be2019-07-02 01:03:07 +08002484 boolean currentLaunchCanTurnScreenOn() {
2485 return mCurrentLaunchCanTurnScreenOn;
chaviwd3bf08d2017-08-01 17:24:59 -07002486 }
2487
2488 /**
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002489 * Retrieves whether we'd like to generate a snapshot that's based solely on the theme. This is
2490 * the case when preview screenshots are disabled {@link #setDisablePreviewScreenshots} or when
2491 * we can't take a snapshot for other reasons, for example, if we have a secure window.
2492 *
2493 * @return True if we need to generate an app theme snapshot, false if we'd like to take a real
2494 * screenshot.
2495 */
2496 boolean shouldUseAppThemeSnapshot() {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002497 return mDisablePreviewScreenshots || forAllWindows(w -> (w.mAttrs.flags & FLAG_SECURE) != 0,
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002498 true /* topToBottom */);
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002499 }
2500
Jorim Jaggibe418292018-03-26 16:14:12 +02002501 SurfaceControl getAppAnimationLayer() {
Jorim Jaggi391790622018-04-18 15:30:44 +02002502 return getAppAnimationLayer(isActivityTypeHome() ? ANIMATION_LAYER_HOME
2503 : needsZBoost() ? ANIMATION_LAYER_BOOSTED
2504 : ANIMATION_LAYER_STANDARD);
Jorim Jaggibe418292018-03-26 16:14:12 +02002505 }
2506
chaviw23ee71c2017-12-18 11:29:41 -08002507 @Override
Jorim Jaggi596a1992017-12-29 14:48:02 +01002508 public SurfaceControl getAnimationLeashParent() {
Robert Carrb9506032018-02-13 13:54:00 -08002509 // For transitions in the pinned stack (menu activity) we just let them occur as a child
2510 // of the pinned stack.
Issei Suzuki71142152019-08-15 14:39:40 +02002511 // All normal app transitions take place in an animation layer which is below the pinned
2512 // stack but may be above the parent stacks of the given animating apps by default. When
2513 // a new hierarchical animation is enabled, we just let them occur as a child of the parent
2514 // stack, i.e. the hierarchy of the surfaces is unchanged.
2515 if (inPinnedWindowingMode()) {
Robert Carrb9506032018-02-13 13:54:00 -08002516 return getStack().getSurfaceControl();
Issei Suzuki71142152019-08-15 14:39:40 +02002517 } else if (WindowManagerService.sHierarchicalAnimations) {
2518 return super.getAnimationLeashParent();
2519 } else {
2520 return getAppAnimationLayer();
Robert Carrb9506032018-02-13 13:54:00 -08002521 }
chaviw23ee71c2017-12-18 11:29:41 -08002522 }
2523
lumarkb5a78b32019-04-25 20:31:30 +08002524
2525 @VisibleForTesting
2526 boolean shouldAnimate(int transit) {
Jorim Jaggic6976f02018-04-18 16:31:07 +02002527 final boolean isSplitScreenPrimary =
2528 getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
2529 final boolean allowSplitScreenPrimaryAnimation = transit != TRANSIT_WALLPAPER_OPEN;
2530
lumarkb5a78b32019-04-25 20:31:30 +08002531 // Don't animate while the task runs recents animation but only if we are in the mode
2532 // where we cancel with deferred screenshot, which means that the controller has
2533 // transformed the task.
lumark54284462019-03-05 20:44:27 +08002534 final RecentsAnimationController controller = mWmService.getRecentsAnimationController();
lumarkb5a78b32019-04-25 20:31:30 +08002535 if (controller != null && controller.isAnimatingTask(getTask())
Winson Chung7a545ae2019-07-16 14:52:13 -07002536 && controller.shouldDeferCancelUntilNextTransition()) {
lumark54284462019-03-05 20:44:27 +08002537 return false;
2538 }
2539
Jorim Jaggic6976f02018-04-18 16:31:07 +02002540 // We animate always if it's not split screen primary, and only some special cases in split
2541 // screen primary because it causes issues with stack clipping when we run an un-minimize
2542 // animation at the same time.
2543 return !isSplitScreenPrimary || allowSplitScreenPrimaryAnimation;
2544 }
2545
Vishnu Naira2977262018-07-26 13:31:26 -07002546 /**
2547 * Creates a layer to apply crop to an animation.
2548 */
2549 private SurfaceControl createAnimationBoundsLayer(Transaction t) {
2550 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.i(TAG, "Creating animation bounds layer");
2551 final SurfaceControl.Builder builder = makeAnimationLeash()
2552 .setParent(getAnimationLeashParent())
Vishnu Naire86bd982018-11-28 13:23:17 -08002553 .setName(getSurfaceControl() + " - animation-bounds");
Vishnu Naira2977262018-07-26 13:31:26 -07002554 final SurfaceControl boundsLayer = builder.build();
2555 t.show(boundsLayer);
2556 return boundsLayer;
2557 }
2558
Evan Roskyed6767f2018-10-26 17:21:06 -07002559 @Override
2560 Rect getDisplayedBounds() {
2561 final Task task = getTask();
2562 if (task != null) {
2563 final Rect overrideDisplayedBounds = task.getOverrideDisplayedBounds();
2564 if (!overrideDisplayedBounds.isEmpty()) {
2565 return overrideDisplayedBounds;
2566 }
2567 }
2568 return getBounds();
2569 }
2570
Evan Rosky641daea2019-04-24 14:45:24 -07002571 @VisibleForTesting
2572 Rect getAnimationBounds(int appStackClipMode) {
2573 if (appStackClipMode == STACK_CLIP_BEFORE_ANIM && getStack() != null) {
2574 // Using the stack bounds here effectively applies the clipping before animation.
2575 return getStack().getBounds();
2576 }
2577 // Use task-bounds if available so that activity-level letterbox (maxAspectRatio) is
2578 // included in the animation.
2579 return getTask() != null ? getTask().getBounds() : getBounds();
2580 }
2581
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002582 boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter,
2583 boolean isVoiceInteraction) {
2584
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002585 if (mWmService.mDisableTransitionAnimation || !shouldAnimate(transit)) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002586 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
Jorim Jaggic6976f02018-04-18 16:31:07 +02002587 Slog.v(TAG_WM, "applyAnimation: transition animation is disabled or skipped."
2588 + " atoken=" + this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002589 }
2590 cancelAnimation();
2591 return false;
2592 }
2593
2594 // Only apply an animation if the display isn't frozen. If it is frozen, there is no reason
2595 // to animate and it can cause strange artifacts when we unfreeze the display if some
2596 // different animation is running.
2597 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#applyAnimationLocked");
2598 if (okToAnimate()) {
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002599 final AnimationAdapter adapter;
Evan Rosky2289ba12018-11-19 18:28:18 -08002600 AnimationAdapter thumbnailAdapter = null;
Evan Rosky4fb1e912019-03-06 13:54:43 -08002601
Evan Rosky641daea2019-04-24 14:45:24 -07002602 final int appStackClipMode =
2603 getDisplayContent().mAppTransition.getAppStackClipMode();
2604
2605 // Separate position and size for use in animators.
2606 mTmpRect.set(getAnimationBounds(appStackClipMode));
Evan Rosky4fb1e912019-03-06 13:54:43 -08002607 mTmpPoint.set(mTmpRect.left, mTmpRect.top);
2608 mTmpRect.offsetTo(0, 0);
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002609
Evan Roskyec9488c2019-03-01 19:32:12 -08002610 final boolean isChanging = AppTransition.isChangeTransit(transit) && enter
2611 && getDisplayContent().mChangingApps.contains(this);
Evan Rosky2289ba12018-11-19 18:28:18 -08002612
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002613 // Delaying animation start isn't compatible with remote animations at all.
lumark588a3e82018-07-20 18:53:54 +08002614 if (getDisplayContent().mAppTransition.getRemoteAnimationController() != null
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002615 && !mSurfaceAnimator.isAnimationStartDelayed()) {
Evan Rosky2289ba12018-11-19 18:28:18 -08002616 RemoteAnimationRecord adapters =
2617 getDisplayContent().mAppTransition.getRemoteAnimationController()
2618 .createRemoteAnimationRecord(this, mTmpPoint, mTmpRect,
2619 (isChanging ? mTransitStartRect : null));
2620 adapter = adapters.mAdapter;
2621 thumbnailAdapter = adapters.mThumbnailAdapter;
2622 } else if (isChanging) {
Evan Roskycf76bed2019-01-15 10:33:58 -08002623 final float durationScale = mWmService.getTransitionAnimationScaleLocked();
Evan Rosky2289ba12018-11-19 18:28:18 -08002624 mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y);
2625 adapter = new LocalAnimationAdapter(
2626 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
Evan Roskycf76bed2019-01-15 10:33:58 -08002627 getDisplayContent().getDisplayInfo(), durationScale,
Evan Rosky2289ba12018-11-19 18:28:18 -08002628 true /* isAppAnimation */, false /* isThumbnail */),
2629 mWmService.mSurfaceAnimationRunner);
Evan Rosky966759f2019-01-15 10:33:58 -08002630 if (mThumbnail != null) {
2631 thumbnailAdapter = new LocalAnimationAdapter(
2632 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
Evan Roskycf76bed2019-01-15 10:33:58 -08002633 getDisplayContent().getDisplayInfo(), durationScale,
Evan Rosky966759f2019-01-15 10:33:58 -08002634 true /* isAppAnimation */, true /* isThumbnail */),
2635 mWmService.mSurfaceAnimationRunner);
2636 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002637 mTransit = transit;
2638 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002639 } else {
Vishnu Naira2977262018-07-26 13:31:26 -07002640 mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM);
2641
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002642 final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
2643 if (a != null) {
Lucas Dupin95acf432019-04-29 17:55:38 -07002644 // Only apply corner radius to animation if we're not in multi window mode.
2645 // We don't want rounded corners when in pip or split screen.
2646 final float windowCornerRadius = !inMultiWindowMode()
2647 ? getDisplayContent().getWindowCornerRadius()
2648 : 0;
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002649 adapter = new LocalAnimationAdapter(
2650 new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
lumark588a3e82018-07-20 18:53:54 +08002651 getDisplayContent().mAppTransition.canSkipFirstFrame(),
Vishnu Naira2977262018-07-26 13:31:26 -07002652 appStackClipMode,
Lucas Dupin3e1dc202018-12-02 15:14:20 -08002653 true /* isAppAnimation */,
Lucas Dupin95acf432019-04-29 17:55:38 -07002654 windowCornerRadius),
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002655 mWmService.mSurfaceAnimationRunner);
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002656 if (a.getZAdjustment() == Animation.ZORDER_TOP) {
2657 mNeedsZBoost = true;
2658 }
2659 mTransit = transit;
lumark588a3e82018-07-20 18:53:54 +08002660 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002661 } else {
2662 adapter = null;
chaviw23ee71c2017-12-18 11:29:41 -08002663 }
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002664 }
2665 if (adapter != null) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002666 startAnimation(getPendingTransaction(), adapter, !isVisible());
Jorim Jaggi82c17862018-02-21 17:50:18 +01002667 if (adapter.getShowWallpaper()) {
2668 mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2669 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002670 if (thumbnailAdapter != null) {
2671 mThumbnail.startAnimation(
2672 getPendingTransaction(), thumbnailAdapter, !isVisible());
2673 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002674 }
2675 } else {
2676 cancelAnimation();
2677 }
2678 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2679
2680 return isReallyAnimating();
2681 }
2682
2683 private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
2684 boolean isVoiceInteraction) {
2685 final DisplayContent displayContent = getTask().getDisplayContent();
2686 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2687 final int width = displayInfo.appWidth;
2688 final int height = displayInfo.appHeight;
2689 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG_WM,
2690 "applyAnimation: atoken=" + this);
2691
2692 // Determine the visible rect to calculate the thumbnail clip
2693 final WindowState win = findMainWindow();
2694 final Rect frame = new Rect(0, 0, width, height);
2695 final Rect displayFrame = new Rect(0, 0,
2696 displayInfo.logicalWidth, displayInfo.logicalHeight);
2697 final Rect insets = new Rect();
2698 final Rect stableInsets = new Rect();
2699 Rect surfaceInsets = null;
2700 final boolean freeform = win != null && win.inFreeformWindowingMode();
2701 if (win != null) {
2702 // Containing frame will usually cover the whole screen, including dialog windows.
2703 // For freeform workspace windows it will not cover the whole screen and it also
2704 // won't exactly match the final freeform window frame (e.g. when overlapping with
2705 // the status bar). In that case we need to use the final frame.
2706 if (freeform) {
chaviw492139a2018-07-16 16:07:35 -07002707 frame.set(win.getFrameLw());
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002708 } else if (win.isLetterboxedAppWindow()) {
2709 frame.set(getTask().getBounds());
Winson Chungc1674272018-02-21 10:15:17 -08002710 } else if (win.isDockedResizing()) {
2711 // If we are animating while docked resizing, then use the stack bounds as the
2712 // animation target (which will be different than the task bounds)
2713 frame.set(getTask().getParent().getBounds());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002714 } else {
chaviw553b0212018-07-12 13:37:01 -07002715 frame.set(win.getContainingFrame());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002716 }
2717 surfaceInsets = win.getAttrs().surfaceInsets;
Adrian Roos20e07892018-02-23 19:12:01 +01002718 // XXX(b/72757033): These are insets relative to the window frame, but we're really
2719 // interested in the insets relative to the frame we chose in the if-blocks above.
chaviw9c81e632018-07-31 11:17:52 -07002720 win.getContentInsets(insets);
2721 win.getStableInsets(stableInsets);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002722 }
2723
2724 if (mLaunchTaskBehind) {
2725 // Differentiate the two animations. This one which is briefly on the screen
2726 // gets the !enter animation, and the other activity which remains on the
2727 // screen gets the enter animation. Both appear in the mOpeningApps set.
2728 enter = false;
2729 }
2730 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "Loading animation for app transition."
2731 + " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter
2732 + " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets);
2733 final Configuration displayConfig = displayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08002734 final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002735 displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
2736 surfaceInsets, stableInsets, isVoiceInteraction, freeform, getTask().mTaskId);
2737 if (a != null) {
2738 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
2739 final int containingWidth = frame.width();
2740 final int containingHeight = frame.height();
2741 a.initialize(containingWidth, containingHeight, width, height);
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002742 a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002743 }
2744 return a;
2745 }
2746
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002747 @Override
Jorim Jaggi6de61012018-03-19 14:53:23 +01002748 public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
2749 return mAnimatingAppWindowTokenRegistry != null
2750 && mAnimatingAppWindowTokenRegistry.notifyAboutToFinish(
2751 this, endDeferFinishCallback);
2752 }
2753
2754 @Override
lumarkf6f34942019-04-29 16:56:50 +08002755 public void onAnimationLeashLost(Transaction t) {
2756 super.onAnimationLeashLost(t);
Vishnu Naira2977262018-07-26 13:31:26 -07002757 if (mAnimationBoundsLayer != null) {
Robert Carr71200f22019-02-05 09:44:53 -08002758 t.remove(mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002759 mAnimationBoundsLayer = null;
2760 }
2761
Jorim Jaggi6de61012018-03-19 14:53:23 +01002762 if (mAnimatingAppWindowTokenRegistry != null) {
2763 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
2764 }
2765 }
2766
2767 @Override
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002768 protected void setLayer(Transaction t, int layer) {
2769 if (!mSurfaceAnimator.hasLeash()) {
2770 t.setLayer(mSurfaceControl, layer);
2771 }
2772 }
2773
2774 @Override
2775 protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
2776 if (!mSurfaceAnimator.hasLeash()) {
2777 t.setRelativeLayer(mSurfaceControl, relativeTo, layer);
2778 }
2779 }
2780
2781 @Override
2782 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
2783 if (!mSurfaceAnimator.hasLeash()) {
Robert Carr10584fa2019-01-14 15:55:19 -08002784 t.reparent(mSurfaceControl, newParent);
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002785 }
2786 }
2787
2788 @Override
2789 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002790 // The leash is parented to the animation layer. We need to preserve the z-order by using
2791 // the prefix order index, but we boost if necessary.
Robert Carrb9506032018-02-13 13:54:00 -08002792 int layer = 0;
2793 if (!inPinnedWindowingMode()) {
2794 layer = getPrefixOrderIndex();
2795 } else {
2796 // Pinned stacks have animations take place within themselves rather than an animation
2797 // layer so we need to preserve the order relative to the stack (e.g. the order of our
2798 // task/parent).
2799 layer = getParent().getPrefixOrderIndex();
2800 }
2801
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002802 if (mNeedsZBoost) {
2803 layer += Z_BOOST_BASE;
2804 }
Jorim Jaggi9cd99132019-04-24 17:41:35 +02002805 if (!mNeedsAnimationBoundsLayer) {
2806 leash.setLayer(layer);
2807 }
Robert Carr2f8aa392018-01-31 14:46:51 -08002808
2809 final DisplayContent dc = getDisplayContent();
Jorim Jaggibe418292018-03-26 16:14:12 +02002810 dc.assignStackOrdering();
Evan Rosky2289ba12018-11-19 18:28:18 -08002811
2812 if (leash == mTransitChangeLeash) {
2813 // This is a temporary state so skip any animation notifications
2814 return;
2815 } else if (mTransitChangeLeash != null) {
2816 // unparent mTransitChangeLeash for clean-up
Evan Rosky25b56192019-02-06 16:10:56 -08002817 clearChangeLeash(t, false /* cancel */);
Evan Rosky2289ba12018-11-19 18:28:18 -08002818 }
2819
Jorim Jaggi6de61012018-03-19 14:53:23 +01002820 if (mAnimatingAppWindowTokenRegistry != null) {
2821 mAnimatingAppWindowTokenRegistry.notifyStarting(this);
2822 }
Vishnu Naira2977262018-07-26 13:31:26 -07002823
2824 // If the animation needs to be cropped then an animation bounds layer is created as a child
2825 // of the pinned stack or animation layer. The leash is then reparented to this new layer.
2826 if (mNeedsAnimationBoundsLayer) {
Evan Rosky7735d352019-03-18 17:27:27 -07002827 mTmpRect.setEmpty();
2828 final Task task = getTask();
2829 if (getDisplayContent().mAppTransitionController.isTransitWithinTask(
2830 getTransit(), task)) {
2831 task.getBounds(mTmpRect);
2832 } else {
2833 final TaskStack stack = getStack();
2834 if (stack == null) {
2835 return;
2836 }
2837 // Set clip rect to stack bounds.
2838 stack.getBounds(mTmpRect);
Vishnu Naira2977262018-07-26 13:31:26 -07002839 }
2840 mAnimationBoundsLayer = createAnimationBoundsLayer(t);
2841
Vishnu Naira2977262018-07-26 13:31:26 -07002842 // Crop to stack bounds.
2843 t.setWindowCrop(mAnimationBoundsLayer, mTmpRect);
Jorim Jaggi9cd99132019-04-24 17:41:35 +02002844 t.setLayer(mAnimationBoundsLayer, layer);
Vishnu Naira2977262018-07-26 13:31:26 -07002845
2846 // Reparent leash to animation bounds layer.
Robert Carr10584fa2019-01-14 15:55:19 -08002847 t.reparent(leash, mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002848 }
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002849 }
2850
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002851 /**
2852 * This must be called while inside a transaction.
2853 */
2854 void showAllWindowsLocked() {
2855 forAllWindows(windowState -> {
2856 if (DEBUG_VISIBILITY) Slog.v(TAG, "performing show on: " + windowState);
2857 windowState.performShowLocked();
2858 }, false /* traverseTopToBottom */);
Jorim Jaggia5e10572017-11-15 14:36:26 +01002859 }
2860
2861 @Override
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002862 protected void onAnimationFinished() {
2863 super.onAnimationFinished();
2864
Ian8b2822e2019-05-14 11:59:02 -07002865 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#onAnimationFinished");
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002866 mTransit = TRANSIT_UNSET;
2867 mTransitFlags = 0;
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002868 mNeedsZBoost = false;
Vishnu Naira2977262018-07-26 13:31:26 -07002869 mNeedsAnimationBoundsLayer = false;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002870
2871 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER,
2872 "AppWindowToken");
2873
Jorim Jaggi988f6682017-11-17 17:46:43 +01002874 clearThumbnail();
Jorim Jaggi752cd822018-03-29 16:29:18 +02002875 setClientHidden(isHidden() && hiddenRequested);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002876
lumarkff0ab692018-11-05 20:32:30 +08002877 getDisplayContent().computeImeTargetIfNeeded(this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002878
2879 if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + this
2880 + ": reportedVisible=" + reportedVisible
2881 + " okToDisplay=" + okToDisplay()
2882 + " okToAnimate=" + okToAnimate()
2883 + " startingDisplayed=" + startingDisplayed);
2884
Evan Rosky2289ba12018-11-19 18:28:18 -08002885 // clean up thumbnail window
2886 if (mThumbnail != null) {
2887 mThumbnail.destroy();
2888 mThumbnail = null;
2889 }
2890
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002891 // WindowState.onExitAnimationDone might modify the children list, so make a copy and then
2892 // traverse the copy.
2893 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
2894 children.forEach(WindowState::onExitAnimationDone);
2895
lumark588a3e82018-07-20 18:53:54 +08002896 getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002897 scheduleAnimation();
Jorim Jaggi9b5e3312019-03-01 18:08:00 +01002898
2899 mActivityRecord.onAnimationFinished();
Ian8b2822e2019-05-14 11:59:02 -07002900 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002901 }
2902
2903 @Override
2904 boolean isAppAnimating() {
2905 return isSelfAnimating();
2906 }
2907
2908 @Override
2909 boolean isSelfAnimating() {
2910 // If we are about to start a transition, we also need to be considered animating.
2911 return isWaitingForTransitionStart() || isReallyAnimating();
2912 }
2913
2914 /**
2915 * @return True if and only if we are actually running an animation. Note that
2916 * {@link #isSelfAnimating} also returns true if we are waiting for an animation to
2917 * start.
2918 */
2919 private boolean isReallyAnimating() {
2920 return super.isSelfAnimating();
2921 }
2922
Evan Rosky25b56192019-02-06 16:10:56 -08002923 /**
2924 * @param cancel {@code true} if clearing the leash due to cancelling instead of transferring
2925 * to another leash.
2926 */
2927 private void clearChangeLeash(Transaction t, boolean cancel) {
2928 if (mTransitChangeLeash == null) {
2929 return;
2930 }
2931 if (cancel) {
2932 clearThumbnail();
2933 SurfaceControl sc = getSurfaceControl();
2934 SurfaceControl parentSc = getParentSurfaceControl();
2935 // Don't reparent if surface is getting destroyed
2936 if (parentSc != null && sc != null) {
2937 t.reparent(sc, getParentSurfaceControl());
2938 }
2939 }
2940 t.hide(mTransitChangeLeash);
Evan Rosky08e20932019-05-14 10:54:07 -07002941 t.remove(mTransitChangeLeash);
Evan Rosky25b56192019-02-06 16:10:56 -08002942 mTransitChangeLeash = null;
2943 if (cancel) {
lumarkf6f34942019-04-29 16:56:50 +08002944 onAnimationLeashLost(t);
Evan Rosky25b56192019-02-06 16:10:56 -08002945 }
2946 }
2947
Jorim Jaggi988f6682017-11-17 17:46:43 +01002948 @Override
2949 void cancelAnimation() {
Evan Rosky2289ba12018-11-19 18:28:18 -08002950 cancelAnimationOnly();
Jorim Jaggi988f6682017-11-17 17:46:43 +01002951 clearThumbnail();
Evan Rosky25b56192019-02-06 16:10:56 -08002952 clearChangeLeash(getPendingTransaction(), true /* cancel */);
Evan Rosky2289ba12018-11-19 18:28:18 -08002953 }
2954
2955 /**
2956 * This only cancels the animation. It doesn't do other teardown like cleaning-up thumbnail
2957 * or interim leashes.
2958 * <p>
2959 * Used when canceling in preparation for starting a new animation.
2960 */
2961 void cancelAnimationOnly() {
2962 super.cancelAnimation();
Jorim Jaggi988f6682017-11-17 17:46:43 +01002963 }
2964
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002965 boolean isWaitingForTransitionStart() {
lumark588a3e82018-07-20 18:53:54 +08002966 return getDisplayContent().mAppTransition.isTransitionSet()
2967 && (getDisplayContent().mOpeningApps.contains(this)
Evan Rosky2289ba12018-11-19 18:28:18 -08002968 || getDisplayContent().mClosingApps.contains(this)
2969 || getDisplayContent().mChangingApps.contains(this));
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002970 }
2971
2972 public int getTransit() {
2973 return mTransit;
2974 }
2975
2976 int getTransitFlags() {
2977 return mTransitFlags;
2978 }
2979
Jorim Jaggi988f6682017-11-17 17:46:43 +01002980 void attachThumbnailAnimation() {
2981 if (!isReallyAnimating()) {
2982 return;
2983 }
2984 final int taskId = getTask().mTaskId;
2985 final GraphicBuffer thumbnailHeader =
lumark588a3e82018-07-20 18:53:54 +08002986 getDisplayContent().mAppTransition.getAppTransitionThumbnailHeader(taskId);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002987 if (thumbnailHeader == null) {
2988 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG, "No thumbnail header bitmap for: " + taskId);
2989 return;
2990 }
2991 clearThumbnail();
Vishnu Nair33197392019-08-30 10:29:37 -07002992 mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory, getPendingTransaction(),
2993 this, thumbnailHeader);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002994 mThumbnail.startAnimation(getPendingTransaction(), loadThumbnailAnimation(thumbnailHeader));
2995 }
2996
Tony Mak64b8d562017-12-28 17:44:02 +00002997 /**
2998 * Attaches a surface with a thumbnail for the
2999 * {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation.
3000 */
3001 void attachCrossProfileAppsThumbnailAnimation() {
3002 if (!isReallyAnimating()) {
3003 return;
3004 }
3005 clearThumbnail();
3006
3007 final WindowState win = findMainWindow();
3008 if (win == null) {
3009 return;
3010 }
chaviw492139a2018-07-16 16:07:35 -07003011 final Rect frame = win.getFrameLw();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08003012 final int thumbnailDrawableRes = getTask().mUserId == mWmService.mCurrentUserId
Tony Mak64b8d562017-12-28 17:44:02 +00003013 ? R.drawable.ic_account_circle
Tony Makda4af232018-04-27 11:01:10 +01003014 : R.drawable.ic_corp_badge;
Tony Mak64b8d562017-12-28 17:44:02 +00003015 final GraphicBuffer thumbnail =
lumark588a3e82018-07-20 18:53:54 +08003016 getDisplayContent().mAppTransition
Tony Mak64b8d562017-12-28 17:44:02 +00003017 .createCrossProfileAppsThumbnail(thumbnailDrawableRes, frame);
3018 if (thumbnail == null) {
3019 return;
3020 }
Vishnu Nair33197392019-08-30 10:29:37 -07003021 mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory,
3022 getPendingTransaction(), this, thumbnail);
Tony Mak64b8d562017-12-28 17:44:02 +00003023 final Animation animation =
lumark588a3e82018-07-20 18:53:54 +08003024 getDisplayContent().mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(
chaviw492139a2018-07-16 16:07:35 -07003025 win.getFrameLw());
Tony Mak64b8d562017-12-28 17:44:02 +00003026 mThumbnail.startAnimation(getPendingTransaction(), animation, new Point(frame.left,
3027 frame.top));
3028 }
3029
Jorim Jaggi988f6682017-11-17 17:46:43 +01003030 private Animation loadThumbnailAnimation(GraphicBuffer thumbnailHeader) {
3031 final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
3032
3033 // If this is a multi-window scenario, we use the windows frame as
3034 // destination of the thumbnail header animation. If this is a full screen
3035 // window scenario, we use the whole display as the target.
3036 WindowState win = findMainWindow();
3037 Rect appRect = win != null ? win.getContentFrameLw() :
3038 new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
chaviw9c81e632018-07-31 11:17:52 -07003039 final Rect insets = win != null ? win.getContentInsets() : null;
Jorim Jaggi988f6682017-11-17 17:46:43 +01003040 final Configuration displayConfig = mDisplayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08003041 return getDisplayContent().mAppTransition.createThumbnailAspectScaleAnimationLocked(
Jorim Jaggi988f6682017-11-17 17:46:43 +01003042 appRect, insets, thumbnailHeader, getTask().mTaskId, displayConfig.uiMode,
3043 displayConfig.orientation);
3044 }
3045
3046 private void clearThumbnail() {
3047 if (mThumbnail == null) {
3048 return;
3049 }
3050 mThumbnail.destroy();
3051 mThumbnail = null;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003052 }
3053
Jorim Jaggif84e2f62018-01-16 14:17:59 +01003054 void registerRemoteAnimations(RemoteAnimationDefinition definition) {
3055 mRemoteAnimationDefinition = definition;
3056 }
3057
3058 RemoteAnimationDefinition getRemoteAnimationDefinition() {
3059 return mRemoteAnimationDefinition;
3060 }
3061
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003062 @Override
3063 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
3064 super.dump(pw, prefix, dumpAll);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003065 if (appToken != null) {
Wale Ogunwale72919d22016-12-08 18:58:50 -08003066 pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003067 }
Winson Chung48b25652018-10-22 14:04:30 -07003068 pw.println(prefix + "component=" + mActivityComponent.flattenToShortString());
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08003069 pw.print(prefix); pw.print("task="); pw.println(getTask());
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -07003070 pw.print(prefix); pw.print(" mOccludesParent="); pw.print(mOccludesParent);
Wale Ogunwale51362492016-09-08 17:49:17 -07003071 pw.print(" mOrientation="); pw.println(mOrientation);
Wale Ogunwale89973222017-04-23 18:39:45 -07003072 pw.println(prefix + "hiddenRequested=" + hiddenRequested + " mClientHidden=" + mClientHidden
3073 + ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "")
3074 + " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible);
Craig Mautner59431632012-04-04 11:56:44 -07003075 if (paused) {
3076 pw.print(prefix); pw.print("paused="); pw.println(paused);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003077 }
Wale Ogunwale9017ec02016-02-25 08:55:25 -08003078 if (mAppStopped) {
3079 pw.print(prefix); pw.print("mAppStopped="); pw.println(mAppStopped);
3080 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07003081 if (mNumInterestingWindows != 0 || mNumDrawnWindows != 0
Jorim Jaggib0fc8172017-11-23 17:04:08 +00003082 || allDrawn || mLastAllDrawn) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07003083 pw.print(prefix); pw.print("mNumInterestingWindows=");
3084 pw.print(mNumInterestingWindows);
3085 pw.print(" mNumDrawnWindows="); pw.print(mNumDrawnWindows);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003086 pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
Craig Mautner6fbda632012-07-03 09:26:39 -07003087 pw.print(" allDrawn="); pw.print(allDrawn);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00003088 pw.print(" lastAllDrawn="); pw.print(mLastAllDrawn);
Craig Mautner6fbda632012-07-03 09:26:39 -07003089 pw.println(")");
3090 }
3091 if (inPendingTransaction) {
3092 pw.print(prefix); pw.print("inPendingTransaction=");
3093 pw.println(inPendingTransaction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003094 }
chaviwa8f07a72019-05-01 16:25:39 -07003095 if (mStartingData != null || removed || firstWindowDrawn || mIsExiting) {
3096 pw.print(prefix); pw.print("startingData="); pw.print(mStartingData);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003097 pw.print(" removed="); pw.print(removed);
Craig Mautner3d7ca312015-01-08 10:56:00 -08003098 pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
Craig Mautner799bc1d2015-01-14 10:33:48 -08003099 pw.print(" mIsExiting="); pw.println(mIsExiting);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003100 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08003101 if (startingWindow != null || startingSurface != null
Wale Ogunwale6c459212017-05-17 08:56:03 -07003102 || startingDisplayed || startingMoved || mHiddenSetFromTransferredStartingWindow) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003103 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08003104 pw.print(" startingSurface="); pw.print(startingSurface);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003105 pw.print(" startingDisplayed="); pw.print(startingDisplayed);
Wale Ogunwale6c459212017-05-17 08:56:03 -07003106 pw.print(" startingMoved="); pw.print(startingMoved);
3107 pw.println(" mHiddenSetFromTransferredStartingWindow="
3108 + mHiddenSetFromTransferredStartingWindow);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003109 }
Jorim Jaggi0429f352015-12-22 16:29:16 +01003110 if (!mFrozenBounds.isEmpty()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08003111 pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
Jorim Jaggi26c8c422016-05-09 19:57:25 -07003112 pw.print(prefix); pw.print("mFrozenMergedConfig="); pw.println(mFrozenMergedConfig);
Chong Zhangd78ddb42016-03-02 17:01:14 -08003113 }
3114 if (mPendingRelaunchCount != 0) {
3115 pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount);
Jorim Jaggi0429f352015-12-22 16:29:16 +01003116 }
Riddle Hsub398da32019-01-21 21:48:16 +08003117 if (mSizeCompatScale != 1f || mSizeCompatBounds != null) {
3118 pw.println(prefix + "mSizeCompatScale=" + mSizeCompatScale + " mSizeCompatBounds="
3119 + mSizeCompatBounds);
3120 }
Wale Ogunwalee287e192017-04-21 09:30:12 -07003121 if (mRemovingFromDisplay) {
3122 pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay);
3123 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003124 }
3125
3126 @Override
3127 void setHidden(boolean hidden) {
3128 super.setHidden(hidden);
3129 scheduleAnimation();
3130 }
3131
3132 @Override
3133 void prepareSurfaces() {
3134 // isSelfAnimating also returns true when we are about to start a transition, so we need
3135 // to check super here.
3136 final boolean reallyAnimating = super.isSelfAnimating();
3137 final boolean show = !isHidden() || reallyAnimating;
Robert Carrd8e4fb72019-01-31 11:14:30 -08003138
3139 if (mSurfaceControl != null) {
3140 if (show && !mLastSurfaceShowing) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003141 getPendingTransaction().show(mSurfaceControl);
Robert Carrd8e4fb72019-01-31 11:14:30 -08003142 } else if (!show && mLastSurfaceShowing) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003143 getPendingTransaction().hide(mSurfaceControl);
Robert Carrd8e4fb72019-01-31 11:14:30 -08003144 }
Jorim Jaggi4d1835d2017-08-31 17:28:27 +02003145 }
Jorim Jaggi988f6682017-11-17 17:46:43 +01003146 if (mThumbnail != null) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003147 mThumbnail.setShowing(getPendingTransaction(), show);
Jorim Jaggi988f6682017-11-17 17:46:43 +01003148 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003149 mLastSurfaceShowing = show;
3150 super.prepareSurfaces();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003151 }
3152
Jorim Jaggi77d0f36c2018-03-16 17:49:49 +01003153 /**
3154 * @return Whether our {@link #getSurfaceControl} is currently showing.
3155 */
3156 boolean isSurfaceShowing() {
3157 return mLastSurfaceShowing;
3158 }
3159
Jorim Jaggib0fc8172017-11-23 17:04:08 +00003160 boolean isFreezingScreen() {
3161 return mFreezingScreen;
3162 }
3163
3164 @Override
3165 boolean needsZBoost() {
3166 return mNeedsZBoost || super.needsZBoost();
3167 }
3168
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07003169 @CallSuper
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003170 @Override
Nataniel Borges023ecb52019-01-16 14:15:43 -08003171 public void writeToProto(ProtoOutputStream proto, long fieldId,
3172 @WindowTraceLogLevel int logLevel) {
3173 // Critical log level logs only visible elements to mitigate performance overheard
3174 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
3175 return;
3176 }
3177
Steven Timotiusaf03df62017-07-18 16:56:43 -07003178 final long token = proto.start(fieldId);
3179 writeNameToProto(proto, NAME);
Nataniel Borges023ecb52019-01-16 14:15:43 -08003180 super.writeToProto(proto, WINDOW_TOKEN, logLevel);
Vishnu Nair04ab4392018-01-10 11:00:06 -08003181 proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing);
3182 proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart());
3183 proto.write(IS_REALLY_ANIMATING, isReallyAnimating());
3184 if (mThumbnail != null){
3185 mThumbnail.writeToProto(proto, THUMBNAIL);
3186 }
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -07003187 proto.write(FILLS_PARENT, mOccludesParent);
Vishnu Nair04ab4392018-01-10 11:00:06 -08003188 proto.write(APP_STOPPED, mAppStopped);
3189 proto.write(HIDDEN_REQUESTED, hiddenRequested);
3190 proto.write(CLIENT_HIDDEN, mClientHidden);
3191 proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient);
3192 proto.write(REPORTED_DRAWN, reportedDrawn);
3193 proto.write(REPORTED_VISIBLE, reportedVisible);
3194 proto.write(NUM_INTERESTING_WINDOWS, mNumInterestingWindows);
3195 proto.write(NUM_DRAWN_WINDOWS, mNumDrawnWindows);
3196 proto.write(ALL_DRAWN, allDrawn);
3197 proto.write(LAST_ALL_DRAWN, mLastAllDrawn);
3198 proto.write(REMOVED, removed);
Nataniel Borges023ecb52019-01-16 14:15:43 -08003199 if (startingWindow != null) {
Vishnu Nair04ab4392018-01-10 11:00:06 -08003200 startingWindow.writeIdentifierToProto(proto, STARTING_WINDOW);
3201 }
3202 proto.write(STARTING_DISPLAYED, startingDisplayed);
3203 proto.write(STARTING_MOVED, startingMoved);
3204 proto.write(HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW,
3205 mHiddenSetFromTransferredStartingWindow);
3206 for (Rect bounds : mFrozenBounds) {
3207 bounds.writeToProto(proto, FROZEN_BOUNDS);
3208 }
Steven Timotiusaf03df62017-07-18 16:56:43 -07003209 proto.end(token);
3210 }
3211
3212 void writeNameToProto(ProtoOutputStream proto, long fieldId) {
3213 if (appToken == null) {
3214 return;
3215 }
3216 try {
3217 proto.write(fieldId, appToken.getName());
3218 } catch (RemoteException e) {
3219 // This shouldn't happen, but in this case fall back to outputting nothing
3220 Slog.e(TAG, e.toString());
3221 }
3222 }
3223
3224 @Override
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003225 public String toString() {
3226 if (stringName == null) {
3227 StringBuilder sb = new StringBuilder();
3228 sb.append("AppWindowToken{");
3229 sb.append(Integer.toHexString(System.identityHashCode(this)));
3230 sb.append(" token="); sb.append(token); sb.append('}');
3231 stringName = sb.toString();
3232 }
Wale Ogunwaleba51ca22016-09-23 06:06:54 -07003233 return stringName + ((mIsExiting) ? " mIsExiting=" : "");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003234 }
Adrian Roos20e07892018-02-23 19:12:01 +01003235
3236 Rect getLetterboxInsets() {
3237 if (mLetterbox != null) {
3238 return mLetterbox.getInsets();
3239 } else {
3240 return new Rect();
3241 }
3242 }
Adrian Roos23df3a32018-03-15 15:41:13 +01003243
Riddle Hsu69de5fb2019-02-23 01:19:50 +08003244 /** Gets the inner bounds of letterbox. The bounds will be empty if there is no letterbox. */
3245 void getLetterboxInnerBounds(Rect outBounds) {
3246 if (mLetterbox != null) {
3247 outBounds.set(mLetterbox.getInnerFrame());
3248 } else {
3249 outBounds.setEmpty();
3250 }
3251 }
3252
Adrian Roos23df3a32018-03-15 15:41:13 +01003253 /**
Riddle Hsu69de5fb2019-02-23 01:19:50 +08003254 * @return {@code true} if there is a letterbox and any part of that letterbox overlaps with
Adrian Roos23df3a32018-03-15 15:41:13 +01003255 * the given {@code rect}.
3256 */
3257 boolean isLetterboxOverlappingWith(Rect rect) {
3258 return mLetterbox != null && mLetterbox.isOverlappingWith(rect);
3259 }
chaviw4ad54912018-05-30 11:05:44 -07003260
3261 /**
3262 * Sets if this AWT is in the process of closing or entering PIP.
3263 * {@link #mWillCloseOrEnterPip}}
3264 */
3265 void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
3266 mWillCloseOrEnterPip = willCloseOrEnterPip;
3267 }
3268
3269 /**
3270 * Returns whether this AWT is considered closing. Conditions are either
3271 * 1. Is this app animating and was requested to be hidden
3272 * 2. App is delayed closing since it might enter PIP.
3273 */
3274 boolean isClosingOrEnteringPip() {
3275 return (isAnimating() && hiddenRequested) || mWillCloseOrEnterPip;
3276 }
Jorim Jaggiaf0d6d22018-06-08 15:25:35 +02003277
3278 /**
3279 * @return Whether we are allowed to show non-starting windows at the moment. We disallow
3280 * showing windows during transitions in case we have windows that have wide-color-gamut
3281 * color mode set to avoid jank in the middle of the transition.
3282 */
3283 boolean canShowWindows() {
3284 return allDrawn && !(isReallyAnimating() && hasNonDefaultColorWindow());
3285 }
3286
3287 /**
3288 * @return true if we have a window that has a non-default color mode set; false otherwise.
3289 */
3290 private boolean hasNonDefaultColorWindow() {
3291 return forAllWindows(ws -> ws.mAttrs.getColorMode() != COLOR_MODE_DEFAULT,
3292 true /* topToBottom */);
3293 }
lumark588a3e82018-07-20 18:53:54 +08003294
chaviwdcf76ec2019-01-11 16:48:46 -08003295 private void updateColorTransform() {
3296 if (mSurfaceControl != null && mLastAppSaturationInfo != null) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003297 getPendingTransaction().setColorTransform(mSurfaceControl,
3298 mLastAppSaturationInfo.mMatrix, mLastAppSaturationInfo.mTranslation);
chaviwdcf76ec2019-01-11 16:48:46 -08003299 mWmService.scheduleAnimationLocked();
3300 }
3301 }
3302
3303 private static class AppSaturationInfo {
3304 float[] mMatrix = new float[9];
3305 float[] mTranslation = new float[3];
3306
3307 void setSaturation(@Size(9) float[] matrix, @Size(3) float[] translation) {
3308 System.arraycopy(matrix, 0, mMatrix, 0, mMatrix.length);
3309 System.arraycopy(translation, 0, mTranslation, 0, mTranslation.length);
3310 }
3311 }
Jeff Browne9bdb312012-04-05 15:30:10 -07003312}