blob: 93b8f0022f79eedb343546b70837f1e3d69a1864 [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
551 // Let's reset the draw state in order to prevent the starting window to be
552 // immediately dismissed when the app still has the surface.
553 forAllWindows(w -> {
554 if (w.mWinAnimator.mDrawState == HAS_DRAWN) {
555 w.mWinAnimator.resetDrawState();
556
557 // Force add to mResizingWindows, so that we are guaranteed to get
558 // another reportDrawn callback.
559 w.resetLastContentInsets();
560 }
561 }, true /* traverseTopToBottom */);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800562 }
563 }
564
565 // In the case where we are making an app visible but holding off for a transition,
566 // we still need to tell the client to make its windows visible so they get drawn.
567 // Otherwise, we will wait on performing the transition until all windows have been
568 // drawn, they never will be, and we are sad.
569 setClientHidden(false);
570
571 requestUpdateWallpaperIfNeeded();
572
573 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "No longer Stopped: " + this);
574 mAppStopped = false;
575
576 transferStartingWindowFromHiddenAboveTokenIfNeeded();
577 }
578
579 // If we are preparing an app transition, then delay changing
580 // the visibility of this token until we execute that transition.
581 if (okToAnimate() && appTransition.isTransitionSet()) {
582 inPendingTransaction = true;
583 if (visible) {
584 displayContent.mOpeningApps.add(this);
585 mEnteringAnimation = true;
586 } else {
587 displayContent.mClosingApps.add(this);
588 mEnteringAnimation = false;
589 }
Louis Chang37317152019-05-09 09:53:58 +0800590 if (appTransition.getAppTransition() == TRANSIT_TASK_OPEN_BEHIND) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800591 // We're launchingBehind, add the launching activity to mOpeningApps.
592 final WindowState win = getDisplayContent().findFocusedWindow();
593 if (win != null) {
594 final AppWindowToken focusedToken = win.mAppToken;
595 if (focusedToken != null) {
596 if (DEBUG_APP_TRANSITIONS) {
597 Slog.d(TAG_WM, "TRANSIT_TASK_OPEN_BEHIND, "
598 + " adding " + focusedToken + " to mOpeningApps");
599 }
600 // Force animation to be loaded.
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800601 displayContent.mOpeningApps.add(focusedToken);
602 }
603 }
604 }
Garfield Tanb6776602019-02-20 14:44:26 -0800605 // Changes in opening apps and closing apps may cause orientation change.
606 reportDescendantOrientationChangeIfNeeded();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800607 return;
608 }
609
610 commitVisibility(null, visible, TRANSIT_UNSET, true, mVoiceInteraction);
611 updateReportedVisibilityLocked();
612 }
613
614 boolean commitVisibility(WindowManager.LayoutParams lp,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700615 boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
616
617 boolean delayed = false;
618 inPendingTransaction = false;
Wale Ogunwale9e4721f2017-05-23 19:37:30 -0700619 // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually
620 // been set by the app now.
621 mHiddenSetFromTransferredStartingWindow = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700622
623 // Allow for state changes and animation to be applied if:
624 // * token is transitioning visibility state
625 // * or the token was marked as hidden and is exiting before we had a chance to play the
626 // transition animation
Louis Chang37317152019-05-09 09:53:58 +0800627 // * or this is an opening app and windows are being replaced
628 // * or the token is the opening app and visible while opening task behind existing one.
629 final DisplayContent displayContent = getDisplayContent();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700630 boolean visibilityChanged = false;
Louis Chang37317152019-05-09 09:53:58 +0800631 if (isHidden() == visible || (isHidden() && mIsExiting)
632 || (visible && waitingForReplacement())
633 || (visible && displayContent.mOpeningApps.contains(this)
634 && displayContent.mAppTransition.getAppTransition() == TRANSIT_TASK_OPEN_BEHIND)) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800635 final AccessibilityController accessibilityController =
636 mWmService.mAccessibilityController;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700637 boolean changed = false;
638 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM,
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200639 "Changing app " + this + " hidden=" + isHidden() + " performLayout=" + performLayout);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700640
641 boolean runningAppAnimation = false;
642
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100643 if (transit != WindowManager.TRANSIT_UNSET) {
Tiger Huangc9d0d002019-05-29 22:55:29 +0800644 if (mUseTransferredAnimation) {
645 runningAppAnimation = isReallyAnimating();
646 } else if (applyAnimationLocked(lp, transit, visible, isVoiceInteraction)) {
647 runningAppAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700648 }
Tiger Huangc9d0d002019-05-29 22:55:29 +0800649 delayed = runningAppAnimation;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700650 final WindowState window = findMainWindow();
Rhed Jao02655dc2018-10-30 20:44:52 +0800651 if (window != null && accessibilityController != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700652 accessibilityController.onAppWindowTransitionLocked(window, transit);
653 }
654 changed = true;
655 }
656
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700657 final int windowsCount = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700658 for (int i = 0; i < windowsCount; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700659 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700660 changed |= win.onAppVisibilityChanged(visible, runningAppAnimation);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700661 }
662
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200663 setHidden(!visible);
664 hiddenRequested = !visible;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700665 visibilityChanged = true;
666 if (!visible) {
667 stopFreezingScreen(true, true);
668 } else {
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700669 // If we are being set visible, and the starting window is not yet displayed,
670 // then make sure it doesn't get displayed.
671 if (startingWindow != null && !startingWindow.isDrawnLw()) {
chaviw15ad49f2019-04-24 15:05:39 -0700672 startingWindow.clearPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY);
673 startingWindow.mLegacyPolicyVisibilityAfterAnim = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700674 }
Jorim Jaggi38d44ec2017-06-14 16:04:59 -0700675
676 // We are becoming visible, so better freeze the screen with the windows that are
677 // getting visible so we also wait for them.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800678 forAllWindows(mWmService::makeWindowFreezingScreenIfNeededLocked, true);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700679 }
680
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800681 if (DEBUG_APP_TRANSITIONS) {
682 Slog.v(TAG_WM, "commitVisibility: " + this
683 + ": hidden=" + isHidden() + " hiddenRequested=" + hiddenRequested);
684 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700685
686 if (changed) {
Louis Chang37317152019-05-09 09:53:58 +0800687 displayContent.getInputMonitor().setUpdateInputWindowsNeededLw();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700688 if (performLayout) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800689 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700690 false /*updateInputWindows*/);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800691 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700692 }
Louis Chang37317152019-05-09 09:53:58 +0800693 displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700694 }
695 }
Tiger Huangc9d0d002019-05-29 22:55:29 +0800696 mUseTransferredAnimation = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700697
lumarkd14173e2019-03-27 19:14:33 +0800698 if (isReallyAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700699 delayed = true;
Jorim Jaggiab9fcb22018-03-15 23:46:12 +0100700 } else {
701
702 // We aren't animating anything, but exiting windows rely on the animation finished
703 // callback being called in case the AppWindowToken was pretending to be animating,
704 // which we might have done because we were in closing/opening apps list.
705 onAnimationFinished();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700706 }
707
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700708 for (int i = mChildren.size() - 1; i >= 0 && !delayed; i--) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100709 if ((mChildren.get(i)).isSelfOrChildAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700710 delayed = true;
711 }
712 }
713
714 if (visibilityChanged) {
715 if (visible && !delayed) {
716 // The token was made immediately visible, there will be no entrance animation.
717 // We need to inform the client the enter animation was finished.
718 mEnteringAnimation = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800719 mWmService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(
720 token);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700721 }
Robert Carr61b81112017-07-17 18:08:15 -0700722
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800723 // If we're becoming visible, immediately change client visibility as well. there seem
724 // to be some edge cases where we change our visibility but client visibility never gets
725 // updated.
Jorim Jaggi110839b2018-01-22 12:49:04 +0100726 // If we're becoming invisible, update the client visibility if we are not running an
727 // animation. Otherwise, we'll update client visibility in onAnimationFinished.
Jorim Jaggi3cad57f2018-02-20 18:32:01 +0100728 if (visible || !isReallyAnimating()) {
Jorim Jaggi110839b2018-01-22 12:49:04 +0100729 setClientHidden(!visible);
Jorim Jaggi4876b4a2018-01-11 15:43:49 +0100730 }
731
Louis Chang37317152019-05-09 09:53:58 +0800732 if (!displayContent.mClosingApps.contains(this)
733 && !displayContent.mOpeningApps.contains(this)) {
chaviwa953fcf2018-03-01 12:00:39 -0800734 // The token is not closing nor opening, so even if there is an animation set, that
735 // doesn't mean that it goes through the normal app transition cycle so we have
736 // to inform the docked controller about visibility change.
737 // TODO(multi-display): notify docked divider on all displays where visibility was
738 // affected.
Louis Chang37317152019-05-09 09:53:58 +0800739 displayContent.getDockedDividerController().notifyAppVisibilityChanged();
chaviwa953fcf2018-03-01 12:00:39 -0800740
741 // Take the screenshot before possibly hiding the WSA, otherwise the screenshot
742 // will not be taken.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800743 mWmService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible);
chaviwa953fcf2018-03-01 12:00:39 -0800744 }
745
Robert Carre7cc44d2017-03-20 19:04:30 -0700746 // If we are hidden but there is no delay needed we immediately
747 // apply the Surface transaction so that the ActivityManager
Robert Carr61b81112017-07-17 18:08:15 -0700748 // can have some guarantee on the Surface state following
749 // setting the visibility. This captures cases like dismissing
750 // the docked or pinned stack where there is no app transition.
751 //
752 // In the case of a "Null" animation, there will be
753 // no animation but there will still be a transition set.
754 // We still need to delay hiding the surface such that it
755 // can be synchronized with showing the next surface in the transition.
Louis Chang37317152019-05-09 09:53:58 +0800756 if (isHidden() && !delayed && !displayContent.mAppTransition.isTransitionSet()) {
Robert Carr6914f082017-03-20 19:04:30 -0700757 SurfaceControl.openTransaction();
758 for (int i = mChildren.size() - 1; i >= 0; i--) {
759 mChildren.get(i).mWinAnimator.hide("immediately hidden");
760 }
761 SurfaceControl.closeTransaction();
762 }
Garfield Tanb6776602019-02-20 14:44:26 -0800763
764 // Visibility changes may cause orientation request change.
765 reportDescendantOrientationChangeIfNeeded();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700766 }
767
768 return delayed;
769 }
770
Garfield Tanb6776602019-02-20 14:44:26 -0800771 private void reportDescendantOrientationChangeIfNeeded() {
772 // Orientation request is exposed only when we're visible. Therefore visibility change
773 // will change requested orientation. Notify upward the hierarchy ladder to adjust
774 // configuration. This is important to cases where activities with incompatible
775 // orientations launch, or user goes back from an activity of bi-orientation to an
776 // activity with specified orientation.
777 if (mActivityRecord.getRequestedConfigurationOrientation() == getConfiguration().orientation
778 || getOrientationIgnoreVisibility() == SCREEN_ORIENTATION_UNSET) {
779 return;
780 }
781
782 final IBinder freezeToken =
783 mActivityRecord.mayFreezeScreenLocked(mActivityRecord.app)
784 ? mActivityRecord.appToken : null;
785 onDescendantOrientationChanged(freezeToken, mActivityRecord);
786 }
787
Jorim Jaggi87fdbcb2017-08-17 13:41:11 +0200788 /**
789 * @return The to top most child window for which {@link LayoutParams#isFullscreen()} returns
790 * true.
791 */
792 WindowState getTopFullscreenWindow() {
793 for (int i = mChildren.size() - 1; i >= 0; i--) {
794 final WindowState win = mChildren.get(i);
795 if (win != null && win.mAttrs.isFullscreen()) {
796 return win;
797 }
798 }
799 return null;
800 }
801
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800802 WindowState findMainWindow() {
Matthew Ng53e66b22018-01-12 17:13:13 -0800803 return findMainWindow(true);
804 }
805
806 /**
807 * Finds the main window that either has type base application or application starting if
808 * requested.
809 *
810 * @param includeStartingApp Allow to search application-starting windows to also be returned.
811 * @return The main window of type base application or application starting if requested.
812 */
813 WindowState findMainWindow(boolean includeStartingApp) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700814 WindowState candidate = null;
Matthew Ng53e66b22018-01-12 17:13:13 -0800815 for (int j = mChildren.size() - 1; j >= 0; --j) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700816 final WindowState win = mChildren.get(j);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700817 final int type = win.mAttrs.type;
818 // No need to loop through child window as base application and starting types can't be
819 // child windows.
Matthew Ng53e66b22018-01-12 17:13:13 -0800820 if (type == TYPE_BASE_APPLICATION
821 || (includeStartingApp && type == TYPE_APPLICATION_STARTING)) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700822 // In cases where there are multiple windows, we prefer the non-exiting window. This
Sungsoo Lim0d3d1f82015-12-02 14:47:59 +0900823 // happens for example when replacing windows during an activity relaunch. When
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700824 // constructing the animation, we want the new window, not the exiting one.
Wale Ogunwalec48a3542016-02-19 15:18:45 -0800825 if (win.mAnimatingExit) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700826 candidate = win;
827 } else {
828 return win;
829 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800830 }
831 }
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700832 return candidate;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800833 }
834
Wale Ogunwale6cae7652015-12-26 07:36:26 -0800835 boolean windowsAreFocusable() {
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800836 if (mTargetSdk < Build.VERSION_CODES.Q) {
837 final int pid = mActivityRecord != null
838 ? (mActivityRecord.app != null ? mActivityRecord.app.getPid() : 0) : 0;
839 final AppWindowToken topFocusedAppOfMyProcess =
840 mWmService.mRoot.mTopFocusedAppByProcess.get(pid);
841 if (topFocusedAppOfMyProcess != null && topFocusedAppOfMyProcess != this) {
842 // For the apps below Q, there can be only one app which has the focused window per
843 // process, because legacy apps may not be ready for a multi-focus system.
844 return false;
845 }
846 }
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700847 return getWindowConfiguration().canReceiveKeys() || mAlwaysFocusable;
Wale Ogunwaled045c822015-12-02 09:14:28 -0800848 }
849
Wale Ogunwale571771c2016-08-26 13:18:50 -0700850 @Override
Wale Ogunwale44f21802016-09-02 12:49:48 -0700851 boolean isVisible() {
Wale Ogunwalee471be62016-10-03 07:53:55 -0700852 // If the app token isn't hidden then it is considered visible and there is no need to check
853 // its children windows to see if they are visible.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200854 return !isHidden();
Wale Ogunwale44f21802016-09-02 12:49:48 -0700855 }
856
857 @Override
Wale Ogunwalee287e192017-04-21 09:30:12 -0700858 void removeImmediately() {
859 onRemovedFromDisplay();
Yunfan Chen3a77f282018-12-12 15:47:52 -0800860 if (mActivityRecord != null) {
861 mActivityRecord.unregisterConfigurationChangeListener(this);
862 }
Wale Ogunwalee287e192017-04-21 09:30:12 -0700863 super.removeImmediately();
864 }
865
866 @Override
Wale Ogunwale571771c2016-08-26 13:18:50 -0700867 void removeIfPossible() {
Craig Mautnere3119b72015-01-20 15:02:36 -0800868 mIsExiting = false;
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800869 removeAllWindowsIfPossible();
Bryce Lee6d410262017-02-28 15:30:17 -0800870 removeImmediately();
Craig Mautnere3119b72015-01-20 15:02:36 -0800871 }
872
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700873 @Override
874 boolean checkCompleteDeferredRemoval() {
875 if (mIsExiting) {
876 removeIfPossible();
877 }
878 return super.checkCompleteDeferredRemoval();
879 }
880
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700881 void onRemovedFromDisplay() {
Wale Ogunwalee287e192017-04-21 09:30:12 -0700882 if (mRemovingFromDisplay) {
883 return;
884 }
885 mRemovingFromDisplay = true;
886
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700887 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app token: " + this);
888
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800889 boolean delayed = commitVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700890
lumark588a3e82018-07-20 18:53:54 +0800891 getDisplayContent().mOpeningApps.remove(this);
Evan Rosky2289ba12018-11-19 18:28:18 -0800892 getDisplayContent().mChangingApps.remove(this);
lumark588a3e82018-07-20 18:53:54 +0800893 getDisplayContent().mUnknownAppVisibilityController.appRemovedOrHidden(this);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800894 mWmService.mTaskSnapshotController.onAppRemoved(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700895 waitingToShow = false;
lumark588a3e82018-07-20 18:53:54 +0800896 if (getDisplayContent().mClosingApps.contains(this)) {
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700897 delayed = true;
lumark588a3e82018-07-20 18:53:54 +0800898 } else if (getDisplayContent().mAppTransition.isTransitionSet()) {
899 getDisplayContent().mClosingApps.add(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700900 delayed = true;
901 }
902
903 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app " + this + " delayed=" + delayed
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200904 + " animation=" + getAnimation() + " animating=" + isSelfAnimating());
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700905
906 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: "
907 + this + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
908
chaviwa8f07a72019-05-01 16:25:39 -0700909 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800910 removeStartingWindow();
Jorim Jaggi19be6052017-08-03 18:33:43 +0200911 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800912
Winson Chung87e5d552017-04-05 11:49:38 -0700913 // If this window was animating, then we need to ensure that the app transition notifies
lumark588a3e82018-07-20 18:53:54 +0800914 // that animations have completed in DisplayContent.handleAnimatingStoppedAndTransition(),
915 // so add to that list now
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200916 if (isSelfAnimating()) {
lumark588a3e82018-07-20 18:53:54 +0800917 getDisplayContent().mNoAnimationNotifyOnTransitionFinished.add(token);
Winson Chung87e5d552017-04-05 11:49:38 -0700918 }
919
Wale Ogunwalee287e192017-04-21 09:30:12 -0700920 final TaskStack stack = getStack();
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700921 if (delayed && !isEmpty()) {
922 // set the token aside because it has an active animation to be finished
923 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM,
924 "removeAppToken make exiting: " + this);
Wale Ogunwalee287e192017-04-21 09:30:12 -0700925 if (stack != null) {
926 stack.mExitingAppTokens.add(this);
927 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700928 mIsExiting = true;
929 } else {
930 // Make sure there is no animation running on this token, so any windows associated
931 // with it will be removed as soon as their animations are complete
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200932 cancelAnimation();
Wale Ogunwale3106ae012017-05-16 08:56:37 -0700933 if (stack != null) {
934 stack.mExitingAppTokens.remove(this);
935 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700936 removeIfPossible();
937 }
938
939 removed = true;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700940 stopFreezingScreen(true, true);
Bryce Lee6d410262017-02-28 15:30:17 -0800941
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800942 final DisplayContent dc = getDisplayContent();
943 if (dc.mFocusedApp == this) {
944 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + this
945 + " displayId=" + dc.getDisplayId());
946 dc.setFocusedApp(null);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800947 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700948 }
Riddle Hsu192fe762019-01-15 23:41:57 +0800949 if (mLetterbox != null) {
950 mLetterbox.destroy();
951 mLetterbox = null;
952 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700953
954 if (!delayed) {
955 updateReportedVisibilityLocked();
956 }
Wale Ogunwalee287e192017-04-21 09:30:12 -0700957
958 mRemovingFromDisplay = false;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700959 }
960
Chong Zhange05bcb12016-07-26 17:47:29 -0700961 void clearAnimatingFlags() {
Chong Zhangb0d26702016-08-12 16:03:29 -0700962 boolean wallpaperMightChange = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700963 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700964 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700965 wallpaperMightChange |= win.clearAnimatingFlags();
Chong Zhange05bcb12016-07-26 17:47:29 -0700966 }
Chong Zhangb0d26702016-08-12 16:03:29 -0700967 if (wallpaperMightChange) {
968 requestUpdateWallpaperIfNeeded();
969 }
Chong Zhange05bcb12016-07-26 17:47:29 -0700970 }
971
Robert Carre12aece2016-02-02 22:43:27 -0800972 void destroySurfaces() {
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700973 destroySurfaces(false /*cleanupOnResume*/);
974 }
975
976 /**
977 * Destroy surfaces which have been marked as eligible by the animator, taking care to ensure
978 * the client has finished with them.
979 *
980 * @param cleanupOnResume whether this is done when app is resumed without fully stopped. If
981 * set to true, destroy only surfaces of removed windows, and clear relevant flags of the
982 * others so that they are ready to be reused. If set to false (common case), destroy all
983 * surfaces that's eligible, if the app is already stopped.
984 */
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700985 private void destroySurfaces(boolean cleanupOnResume) {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700986 boolean destroyedSomething = false;
Jorim Jaggia5e10572017-11-15 14:36:26 +0100987
988 // Copying to a different list as multiple children can be removed.
Jorim Jaggi59f3e922018-01-05 15:40:32 +0100989 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
Jorim Jaggia5e10572017-11-15 14:36:26 +0100990 for (int i = children.size() - 1; i >= 0; i--) {
991 final WindowState win = children.get(i);
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700992 destroyedSomething |= win.destroySurface(cleanupOnResume, mAppStopped);
Robert Carre12aece2016-02-02 22:43:27 -0800993 }
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700994 if (destroyedSomething) {
995 final DisplayContent dc = getDisplayContent();
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700996 dc.assignWindowLayers(true /*setLayoutNeeded*/);
Adrian Roos23df3a32018-03-15 15:41:13 +0100997 updateLetterboxSurface(null);
Robert Carre12aece2016-02-02 22:43:27 -0800998 }
999 }
1000
Wale Ogunwale8d5a5422016-03-03 18:28:21 -08001001 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001002 * Notify that the app is now resumed, and it was not stopped before, perform a clean
1003 * up of the surfaces
Wale Ogunwale8d5a5422016-03-03 18:28:21 -08001004 */
Jorim Jaggibae01b12017-04-11 16:29:10 -07001005 void notifyAppResumed(boolean wasStopped) {
Chong Zhangad24f962016-08-25 12:12:33 -07001006 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppResumed: wasStopped=" + wasStopped
Jorim Jaggibae01b12017-04-11 16:29:10 -07001007 + " " + this);
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001008 mAppStopped = false;
chaviwd3bf08d2017-08-01 17:24:59 -07001009 // Allow the window to turn the screen on once the app is resumed again.
Riddle Hsu4bb06be2019-07-02 01:03:07 +08001010 setCurrentLaunchCanTurnScreenOn(true);
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001011 if (!wasStopped) {
1012 destroySurfaces(true /*cleanupOnResume*/);
Wale Ogunwale8d5a5422016-03-03 18:28:21 -08001013 }
Robert Carre12aece2016-02-02 22:43:27 -08001014 }
1015
Chong Zhangbef461f2015-10-27 11:38:24 -07001016 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001017 * Notify that the app has stopped, and it is okay to destroy any surfaces which were
1018 * keeping alive in case they were still being used.
1019 */
1020 void notifyAppStopped() {
1021 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: " + this);
1022 mAppStopped = true;
Hongwei Wanga5799f82019-07-01 15:52:50 -07001023 // Reset the last saved PiP snap fraction on app stop.
1024 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(this);
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001025 destroySurfaces();
1026 // Remove any starting window that was added for this app if they are still around.
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001027 removeStartingWindow();
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001028 }
1029
Chong Zhang92147042016-05-09 12:47:11 -07001030 void clearAllDrawn() {
1031 allDrawn = false;
1032 deferClearAllDrawn = false;
Chong Zhangbef461f2015-10-27 11:38:24 -07001033 }
1034
Bryce Lee6d410262017-02-28 15:30:17 -08001035 Task getTask() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001036 return (Task) getParent();
Bryce Lee6d410262017-02-28 15:30:17 -08001037 }
1038
Jorim Jaggi3878ca32017-02-02 17:13:05 -08001039 TaskStack getStack() {
1040 final Task task = getTask();
1041 if (task != null) {
1042 return task.mStack;
1043 } else {
1044 return null;
1045 }
1046 }
1047
Bryce Lee6d410262017-02-28 15:30:17 -08001048 @Override
Riddle Hsu3a4bb612019-01-31 00:02:22 +08001049 void onParentChanged() {
1050 super.onParentChanged();
Bryce Lee6d410262017-02-28 15:30:17 -08001051
Robert Carred3e83b2017-04-21 13:26:55 -07001052 final Task task = getTask();
1053
Bryce Lee6d410262017-02-28 15:30:17 -08001054 // When the associated task is {@code null}, the {@link AppWindowToken} can no longer
1055 // access visual elements like the {@link DisplayContent}. We must remove any associations
1056 // such as animations.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001057 if (!mReparenting) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001058 if (task == null) {
1059 // It is possible we have been marked as a closing app earlier. We must remove ourselves
1060 // from this list so we do not participate in any future animations.
lumark588a3e82018-07-20 18:53:54 +08001061 getDisplayContent().mClosingApps.remove(this);
Robert Carred3e83b2017-04-21 13:26:55 -07001062 } else if (mLastParent != null && mLastParent.mStack != null) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001063 task.mStack.mExitingAppTokens.remove(this);
1064 }
Bryce Lee6d410262017-02-28 15:30:17 -08001065 }
Jorim Jaggi6de61012018-03-19 14:53:23 +01001066 final TaskStack stack = getStack();
1067
1068 // If we reparent, make sure to remove ourselves from the old animation registry.
1069 if (mAnimatingAppWindowTokenRegistry != null) {
1070 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
1071 }
1072 mAnimatingAppWindowTokenRegistry = stack != null
1073 ? stack.getAnimatingAppWindowTokenRegistry()
1074 : null;
1075
Robert Carred3e83b2017-04-21 13:26:55 -07001076 mLastParent = task;
chaviwdcf76ec2019-01-11 16:48:46 -08001077
1078 updateColorTransform();
Bryce Lee6d410262017-02-28 15:30:17 -08001079 }
1080
Wale Ogunwalefa854eb2016-09-20 13:43:52 -07001081 void postWindowRemoveStartingWindowCleanup(WindowState win) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001082 // TODO: Something smells about the code below...Is there a better way?
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001083 if (startingWindow == win) {
1084 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Notify removed startingWindow " + win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001085 removeStartingWindow();
Wale Ogunwale6c459212017-05-17 08:56:03 -07001086 } else if (mChildren.size() == 0) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001087 // If this is the last window and we had requested a starting transition window,
1088 // well there is no point now.
Jorim Jaggi02886a82016-12-06 09:10:06 -08001089 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Nulling last startingData");
chaviwa8f07a72019-05-01 16:25:39 -07001090 mStartingData = null;
Wale Ogunwale6c459212017-05-17 08:56:03 -07001091 if (mHiddenSetFromTransferredStartingWindow) {
1092 // We set the hidden state to false for the token from a transferred starting window.
1093 // We now reset it back to true since the starting window was the last window in the
1094 // token.
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001095 setHidden(true);
Wale Ogunwale6c459212017-05-17 08:56:03 -07001096 }
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01001097 } else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001098 // If this is the last window except for a starting transition window,
1099 // we need to get rid of the starting transition.
Jorim Jaggie4b0f282017-05-17 15:10:29 +02001100 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Last window, removing starting window "
1101 + win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001102 removeStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001103 }
1104 }
1105
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001106 void removeDeadWindows() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001107 for (int winNdx = mChildren.size() - 1; winNdx >= 0; --winNdx) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001108 WindowState win = mChildren.get(winNdx);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001109 if (win.mAppDied) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001110 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.w(TAG,
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001111 "removeDeadWindows: " + win);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001112 // Set mDestroying, we don't want any animation or delayed removal here.
1113 win.mDestroying = true;
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001114 // Also removes child windows.
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001115 win.removeIfPossible();
Chong Zhang112eb8c2015-11-02 11:17:00 -08001116 }
1117 }
1118 }
1119
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001120 boolean hasWindowsAlive() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001121 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001122 // No need to loop through child windows as the answer should be the same as that of the
1123 // parent window.
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001124 if (!(mChildren.get(i)).mAppDied) {
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001125 return true;
1126 }
1127 }
1128 return false;
1129 }
1130
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001131 void setWillReplaceWindows(boolean animate) {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001132 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
1133 "Marking app token " + this + " with replacing windows.");
Robert Carra1eb4392015-12-10 12:43:51 -08001134
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001135 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001136 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001137 w.setWillReplaceWindow(animate);
Robert Carra1eb4392015-12-10 12:43:51 -08001138 }
Robert Carra1eb4392015-12-10 12:43:51 -08001139 }
1140
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001141 void setWillReplaceChildWindows() {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001142 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Marking app token " + this
Robert Carr23fa16b2016-01-13 13:19:58 -08001143 + " with replacing child windows.");
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001144 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001145 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001146 w.setWillReplaceChildWindows();
Robert Carr23fa16b2016-01-13 13:19:58 -08001147 }
1148 }
1149
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001150 void clearWillReplaceWindows() {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001151 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
1152 "Resetting app token " + this + " of replacing window marks.");
Chong Zhangf596cd52016-01-05 13:42:44 -08001153
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001154 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001155 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001156 w.clearWillReplaceWindow();
Chong Zhangf596cd52016-01-05 13:42:44 -08001157 }
1158 }
1159
Chong Zhang4d7369a2016-04-25 16:09:14 -07001160 void requestUpdateWallpaperIfNeeded() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001161 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001162 final WindowState w = mChildren.get(i);
Chong Zhang4d7369a2016-04-25 16:09:14 -07001163 w.requestUpdateWallpaperIfNeeded();
1164 }
1165 }
1166
Chong Zhangd78ddb42016-03-02 17:01:14 -08001167 boolean isRelaunching() {
1168 return mPendingRelaunchCount > 0;
1169 }
1170
Robert Carr68375192017-06-13 12:41:53 -07001171 boolean shouldFreezeBounds() {
1172 final Task task = getTask();
1173
1174 // For freeform windows, we can't freeze the bounds at the moment because this would make
1175 // the resizing unresponsive.
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001176 if (task == null || task.inFreeformWindowingMode()) {
Robert Carr68375192017-06-13 12:41:53 -07001177 return false;
1178 }
1179
1180 // We freeze the bounds while drag resizing to deal with the time between
1181 // the divider/drag handle being released, and the handling it's new
1182 // configuration. If we are relaunched outside of the drag resizing state,
1183 // we need to be careful not to do this.
1184 return getTask().isDragResizing();
1185 }
1186
Chong Zhangd78ddb42016-03-02 17:01:14 -08001187 void startRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001188 if (shouldFreezeBounds()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08001189 freezeBounds();
1190 }
Robert Carrd5c7dd62017-03-08 10:39:30 -08001191
1192 // In the process of tearing down before relaunching, the app will
1193 // try and clean up it's child surfaces. We need to prevent this from
1194 // happening, so we sever the children, transfering their ownership
1195 // from the client it-self to the parent surface (owned by us).
Robert Carr29daa922018-04-27 11:56:48 -07001196 detachChildren();
1197
1198 mPendingRelaunchCount++;
1199 }
1200
1201 void detachChildren() {
Robert Carrfd8e93b2018-05-10 13:40:25 -07001202 SurfaceControl.openTransaction();
Robert Carrd5c7dd62017-03-08 10:39:30 -08001203 for (int i = mChildren.size() - 1; i >= 0; i--) {
1204 final WindowState w = mChildren.get(i);
1205 w.mWinAnimator.detachChildren();
1206 }
Robert Carrfd8e93b2018-05-10 13:40:25 -07001207 SurfaceControl.closeTransaction();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001208 }
1209
1210 void finishRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001211 unfreezeBounds();
1212
Chong Zhangd78ddb42016-03-02 17:01:14 -08001213 if (mPendingRelaunchCount > 0) {
1214 mPendingRelaunchCount--;
Bryce Lee081554b2017-05-25 07:52:12 -07001215 } else {
1216 // Update keyguard flags upon finishing relaunch.
1217 checkKeyguardFlagsChanged();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001218 }
1219 }
1220
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001221 void clearRelaunching() {
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001222 if (mPendingRelaunchCount == 0) {
1223 return;
1224 }
Robert Carr68375192017-06-13 12:41:53 -07001225 unfreezeBounds();
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001226 mPendingRelaunchCount = 0;
1227 }
1228
Wale Ogunwale07bcab72016-10-14 15:30:09 -07001229 /**
1230 * Returns true if the new child window we are adding to this token is considered greater than
1231 * the existing child window in this token in terms of z-order.
1232 */
1233 @Override
1234 protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
1235 WindowState existingWindow) {
1236 final int type1 = newWindow.mAttrs.type;
1237 final int type2 = existingWindow.mAttrs.type;
1238
1239 // Base application windows should be z-ordered BELOW all other windows in the app token.
1240 if (type1 == TYPE_BASE_APPLICATION && type2 != TYPE_BASE_APPLICATION) {
1241 return false;
1242 } else if (type1 != TYPE_BASE_APPLICATION && type2 == TYPE_BASE_APPLICATION) {
1243 return true;
1244 }
1245
1246 // Starting windows should be z-ordered ABOVE all other windows in the app token.
1247 if (type1 == TYPE_APPLICATION_STARTING && type2 != TYPE_APPLICATION_STARTING) {
1248 return true;
1249 } else if (type1 != TYPE_APPLICATION_STARTING && type2 == TYPE_APPLICATION_STARTING) {
1250 return false;
1251 }
1252
1253 // Otherwise the new window is greater than the existing window.
1254 return true;
1255 }
1256
Tarandeep Singh69ab1042019-07-30 13:30:03 -07001257 /**
1258 * @return {@code true} if starting window is in app's hierarchy.
1259 */
1260 boolean hasStartingWindow() {
1261 if (startingDisplayed || mStartingData != null) {
1262 return true;
1263 }
1264 for (int i = mChildren.size() - 1; i >= 0; i--) {
1265 if (getChildAt(i).mAttrs.type == TYPE_APPLICATION_STARTING) {
1266 return true;
1267 }
1268 }
1269 return false;
1270 }
1271
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001272 @Override
Robert Carra1eb4392015-12-10 12:43:51 -08001273 void addWindow(WindowState w) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001274 super.addWindow(w);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001275
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001276 boolean gotReplacementWindow = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001277 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001278 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001279 gotReplacementWindow |= candidate.setReplacementWindowIfNeeded(w);
1280 }
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001281
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001282 // if we got a replacement window, reset the timeout to give drawing more time
1283 if (gotReplacementWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001284 mWmService.scheduleWindowReplacementTimeouts(this);
Robert Carra1eb4392015-12-10 12:43:51 -08001285 }
Jorim Jaggife762342016-10-13 14:33:27 +02001286 checkKeyguardFlagsChanged();
1287 }
1288
1289 @Override
1290 void removeChild(WindowState child) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001291 if (!mChildren.contains(child)) {
1292 // This can be true when testing.
1293 return;
1294 }
Jorim Jaggife762342016-10-13 14:33:27 +02001295 super.removeChild(child);
1296 checkKeyguardFlagsChanged();
Adrian Roos23df3a32018-03-15 15:41:13 +01001297 updateLetterboxSurface(child);
Robert Carra1eb4392015-12-10 12:43:51 -08001298 }
1299
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001300 private boolean waitingForReplacement() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001301 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001302 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001303 if (candidate.waitingForReplacement()) {
Robert Carra1eb4392015-12-10 12:43:51 -08001304 return true;
1305 }
1306 }
1307 return false;
1308 }
1309
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001310 void onWindowReplacementTimeout() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001311 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001312 (mChildren.get(i)).onWindowReplacementTimeout();
Robert Carra1eb4392015-12-10 12:43:51 -08001313 }
1314 }
1315
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001316 void reparent(Task task, int position) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001317 if (DEBUG_ADD_REMOVE) {
1318 Slog.i(TAG_WM, "reparent: moving app token=" + this
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001319 + " to task=" + task.mTaskId + " at " + position);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001320 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001321 if (task == null) {
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001322 throw new IllegalArgumentException("reparent: could not find task");
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001323 }
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001324 final Task currentTask = getTask();
1325 if (task == currentTask) {
Winson Chung30480042017-01-26 10:55:34 -08001326 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001327 "window token=" + this + " already child of task=" + currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001328 }
Bryce Lee6d410262017-02-28 15:30:17 -08001329
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001330 if (currentTask.mStack != task.mStack) {
Bryce Lee6d410262017-02-28 15:30:17 -08001331 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001332 "window token=" + this + " current task=" + currentTask
Bryce Lee6d410262017-02-28 15:30:17 -08001333 + " belongs to a different stack than " + task);
1334 }
1335
Winson Chung30480042017-01-26 10:55:34 -08001336 if (DEBUG_ADD_REMOVE) Slog.i(TAG, "reParentWindowToken: removing window token=" + this
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001337 + " from task=" + currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001338 final DisplayContent prevDisplayContent = getDisplayContent();
1339
Bryce Lee6d410262017-02-28 15:30:17 -08001340 mReparenting = true;
1341
Winson Chung30480042017-01-26 10:55:34 -08001342 getParent().removeChild(this);
1343 task.addChild(this, position);
1344
Bryce Lee6d410262017-02-28 15:30:17 -08001345 mReparenting = false;
1346
Winson Chung30480042017-01-26 10:55:34 -08001347 // Relayout display(s).
1348 final DisplayContent displayContent = task.getDisplayContent();
1349 displayContent.setLayoutNeeded();
1350 if (prevDisplayContent != displayContent) {
1351 onDisplayChanged(displayContent);
1352 prevDisplayContent.setLayoutNeeded();
1353 }
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001354 getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
Winson Chung30480042017-01-26 10:55:34 -08001355 }
1356
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001357 @Override
1358 void onDisplayChanged(DisplayContent dc) {
1359 DisplayContent prevDc = mDisplayContent;
1360 super.onDisplayChanged(dc);
Evan Roskyb1e75f72019-04-26 20:23:26 -07001361 if (prevDc == null || prevDc == mDisplayContent) {
Evan Rosky25b56192019-02-06 16:10:56 -08001362 return;
1363 }
Wale Ogunwaleb8e6b632019-06-28 15:19:25 +00001364
1365 if (prevDc.mOpeningApps.remove(this)) {
1366 // Transfer opening transition to new display.
1367 mDisplayContent.mOpeningApps.add(this);
1368 mDisplayContent.prepareAppTransition(prevDc.mAppTransition.getAppTransition(), true);
1369 mDisplayContent.executeAppTransition();
1370 }
1371
1372 if (prevDc.mChangingApps.remove(this)) {
Evan Rosky25b56192019-02-06 16:10:56 -08001373 // This gets called *after* the AppWindowToken has been reparented to the new display.
1374 // That reparenting resulted in this window changing modes (eg. FREEFORM -> FULLSCREEN),
1375 // so this token is now "frozen" while waiting for the animation to start on prevDc
1376 // (which will be cancelled since the window is no-longer a child). However, since this
1377 // is no longer a child of prevDc, this won't be notified of the cancelled animation,
1378 // so we need to cancel the change transition here.
1379 clearChangeLeash(getPendingTransaction(), true /* cancel */);
1380 }
Wale Ogunwaleb8e6b632019-06-28 15:19:25 +00001381 prevDc.mClosingApps.remove(this);
1382
Evan Rosky25b56192019-02-06 16:10:56 -08001383 if (prevDc.mFocusedApp == this) {
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001384 prevDc.setFocusedApp(null);
lumarkbf844642018-11-23 17:11:36 +08001385 final TaskStack stack = dc.getTopStack();
1386 if (stack != null) {
1387 final Task task = stack.getTopChild();
1388 if (task != null && task.getTopChild() == this) {
1389 dc.setFocusedApp(this);
1390 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001391 }
1392 }
Riddle Hsu192fe762019-01-15 23:41:57 +08001393
Evan Roskyb1e75f72019-04-26 20:23:26 -07001394 if (mLetterbox != null) {
Riddle Hsu192fe762019-01-15 23:41:57 +08001395 mLetterbox.onMovedToDisplay(mDisplayContent.getDisplayId());
1396 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001397 }
1398
Jorim Jaggi0429f352015-12-22 16:29:16 +01001399 /**
1400 * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds
1401 * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even
1402 * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen
1403 * with a queue.
1404 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001405 private void freezeBounds() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001406 final Task task = getTask();
1407 mFrozenBounds.offer(new Rect(task.mPreparedFrozenBounds));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001408
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001409 if (task.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001410 // We didn't call prepareFreezingBounds on the task, so use the current value.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001411 mFrozenMergedConfig.offer(new Configuration(task.getConfiguration()));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001412 } else {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001413 mFrozenMergedConfig.offer(new Configuration(task.mPreparedFrozenMergedConfig));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001414 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001415 // Calling unset() to make it equal to Configuration.EMPTY.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001416 task.mPreparedFrozenMergedConfig.unset();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001417 }
1418
1419 /**
1420 * Unfreezes the previously frozen bounds. See {@link #freezeBounds}.
1421 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001422 private void unfreezeBounds() {
Robert Carr68375192017-06-13 12:41:53 -07001423 if (mFrozenBounds.isEmpty()) {
1424 return;
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001425 }
Robert Carr68375192017-06-13 12:41:53 -07001426 mFrozenBounds.remove();
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001427 if (!mFrozenMergedConfig.isEmpty()) {
1428 mFrozenMergedConfig.remove();
1429 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001430 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001431 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001432 win.onUnfreezeBounds();
Jorim Jaggi4846ee32016-01-07 17:39:12 +01001433 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001434 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001435 }
1436
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001437 void setAppLayoutChanges(int changes, String reason) {
1438 if (!mChildren.isEmpty()) {
1439 final DisplayContent dc = getDisplayContent();
1440 dc.pendingLayoutChanges |= changes;
1441 if (DEBUG_LAYOUT_REPEATS) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001442 mWmService.mWindowPlacerLocked.debugLayoutRepeats(reason, dc.pendingLayoutChanges);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001443 }
1444 }
1445 }
1446
1447 void removeReplacedWindowIfNeeded(WindowState replacement) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001448 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001449 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001450 if (win.removeReplacedWindowIfNeeded(replacement)) {
1451 return;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001452 }
1453 }
1454 }
1455
1456 void startFreezingScreen() {
1457 if (DEBUG_ORIENTATION) logWithStack(TAG, "Set freezing of " + appToken + ": hidden="
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001458 + isHidden() + " freezing=" + mFreezingScreen + " hiddenRequested="
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001459 + hiddenRequested);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001460 if (!hiddenRequested) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001461 if (!mFreezingScreen) {
1462 mFreezingScreen = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001463 mWmService.registerAppFreezeListener(this);
1464 mWmService.mAppsFreezingScreen++;
1465 if (mWmService.mAppsFreezingScreen == 1) {
1466 mWmService.startFreezingDisplayLocked(0, 0, getDisplayContent());
1467 mWmService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
1468 mWmService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001469 }
1470 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001471 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001472 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001473 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001474 w.onStartFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001475 }
1476 }
1477 }
1478
1479 void stopFreezingScreen(boolean unfreezeSurfaceNow, boolean force) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001480 if (!mFreezingScreen) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001481 return;
1482 }
1483 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + this + " force=" + force);
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001484 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001485 boolean unfrozeWindows = false;
1486 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001487 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001488 unfrozeWindows |= w.onStopFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001489 }
1490 if (force || unfrozeWindows) {
1491 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "No longer freezing: " + this);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001492 mFreezingScreen = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001493 mWmService.unregisterAppFreezeListener(this);
1494 mWmService.mAppsFreezingScreen--;
1495 mWmService.mLastFinishedFreezeSource = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001496 }
1497 if (unfreezeSurfaceNow) {
1498 if (unfrozeWindows) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001499 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001500 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001501 mWmService.stopFreezingDisplayLocked();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001502 }
1503 }
1504
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001505 @Override
1506 public void onAppFreezeTimeout() {
1507 Slog.w(TAG_WM, "Force clearing freeze: " + this);
1508 stopFreezingScreen(true, true);
1509 }
1510
Jorim Jaggi60f9c972018-02-01 19:21:07 +01001511 /**
1512 * Tries to transfer the starting window from a token that's above ourselves in the task but
1513 * not visible anymore. This is a common scenario apps use: Trampoline activity T start main
1514 * activity M in the same task. Now, when reopening the task, T starts on top of M but then
1515 * immediately finishes after, so we have to transfer T to M.
1516 */
1517 void transferStartingWindowFromHiddenAboveTokenIfNeeded() {
1518 final Task task = getTask();
1519 for (int i = task.mChildren.size() - 1; i >= 0; i--) {
1520 final AppWindowToken fromToken = task.mChildren.get(i);
1521 if (fromToken == this) {
1522 return;
1523 }
1524 if (fromToken.hiddenRequested && transferStartingWindow(fromToken.token)) {
1525 return;
1526 }
1527 }
1528 }
1529
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001530 boolean transferStartingWindow(IBinder transferFrom) {
Wale Ogunwale02319a62016-09-26 15:21:22 -07001531 final AppWindowToken fromToken = getDisplayContent().getAppWindowToken(transferFrom);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001532 if (fromToken == null) {
1533 return false;
1534 }
1535
1536 final WindowState tStartingWindow = fromToken.startingWindow;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08001537 if (tStartingWindow != null && fromToken.startingSurface != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001538 // In this case, the starting icon has already been displayed, so start
1539 // letting windows get shown immediately without any more transitions.
lumark588a3e82018-07-20 18:53:54 +08001540 getDisplayContent().mSkipAppTransitionAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001541
1542 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Moving existing starting " + tStartingWindow
1543 + " from " + fromToken + " to " + this);
1544
1545 final long origId = Binder.clearCallingIdentity();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001546 try {
1547 // Transfer the starting window over to the new token.
chaviwa8f07a72019-05-01 16:25:39 -07001548 mStartingData = fromToken.mStartingData;
Peter Visontay3556a3b2017-11-01 17:23:17 +00001549 startingSurface = fromToken.startingSurface;
1550 startingDisplayed = fromToken.startingDisplayed;
1551 fromToken.startingDisplayed = false;
1552 startingWindow = tStartingWindow;
1553 reportedVisible = fromToken.reportedVisible;
chaviwa8f07a72019-05-01 16:25:39 -07001554 fromToken.mStartingData = null;
Peter Visontay3556a3b2017-11-01 17:23:17 +00001555 fromToken.startingSurface = null;
1556 fromToken.startingWindow = null;
1557 fromToken.startingMoved = true;
1558 tStartingWindow.mToken = this;
1559 tStartingWindow.mAppToken = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001560
Peter Visontay3556a3b2017-11-01 17:23:17 +00001561 if (DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
1562 "Removing starting " + tStartingWindow + " from " + fromToken);
1563 fromToken.removeChild(tStartingWindow);
1564 fromToken.postWindowRemoveStartingWindowCleanup(tStartingWindow);
1565 fromToken.mHiddenSetFromTransferredStartingWindow = false;
1566 addWindow(tStartingWindow);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001567
Peter Visontay3556a3b2017-11-01 17:23:17 +00001568 // Propagate other interesting state between the tokens. If the old token is displayed,
1569 // we should immediately force the new one to be displayed. If it is animating, we need
1570 // to move that animation to the new one.
1571 if (fromToken.allDrawn) {
1572 allDrawn = true;
1573 deferClearAllDrawn = fromToken.deferClearAllDrawn;
1574 }
1575 if (fromToken.firstWindowDrawn) {
1576 firstWindowDrawn = true;
1577 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001578 if (!fromToken.isHidden()) {
1579 setHidden(false);
Peter Visontay3556a3b2017-11-01 17:23:17 +00001580 hiddenRequested = false;
1581 mHiddenSetFromTransferredStartingWindow = true;
1582 }
1583 setClientHidden(fromToken.mClientHidden);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001584
Jorim Jaggi980c9de2017-11-17 01:41:37 +01001585 transferAnimation(fromToken);
1586
1587 // When transferring an animation, we no longer need to apply an animation to the
Tiger Huangc9d0d002019-05-29 22:55:29 +08001588 // the token we transfer the animation over. Thus, set this flag to indicate we've
1589 // transferred the animation.
1590 mUseTransferredAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001591
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001592 mWmService.updateFocusedWindowLocked(
Peter Visontay3556a3b2017-11-01 17:23:17 +00001593 UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/);
1594 getDisplayContent().setLayoutNeeded();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001595 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001596 } finally {
1597 Binder.restoreCallingIdentity(origId);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001598 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001599 return true;
chaviwa8f07a72019-05-01 16:25:39 -07001600 } else if (fromToken.mStartingData != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001601 // The previous app was getting ready to show a
1602 // starting window, but hasn't yet done so. Steal it!
1603 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
1604 "Moving pending starting from " + fromToken + " to " + this);
chaviwa8f07a72019-05-01 16:25:39 -07001605 mStartingData = fromToken.mStartingData;
1606 fromToken.mStartingData = null;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001607 fromToken.startingMoved = true;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001608 scheduleAddStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001609 return true;
1610 }
1611
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001612 // TODO: Transfer thumbnail
1613
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001614 return false;
1615 }
1616
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001617 boolean isLastWindow(WindowState win) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001618 return mChildren.size() == 1 && mChildren.get(0) == win;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001619 }
1620
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001621 @Override
1622 void onAppTransitionDone() {
1623 sendingToBottom = false;
1624 }
1625
Wale Ogunwale51362492016-09-08 17:49:17 -07001626 /**
1627 * We override because this class doesn't want its children affecting its reported orientation
1628 * in anyway.
1629 */
1630 @Override
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001631 int getOrientation(int candidate) {
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001632 if (candidate == SCREEN_ORIENTATION_BEHIND) {
1633 // Allow app to specify orientation regardless of its visibility state if the current
1634 // candidate want us to use orientation behind. I.e. the visible app on-top of this one
1635 // wants us to use the orientation of the app behind it.
1636 return mOrientation;
1637 }
1638
Bryce Lee61fbcbc2017-03-10 14:14:03 -08001639 // The {@link AppWindowToken} should only specify an orientation when it is not closing or
1640 // going to the bottom. Allowing closing {@link AppWindowToken} to participate can lead to
1641 // an Activity in another task being started in the wrong orientation during the transition.
lumark588a3e82018-07-20 18:53:54 +08001642 if (!(sendingToBottom || getDisplayContent().mClosingApps.contains(this))
1643 && (isVisible() || getDisplayContent().mOpeningApps.contains(this))) {
Bryce Leea163b762017-01-24 11:05:01 -08001644 return mOrientation;
Wale Ogunwale51362492016-09-08 17:49:17 -07001645 }
Bryce Leea163b762017-01-24 11:05:01 -08001646
1647 return SCREEN_ORIENTATION_UNSET;
Wale Ogunwale51362492016-09-08 17:49:17 -07001648 }
1649
Wale Ogunwaleb198b742016-12-01 08:44:09 -08001650 /** Returns the app's preferred orientation regardless of its currently visibility state. */
1651 int getOrientationIgnoreVisibility() {
1652 return mOrientation;
1653 }
1654
Riddle Hsub398da32019-01-21 21:48:16 +08001655 /** @return {@code true} if the compatibility bounds is taking effect. */
1656 boolean inSizeCompatMode() {
1657 return mSizeCompatBounds != null;
1658 }
1659
1660 @Override
1661 float getSizeCompatScale() {
1662 return inSizeCompatMode() ? mSizeCompatScale : super.getSizeCompatScale();
1663 }
1664
1665 /**
1666 * @return Non-empty bounds if the activity has override bounds.
1667 * @see ActivityRecord#resolveOverrideConfiguration(Configuration)
1668 */
1669 Rect getResolvedOverrideBounds() {
1670 // Get bounds from resolved override configuration because it is computed with orientation.
1671 return getResolvedOverrideConfiguration().windowConfiguration.getBounds();
1672 }
1673
Craig Mautnerdbb79912012-03-01 18:59:14 -08001674 @Override
Winson Chunge55c0192017-08-24 14:50:48 -07001675 public void onConfigurationChanged(Configuration newParentConfig) {
1676 final int prevWinMode = getWindowingMode();
Evan Rosky2289ba12018-11-19 18:28:18 -08001677 mTmpPrevBounds.set(getBounds());
Winson Chunge55c0192017-08-24 14:50:48 -07001678 super.onConfigurationChanged(newParentConfig);
Riddle Hsub398da32019-01-21 21:48:16 +08001679
1680 final Task task = getTask();
1681 final Rect overrideBounds = getResolvedOverrideBounds();
1682 if (task != null && !overrideBounds.isEmpty()
1683 // If the changes come from change-listener, the incoming parent configuration is
1684 // still the old one. Make sure their orientations are the same to reduce computing
1685 // the compatibility bounds for the intermediate state.
Riddle Hsu04164182019-03-07 18:03:27 +08001686 && (task.mTaskRecord == null || task.mTaskRecord
1687 .getConfiguration().orientation == newParentConfig.orientation)) {
Riddle Hsub398da32019-01-21 21:48:16 +08001688 final Rect taskBounds = task.getBounds();
1689 // Since we only center the activity horizontally, if only the fixed height is smaller
1690 // than its container, the override bounds don't need to take effect.
1691 if ((overrideBounds.width() != taskBounds.width()
1692 || overrideBounds.height() > taskBounds.height())) {
1693 calculateCompatBoundsTransformation(newParentConfig);
1694 updateSurfacePosition();
1695 } else if (mSizeCompatBounds != null) {
1696 mSizeCompatBounds = null;
1697 mSizeCompatScale = 1f;
1698 updateSurfacePosition();
1699 }
1700 }
1701
Winson Chunge55c0192017-08-24 14:50:48 -07001702 final int winMode = getWindowingMode();
1703
1704 if (prevWinMode == winMode) {
1705 return;
1706 }
1707
1708 if (prevWinMode != WINDOWING_MODE_UNDEFINED && winMode == WINDOWING_MODE_PINNED) {
1709 // Entering PiP from fullscreen, reset the snap fraction
1710 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(this);
Winson Chung82267ce2018-04-06 16:38:26 -07001711 } else if (prevWinMode == WINDOWING_MODE_PINNED && winMode != WINDOWING_MODE_UNDEFINED
1712 && !isHidden()) {
Winson Chunge55c0192017-08-24 14:50:48 -07001713 // Leaving PiP to fullscreen, save the snap fraction based on the pre-animation bounds
1714 // for the next re-entry into PiP (assuming the activity is not hidden or destroyed)
1715 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
1716 if (pinnedStack != null) {
Winson Chung8efa1652018-06-06 09:34:23 -07001717 final Rect stackBounds;
1718 if (pinnedStack.lastAnimatingBoundsWasToFullscreen()) {
1719 // We are animating the bounds, use the pre-animation bounds to save the snap
1720 // fraction
1721 stackBounds = pinnedStack.mPreAnimationBounds;
1722 } else {
1723 // We skip the animation if the fullscreen configuration is not compatible, so
1724 // use the current bounds to calculate the saved snap fraction instead
1725 // (see PinnedActivityStack.skipResizeAnimation())
1726 stackBounds = mTmpRect;
1727 pinnedStack.getBounds(stackBounds);
1728 }
Winson Chunge55c0192017-08-24 14:50:48 -07001729 mDisplayContent.mPinnedStackControllerLocked.saveReentrySnapFraction(this,
Winson Chung8efa1652018-06-06 09:34:23 -07001730 stackBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001731 }
Evan Rosky2289ba12018-11-19 18:28:18 -08001732 } else if (shouldStartChangeTransition(prevWinMode, winMode)) {
1733 initializeChangeTransition(mTmpPrevBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001734 }
1735 }
1736
Evan Rosky2289ba12018-11-19 18:28:18 -08001737 private boolean shouldStartChangeTransition(int prevWinMode, int newWinMode) {
Evan Rosky25b56192019-02-06 16:10:56 -08001738 if (mWmService.mDisableTransitionAnimation
1739 || !isVisible()
1740 || getDisplayContent().mAppTransition.isTransitionSet()
1741 || getSurfaceControl() == null) {
Evan Rosky2289ba12018-11-19 18:28:18 -08001742 return false;
1743 }
1744 // Only do an animation into and out-of freeform mode for now. Other mode
1745 // transition animations are currently handled by system-ui.
1746 return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
1747 }
1748
1749 /**
1750 * Initializes a change transition. Because the app is visible already, there is a small period
1751 * of time where the user can see the app content/window update before the transition starts.
1752 * To prevent this, we immediately take a snapshot and place the app/snapshot into a leash which
1753 * "freezes" the location/crop until the transition starts.
1754 * <p>
1755 * Here's a walk-through of the process:
1756 * 1. Create a temporary leash ("interim-change-leash") and reparent the app to it.
1757 * 2. Set the temporary leash's position/crop to the current state.
1758 * 3. Create a snapshot and place that at the top of the leash to cover up content changes.
1759 * 4. Once the transition is ready, it will reparent the app to the animation leash.
1760 * 5. Detach the interim-change-leash.
1761 */
1762 private void initializeChangeTransition(Rect startBounds) {
1763 mDisplayContent.prepareAppTransition(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
1764 false /* alwaysKeepCurrent */, 0, false /* forceOverride */);
1765 mDisplayContent.mChangingApps.add(this);
1766 mTransitStartRect.set(startBounds);
1767
1768 final SurfaceControl.Builder builder = makeAnimationLeash()
1769 .setParent(getAnimationLeashParent())
1770 .setName(getSurfaceControl() + " - interim-change-leash");
1771 mTransitChangeLeash = builder.build();
1772 Transaction t = getPendingTransaction();
1773 t.setWindowCrop(mTransitChangeLeash, startBounds.width(), startBounds.height());
1774 t.setPosition(mTransitChangeLeash, startBounds.left, startBounds.top);
1775 t.show(mTransitChangeLeash);
1776 t.reparent(getSurfaceControl(), mTransitChangeLeash);
1777 onAnimationLeashCreated(t, mTransitChangeLeash);
1778
Evan Rosky966759f2019-01-15 10:33:58 -08001779 // Skip creating snapshot if this transition is controlled by a remote animator which
1780 // doesn't need it.
1781 ArraySet<Integer> activityTypes = new ArraySet<>();
1782 activityTypes.add(getActivityType());
1783 RemoteAnimationAdapter adapter =
1784 mDisplayContent.mAppTransitionController.getRemoteAnimationOverride(
1785 this, TRANSIT_TASK_CHANGE_WINDOWING_MODE, activityTypes);
1786 if (adapter != null && !adapter.getChangeNeedsSnapshot()) {
1787 return;
1788 }
1789
Evan Rosky08e20932019-05-14 10:54:07 -07001790 Task task = getTask();
1791 if (mThumbnail == null && task != null && !hasCommittedReparentToAnimationLeash()) {
1792 SurfaceControl.ScreenshotGraphicBuffer snapshot =
1793 mWmService.mTaskSnapshotController.createTaskSnapshot(
1794 task, 1 /* scaleFraction */);
Yunfan Chendcb1fcf2019-02-07 19:08:41 +09001795 if (snapshot != null) {
Vishnu Nair33197392019-08-30 10:29:37 -07001796 mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory, t, this,
1797 snapshot.getGraphicBuffer(), true /* relative */);
Yunfan Chendcb1fcf2019-02-07 19:08:41 +09001798 }
Evan Rosky2289ba12018-11-19 18:28:18 -08001799 }
1800 }
1801
1802 boolean isInChangeTransition() {
Evan Roskyec9488c2019-03-01 19:32:12 -08001803 return mTransitChangeLeash != null || AppTransition.isChangeTransit(mTransit);
Evan Rosky2289ba12018-11-19 18:28:18 -08001804 }
1805
Evan Rosky966759f2019-01-15 10:33:58 -08001806 @VisibleForTesting
1807 AppWindowThumbnail getThumbnail() {
1808 return mThumbnail;
1809 }
1810
Riddle Hsub398da32019-01-21 21:48:16 +08001811 /**
1812 * Calculates the scale and offset to horizontal center the size compatibility bounds into the
1813 * region which is available to application.
1814 */
1815 private void calculateCompatBoundsTransformation(Configuration newParentConfig) {
1816 final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds();
Riddle Hsu74826262019-04-17 14:57:42 +08001817 final Rect parentBounds = newParentConfig.windowConfiguration.getBounds();
1818 final Rect viewportBounds = parentAppBounds != null ? parentAppBounds : parentBounds;
Riddle Hsu04164182019-03-07 18:03:27 +08001819 final Rect appBounds = getWindowConfiguration().getAppBounds();
1820 final Rect contentBounds = appBounds != null ? appBounds : getResolvedOverrideBounds();
Riddle Hsub398da32019-01-21 21:48:16 +08001821 final float contentW = contentBounds.width();
1822 final float contentH = contentBounds.height();
1823 final float viewportW = viewportBounds.width();
1824 final float viewportH = viewportBounds.height();
1825 // Only allow to scale down.
1826 mSizeCompatScale = (contentW <= viewportW && contentH <= viewportH)
1827 ? 1 : Math.min(viewportW / contentW, viewportH / contentH);
1828 final int offsetX = (int) ((viewportW - contentW * mSizeCompatScale + 1) * 0.5f)
1829 + viewportBounds.left;
1830
1831 if (mSizeCompatBounds == null) {
1832 mSizeCompatBounds = new Rect();
1833 }
1834 mSizeCompatBounds.set(contentBounds);
1835 mSizeCompatBounds.offsetTo(0, 0);
1836 mSizeCompatBounds.scale(mSizeCompatScale);
Riddle Hsu74826262019-04-17 14:57:42 +08001837 // Ensure to align the top with the parent.
1838 mSizeCompatBounds.top = parentBounds.top;
Riddle Hsu04164182019-03-07 18:03:27 +08001839 // The decor inset is included in height.
1840 mSizeCompatBounds.bottom += viewportBounds.top;
Riddle Hsub398da32019-01-21 21:48:16 +08001841 mSizeCompatBounds.left += offsetX;
1842 mSizeCompatBounds.right += offsetX;
1843 }
1844
1845 @Override
1846 public Rect getBounds() {
1847 if (mSizeCompatBounds != null) {
1848 return mSizeCompatBounds;
1849 }
1850 return super.getBounds();
1851 }
1852
1853 @Override
1854 public boolean matchParentBounds() {
1855 if (super.matchParentBounds()) {
1856 return true;
1857 }
1858 // An activity in size compatibility mode may have override bounds which equals to its
1859 // parent bounds, so the exact bounds should also be checked.
1860 final WindowContainer parent = getParent();
1861 return parent == null || parent.getBounds().equals(getResolvedOverrideBounds());
1862 }
1863
Winson Chunge55c0192017-08-24 14:50:48 -07001864 @Override
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001865 void checkAppWindowsReadyToShow() {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001866 if (allDrawn == mLastAllDrawn) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001867 return;
1868 }
1869
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001870 mLastAllDrawn = allDrawn;
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001871 if (!allDrawn) {
1872 return;
1873 }
1874
1875 // The token has now changed state to having all windows shown... what to do, what to do?
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001876 if (mFreezingScreen) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001877 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001878 stopFreezingScreen(false, true);
1879 if (DEBUG_ORIENTATION) Slog.i(TAG,
1880 "Setting mOrientationChangeComplete=true because wtoken " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001881 + " numInteresting=" + mNumInterestingWindows + " numDrawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001882 // This will set mOrientationChangeComplete and cause a pass through layout.
1883 setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001884 "checkAppWindowsReadyToShow: freezingScreen");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001885 } else {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001886 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001887
1888 // We can now show all of the drawn windows!
lumark588a3e82018-07-20 18:53:54 +08001889 if (!getDisplayContent().mOpeningApps.contains(this) && canShowWindows()) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001890 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001891 }
1892 }
1893 }
1894
Matthew Ng5d23afa2017-06-21 16:16:24 -07001895 /**
Bryce Leed390deb2017-06-22 13:14:28 -07001896 * Returns whether the drawn window states of this {@link AppWindowToken} has considered every
1897 * child {@link WindowState}. A child is considered if it has been passed into
1898 * {@link #updateDrawnWindowStates(WindowState)} after being added. This is used to determine
1899 * whether states, such as {@code allDrawn}, can be set, which relies on state variables such as
1900 * {@code mNumInterestingWindows}, which depend on all {@link WindowState}s being considered.
1901 *
1902 * @return {@code true} If all children have been considered, {@code false}.
1903 */
1904 private boolean allDrawnStatesConsidered() {
Bryce Lee6311c4b2017-07-06 14:09:29 -07001905 for (int i = mChildren.size() - 1; i >= 0; --i) {
1906 final WindowState child = mChildren.get(i);
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001907 if (child.mightAffectAllDrawn() && !child.getDrawnStateEvaluated()) {
Bryce Leed390deb2017-06-22 13:14:28 -07001908 return false;
1909 }
1910 }
1911 return true;
1912 }
1913
1914 /**
Matthew Ng5d23afa2017-06-21 16:16:24 -07001915 * Determines if the token has finished drawing. This should only be called from
1916 * {@link DisplayContent#applySurfaceChangesTransaction}
1917 */
Matthew Ng498c71d2017-04-18 13:55:45 -07001918 void updateAllDrawn() {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001919 if (!allDrawn) {
Matthew Ng498c71d2017-04-18 13:55:45 -07001920 // Number of drawn windows can be less when a window is being relaunched, wait for
Bryce Leed390deb2017-06-22 13:14:28 -07001921 // all windows to be launched and drawn for this token be considered all drawn.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001922 final int numInteresting = mNumInterestingWindows;
Bryce Leed390deb2017-06-22 13:14:28 -07001923
1924 // We must make sure that all present children have been considered (determined by
1925 // {@link #allDrawnStatesConsidered}) before evaluating whether everything has been
1926 // drawn.
1927 if (numInteresting > 0 && allDrawnStatesConsidered()
1928 && mNumDrawnWindows >= numInteresting && !isRelaunching()) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001929 if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawn: " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001930 + " interesting=" + numInteresting + " drawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001931 allDrawn = true;
1932 // Force an additional layout pass where
1933 // WindowStateAnimator#commitFinishDrawingLocked() will call performShowLocked().
Matthew Ng498c71d2017-04-18 13:55:45 -07001934 if (mDisplayContent != null) {
1935 mDisplayContent.setLayoutNeeded();
1936 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001937 mWmService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
Robert Carrecc06b32017-04-18 14:25:10 -07001938
Winson Chunge7ba6862017-05-24 12:13:33 -07001939 // Notify the pinned stack upon all windows drawn. If there was an animation in
1940 // progress then this signal will resume that animation.
Wale Ogunwale61911492017-10-11 08:50:50 -07001941 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
Winson Chunge7ba6862017-05-24 12:13:33 -07001942 if (pinnedStack != null) {
1943 pinnedStack.onAllWindowsDrawn();
Robert Carrecc06b32017-04-18 14:25:10 -07001944 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001945 }
1946 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001947 }
1948
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001949 boolean keyDispatchingTimedOut(String reason, int windowPid) {
1950 return mActivityRecord != null && mActivityRecord.keyDispatchingTimedOut(reason, windowPid);
1951 }
1952
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001953 /**
1954 * Updated this app token tracking states for interesting and drawn windows based on the window.
1955 *
1956 * @return Returns true if the input window is considered interesting and drawn while all the
1957 * windows in this app token where not considered drawn as of the last pass.
1958 */
1959 boolean updateDrawnWindowStates(WindowState w) {
Bryce Leed390deb2017-06-22 13:14:28 -07001960 w.setDrawnStateEvaluated(true /*evaluated*/);
1961
Jorim Jaggie4b0f282017-05-17 15:10:29 +02001962 if (DEBUG_STARTING_WINDOW_VERBOSE && w == startingWindow) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001963 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + w.isOnScreen()
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001964 + " allDrawn=" + allDrawn + " freezingScreen=" + mFreezingScreen);
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001965 }
1966
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001967 if (allDrawn && !mFreezingScreen) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001968 return false;
1969 }
1970
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001971 if (mLastTransactionSequence != mWmService.mTransactionSequence) {
1972 mLastTransactionSequence = mWmService.mTransactionSequence;
Matthew Ng53e66b22018-01-12 17:13:13 -08001973 mNumDrawnWindows = 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001974 startingDisplayed = false;
Matthew Ng53e66b22018-01-12 17:13:13 -08001975
1976 // There is the main base application window, even if it is exiting, wait for it
1977 mNumInterestingWindows = findMainWindow(false /* includeStartingApp */) != null ? 1 : 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001978 }
1979
1980 final WindowStateAnimator winAnimator = w.mWinAnimator;
1981
1982 boolean isInterestingAndDrawn = false;
1983
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001984 if (!allDrawn && w.mightAffectAllDrawn()) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001985 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
1986 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001987 + ", isAnimationSet=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001988 if (!w.isDrawnLw()) {
1989 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController
chaviw15ad49f2019-04-24 15:05:39 -07001990 + " pv=" + w.isVisibleByPolicy()
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001991 + " mDrawState=" + winAnimator.drawStateToString()
1992 + " ph=" + w.isParentWindowHidden() + " th=" + hiddenRequested
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001993 + " a=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001994 }
1995 }
1996
1997 if (w != startingWindow) {
1998 if (w.isInteresting()) {
Matthew Ng53e66b22018-01-12 17:13:13 -08001999 // Add non-main window as interesting since the main app has already been added
2000 if (findMainWindow(false /* includeStartingApp */) != w) {
2001 mNumInterestingWindows++;
2002 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002003 if (w.isDrawnLw()) {
2004 mNumDrawnWindows++;
2005
2006 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, "tokenMayBeDrawn: "
2007 + this + " w=" + w + " numInteresting=" + mNumInterestingWindows
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002008 + " freezingScreen=" + mFreezingScreen
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002009 + " mAppFreezing=" + w.mAppFreezing);
2010
2011 isInterestingAndDrawn = true;
2012 }
2013 }
2014 } else if (w.isDrawnLw()) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002015 if (mActivityRecord != null) {
2016 mActivityRecord.onStartingWindowDrawn(SystemClock.uptimeMillis());
Jorim Jaggi3878ca32017-02-02 17:13:05 -08002017 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002018 startingDisplayed = true;
2019 }
2020 }
2021
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002022 return isInterestingAndDrawn;
2023 }
2024
Adrian Roos23df3a32018-03-15 15:41:13 +01002025 void layoutLetterbox(WindowState winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002026 final WindowState w = findMainWindow();
Adrian Roosf93b6d22018-03-21 13:48:26 +01002027 if (w == null || winHint != null && w != winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002028 return;
2029 }
Jorim Jaggia32da382018-03-28 18:01:22 +02002030 final boolean surfaceReady = w.isDrawnLw() // Regular case
Adrian Roosf93b6d22018-03-21 13:48:26 +01002031 || w.mWinAnimator.mSurfaceDestroyDeferred // The preserved surface is still ready.
2032 || w.isDragResizeChanged(); // Waiting for relayoutWindow to call preserveSurface.
Jorim Jaggi4981f152019-03-26 18:58:45 +01002033 final boolean needsLetterbox = surfaceReady && w.isLetterboxedAppWindow() && fillsParent();
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002034 if (needsLetterbox) {
2035 if (mLetterbox == null) {
Vishnu Nair33197392019-08-30 10:29:37 -07002036 mLetterbox = new Letterbox(() -> makeChildSurface(null),
2037 mWmService.mTransactionFactory);
Riddle Hsu192fe762019-01-15 23:41:57 +08002038 mLetterbox.attachInput(w);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002039 }
Adrian Roos7af9d972018-11-30 15:26:27 +01002040 getPosition(mTmpPoint);
Evan Rosky67c15642019-04-24 13:17:28 -07002041 // Get the bounds of the "space-to-fill". In multi-window mode, the task-level
2042 // represents this. In fullscreen-mode, the stack does (since the orientation letterbox
2043 // is also applied to the task).
2044 Rect spaceToFill = (inMultiWindowMode() || getStack() == null)
2045 ? getTask().getDisplayedBounds() : getStack().getDisplayedBounds();
Evan Rosky4fb1e912019-03-06 13:54:43 -08002046 mLetterbox.layout(spaceToFill, w.getFrameLw(), mTmpPoint);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002047 } else if (mLetterbox != null) {
Adrian Roos23df3a32018-03-15 15:41:13 +01002048 mLetterbox.hide();
2049 }
2050 }
2051
2052 void updateLetterboxSurface(WindowState winHint) {
2053 final WindowState w = findMainWindow();
2054 if (w != winHint && winHint != null && w != null) {
2055 return;
2056 }
2057 layoutLetterbox(winHint);
2058 if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) {
Tiger Huanged6794e2019-05-07 20:07:59 +08002059 mLetterbox.applySurfaceChanges(getPendingTransaction());
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002060 }
2061 }
2062
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07002063 @Override
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002064 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002065 // For legacy reasons we process the TaskStack.mExitingAppTokens first in DisplayContent
2066 // before the non-exiting app tokens. So, we skip the exiting app tokens here.
2067 // TODO: Investigate if we need to continue to do this or if we can just process them
2068 // in-order.
2069 if (mIsExiting && !waitingForReplacement()) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002070 return false;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002071 }
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002072 return forAllWindowsUnchecked(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002073 }
2074
lumark588a3e82018-07-20 18:53:54 +08002075 @Override
2076 void forAllAppWindows(Consumer<AppWindowToken> callback) {
2077 callback.accept(this);
2078 }
2079
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002080 boolean forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback,
2081 boolean traverseTopToBottom) {
2082 return super.forAllWindows(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002083 }
2084
2085 @Override
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002086 AppWindowToken asAppWindowToken() {
2087 // I am an app window token!
2088 return this;
2089 }
2090
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002091 boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
2092 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
2093 IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
2094 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
2095 // If the display is frozen, we won't do anything until the actual window is
2096 // displayed so there is no reason to put in the starting window.
2097 if (!okToDisplay()) {
2098 return false;
2099 }
2100
chaviwa8f07a72019-05-01 16:25:39 -07002101 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002102 return false;
2103 }
2104
2105 final WindowState mainWin = findMainWindow();
2106 if (mainWin != null && mainWin.mWinAnimator.getShown()) {
2107 // App already has a visible window...why would you want a starting window?
2108 return false;
2109 }
2110
2111 final ActivityManager.TaskSnapshot snapshot =
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002112 mWmService.mTaskSnapshotController.getSnapshot(
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002113 getTask().mTaskId, getTask().mUserId,
2114 false /* restoreFromDisk */, false /* reducedResolution */);
2115 final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
2116 allowTaskSnapshot, activityCreated, fromRecents, snapshot);
2117
2118 if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
2119 return createSnapshot(snapshot);
2120 }
2121
2122 // If this is a translucent window, then don't show a starting window -- the current
2123 // effect (a full-screen opaque starting window that fades away to the real contents
2124 // when it is ready) does not work for this.
2125 if (DEBUG_STARTING_WINDOW) {
2126 Slog.v(TAG, "Checking theme of starting window: 0x" + Integer.toHexString(theme));
2127 }
2128 if (theme != 0) {
2129 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
2130 com.android.internal.R.styleable.Window,
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002131 mWmService.mCurrentUserId);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002132 if (ent == null) {
2133 // Whoops! App doesn't exist. Um. Okay. We'll just pretend like we didn't
2134 // see that.
2135 return false;
2136 }
2137 final boolean windowIsTranslucent = ent.array.getBoolean(
2138 com.android.internal.R.styleable.Window_windowIsTranslucent, false);
2139 final boolean windowIsFloating = ent.array.getBoolean(
2140 com.android.internal.R.styleable.Window_windowIsFloating, false);
2141 final boolean windowShowWallpaper = ent.array.getBoolean(
2142 com.android.internal.R.styleable.Window_windowShowWallpaper, false);
2143 final boolean windowDisableStarting = ent.array.getBoolean(
2144 com.android.internal.R.styleable.Window_windowDisablePreview, false);
2145 if (DEBUG_STARTING_WINDOW) {
2146 Slog.v(TAG, "Translucent=" + windowIsTranslucent
2147 + " Floating=" + windowIsFloating
2148 + " ShowWallpaper=" + windowShowWallpaper);
2149 }
2150 if (windowIsTranslucent) {
2151 return false;
2152 }
2153 if (windowIsFloating || windowDisableStarting) {
2154 return false;
2155 }
2156 if (windowShowWallpaper) {
2157 if (getDisplayContent().mWallpaperController
2158 .getWallpaperTarget() == null) {
2159 // If this theme is requesting a wallpaper, and the wallpaper
2160 // is not currently visible, then this effectively serves as
2161 // an opaque window and our starting window transition animation
2162 // can still work. We just need to make sure the starting window
2163 // is also showing the wallpaper.
2164 windowFlags |= FLAG_SHOW_WALLPAPER;
2165 } else {
2166 return false;
2167 }
2168 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002169 }
Yunfan Chen8a8c0ed2018-12-18 16:46:32 -08002170
2171 if (transferStartingWindow(transferFrom)) {
2172 return true;
2173 }
2174
2175 // There is no existing starting window, and we don't want to create a splash screen, so
2176 // that's it!
2177 if (type != STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
2178 return false;
2179 }
2180
2181 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SplashScreenStartingData");
chaviwa8f07a72019-05-01 16:25:39 -07002182 mStartingData = new SplashScreenStartingData(mWmService, pkg,
Yunfan Chen8a8c0ed2018-12-18 16:46:32 -08002183 theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
2184 getMergedOverrideConfiguration());
2185 scheduleAddStartingWindow();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002186 return true;
2187 }
2188
2189
2190 private boolean createSnapshot(ActivityManager.TaskSnapshot snapshot) {
2191 if (snapshot == null) {
2192 return false;
2193 }
2194
2195 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SnapshotStartingData");
chaviwa8f07a72019-05-01 16:25:39 -07002196 mStartingData = new SnapshotStartingData(mWmService, snapshot);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002197 scheduleAddStartingWindow();
2198 return true;
2199 }
2200
2201 void scheduleAddStartingWindow() {
2202 // Note: we really want to do sendMessageAtFrontOfQueue() because we
2203 // want to process the message ASAP, before any other queued
2204 // messages.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002205 if (!mWmService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002206 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING");
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002207 mWmService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002208 }
2209 }
2210
2211 private final Runnable mAddStartingWindow = new Runnable() {
2212
2213 @Override
2214 public void run() {
chaviwa8f07a72019-05-01 16:25:39 -07002215 // Can be accessed without holding the global lock
2216 final StartingData startingData;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002217 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002218 // There can only be one adding request, silly caller!
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002219 mWmService.mAnimationHandler.removeCallbacks(this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002220
chaviwa8f07a72019-05-01 16:25:39 -07002221 if (mStartingData == null) {
2222 // Animation has been canceled... do nothing.
2223 if (DEBUG_STARTING_WINDOW) {
2224 Slog.v(TAG, "startingData was nulled out before handling"
2225 + " mAddStartingWindow: " + AppWindowToken.this);
2226 }
2227 return;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002228 }
chaviwa8f07a72019-05-01 16:25:39 -07002229 startingData = mStartingData;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002230 }
2231
2232 if (DEBUG_STARTING_WINDOW) {
2233 Slog.v(TAG, "Add starting " + this + ": startingData=" + startingData);
2234 }
2235
2236 WindowManagerPolicy.StartingSurface surface = null;
2237 try {
2238 surface = startingData.createStartingSurface(AppWindowToken.this);
2239 } catch (Exception e) {
2240 Slog.w(TAG, "Exception when adding starting window", e);
2241 }
2242 if (surface != null) {
2243 boolean abort = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002244 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002245 // If the window was successfully added, then
2246 // we need to remove it.
chaviwa8f07a72019-05-01 16:25:39 -07002247 if (removed || mStartingData == null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002248 if (DEBUG_STARTING_WINDOW) {
2249 Slog.v(TAG, "Aborted starting " + AppWindowToken.this
chaviwa8f07a72019-05-01 16:25:39 -07002250 + ": removed=" + removed + " startingData=" + mStartingData);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002251 }
2252 startingWindow = null;
chaviwa8f07a72019-05-01 16:25:39 -07002253 mStartingData = null;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002254 abort = true;
2255 } else {
2256 startingSurface = surface;
2257 }
2258 if (DEBUG_STARTING_WINDOW && !abort) {
chaviwa8f07a72019-05-01 16:25:39 -07002259 Slog.v(TAG,
2260 "Added starting " + AppWindowToken.this + ": startingWindow="
2261 + startingWindow + " startingView=" + startingSurface);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002262 }
2263 }
2264 if (abort) {
2265 surface.remove();
2266 }
2267 } else if (DEBUG_STARTING_WINDOW) {
2268 Slog.v(TAG, "Surface returned was null: " + AppWindowToken.this);
2269 }
2270 }
2271 };
2272
2273 private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
2274 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents,
2275 ActivityManager.TaskSnapshot snapshot) {
2276 if (getDisplayContent().mAppTransition.getAppTransition()
2277 == TRANSIT_DOCK_TASK_FROM_RECENTS) {
2278 // TODO(b/34099271): Remove this statement to add back the starting window and figure
2279 // out why it causes flickering, the starting window appears over the thumbnail while
2280 // the docked from recents transition occurs
2281 return STARTING_WINDOW_TYPE_NONE;
2282 } else if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
2283 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2284 } else if (taskSwitch && allowTaskSnapshot) {
Kevin716a9db2018-12-18 16:53:39 -08002285 if (mWmService.mLowRamTaskSnapshotsAndRecents) {
Kevin58b47f12018-12-17 14:09:01 -08002286 // For low RAM devices, we use the splash screen starting window instead of the
2287 // task snapshot starting window.
2288 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2289 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002290 return snapshot == null ? STARTING_WINDOW_TYPE_NONE
2291 : snapshotOrientationSameAsTask(snapshot) || fromRecents
2292 ? STARTING_WINDOW_TYPE_SNAPSHOT : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2293 } else {
2294 return STARTING_WINDOW_TYPE_NONE;
2295 }
2296 }
2297
2298
2299 private boolean snapshotOrientationSameAsTask(ActivityManager.TaskSnapshot snapshot) {
2300 if (snapshot == null) {
2301 return false;
2302 }
2303 return getTask().getConfiguration().orientation == snapshot.getOrientation();
2304 }
2305
2306 void removeStartingWindow() {
2307 if (startingWindow == null) {
chaviwa8f07a72019-05-01 16:25:39 -07002308 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002309 // Starting window has not been added yet, but it is scheduled to be added.
2310 // Go ahead and cancel the request.
2311 if (DEBUG_STARTING_WINDOW) {
2312 Slog.v(TAG_WM, "Clearing startingData for token=" + this);
2313 }
chaviwa8f07a72019-05-01 16:25:39 -07002314 mStartingData = null;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002315 }
2316 return;
2317 }
2318
2319 final WindowManagerPolicy.StartingSurface surface;
chaviwa8f07a72019-05-01 16:25:39 -07002320 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002321 surface = startingSurface;
chaviwa8f07a72019-05-01 16:25:39 -07002322 mStartingData = null;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002323 startingSurface = null;
2324 startingWindow = null;
2325 startingDisplayed = false;
2326 if (surface == null) {
2327 if (DEBUG_STARTING_WINDOW) {
2328 Slog.v(TAG_WM, "startingWindow was set but startingSurface==null, couldn't "
2329 + "remove");
2330 }
2331 return;
2332 }
2333 } else {
2334 if (DEBUG_STARTING_WINDOW) {
2335 Slog.v(TAG_WM, "Tried to remove starting window but startingWindow was null:"
2336 + this);
2337 }
2338 return;
2339 }
2340
2341 if (DEBUG_STARTING_WINDOW) {
2342 Slog.v(TAG_WM, "Schedule remove starting " + this
2343 + " startingWindow=" + startingWindow
2344 + " startingView=" + startingSurface
2345 + " Callers=" + Debug.getCallers(5));
2346 }
2347
2348 // Use the same thread to remove the window as we used to add it, as otherwise we end up
2349 // with things in the view hierarchy being called from different threads.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002350 mWmService.mAnimationHandler.post(() -> {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002351 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Removing startingView=" + surface);
2352 try {
2353 surface.remove();
2354 } catch (Exception e) {
2355 Slog.w(TAG_WM, "Exception when removing starting window", e);
2356 }
2357 });
2358 }
2359
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002360 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -07002361 boolean fillsParent() {
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -07002362 return occludesParent();
Wale Ogunwale51362492016-09-08 17:49:17 -07002363 }
2364
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -07002365 /** Returns true if this activity is opaque and fills the entire space of this task. */
2366 boolean occludesParent() {
2367 return mOccludesParent;
2368 }
2369
2370 boolean setOccludesParent(boolean occludesParent) {
2371 final boolean changed = occludesParent != mOccludesParent;
2372 mOccludesParent = occludesParent;
2373 setMainWindowOpaque(occludesParent);
2374 mWmService.mWindowPlacerLocked.requestTraversal();
2375 return changed;
2376 }
2377
2378 void setMainWindowOpaque(boolean isOpaque) {
2379 final WindowState win = findMainWindow();
2380 if (win == null) {
2381 return;
2382 }
2383 isOpaque = isOpaque & !PixelFormat.formatHasAlpha(win.getAttrs().format);
2384 win.mWinAnimator.setOpaqueLocked(isOpaque);
Wale Ogunwale51362492016-09-08 17:49:17 -07002385 }
2386
Jorim Jaggife762342016-10-13 14:33:27 +02002387 boolean containsDismissKeyguardWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002388 // Window state is transient during relaunch. We are not guaranteed to be frozen during the
2389 // entirety of the relaunch.
2390 if (isRelaunching()) {
2391 return mLastContainsDismissKeyguardWindow;
2392 }
2393
Jorim Jaggife762342016-10-13 14:33:27 +02002394 for (int i = mChildren.size() - 1; i >= 0; i--) {
2395 if ((mChildren.get(i).mAttrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
2396 return true;
2397 }
2398 }
2399 return false;
2400 }
2401
2402 boolean containsShowWhenLockedWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002403 // When we are relaunching, it is possible for us to be unfrozen before our previous
2404 // windows have been added back. Using the cached value ensures that our previous
2405 // showWhenLocked preference is honored until relaunching is complete.
2406 if (isRelaunching()) {
2407 return mLastContainsShowWhenLockedWindow;
2408 }
2409
Jorim Jaggife762342016-10-13 14:33:27 +02002410 for (int i = mChildren.size() - 1; i >= 0; i--) {
2411 if ((mChildren.get(i).mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
2412 return true;
2413 }
2414 }
Bryce Lee081554b2017-05-25 07:52:12 -07002415
Jorim Jaggife762342016-10-13 14:33:27 +02002416 return false;
2417 }
2418
2419 void checkKeyguardFlagsChanged() {
2420 final boolean containsDismissKeyguard = containsDismissKeyguardWindow();
2421 final boolean containsShowWhenLocked = containsShowWhenLockedWindow();
2422 if (containsDismissKeyguard != mLastContainsDismissKeyguardWindow
2423 || containsShowWhenLocked != mLastContainsShowWhenLockedWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002424 mWmService.notifyKeyguardFlagsChanged(null /* callback */,
lumark588a3e82018-07-20 18:53:54 +08002425 getDisplayContent().getDisplayId());
Jorim Jaggife762342016-10-13 14:33:27 +02002426 }
2427 mLastContainsDismissKeyguardWindow = containsDismissKeyguard;
2428 mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
2429 }
2430
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002431 WindowState getImeTargetBelowWindow(WindowState w) {
2432 final int index = mChildren.indexOf(w);
2433 if (index > 0) {
2434 final WindowState target = mChildren.get(index - 1);
2435 if (target.canBeImeTarget()) {
2436 return target;
2437 }
2438 }
2439 return null;
2440 }
2441
2442 WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
2443 WindowState candidate = null;
2444 for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
2445 final WindowState w = mChildren.get(i);
2446 if (w.mRemoved) {
2447 continue;
2448 }
Jorim Jaggi35d328a2018-08-14 17:00:20 +02002449 if (candidate == null) {
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002450 candidate = w;
2451 }
2452 }
2453 return candidate;
2454 }
2455
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002456 /**
2457 * See {@link Activity#setDisablePreviewScreenshots}.
2458 */
2459 void setDisablePreviewScreenshots(boolean disable) {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002460 mDisablePreviewScreenshots = disable;
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002461 }
2462
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002463 /**
Riddle Hsu4bb06be2019-07-02 01:03:07 +08002464 * Sets whether the current launch can turn the screen on.
2465 * @see #currentLaunchCanTurnScreenOn()
chaviwd3bf08d2017-08-01 17:24:59 -07002466 */
Riddle Hsu4bb06be2019-07-02 01:03:07 +08002467 void setCurrentLaunchCanTurnScreenOn(boolean currentLaunchCanTurnScreenOn) {
2468 mCurrentLaunchCanTurnScreenOn = currentLaunchCanTurnScreenOn;
chaviwd3bf08d2017-08-01 17:24:59 -07002469 }
2470
2471 /**
2472 * Indicates whether the current launch can turn the screen on. This is to prevent multiple
2473 * relayouts from turning the screen back on. The screen should only turn on at most
2474 * once per activity resume.
Riddle Hsu4bb06be2019-07-02 01:03:07 +08002475 * <p>
2476 * Note this flag is only meaningful when {@link WindowManager.LayoutParams#FLAG_TURN_SCREEN_ON}
2477 * or {@link ActivityRecord#canTurnScreenOn} is set.
chaviwd3bf08d2017-08-01 17:24:59 -07002478 *
Riddle Hsu4bb06be2019-07-02 01:03:07 +08002479 * @return {@code true} if the activity is ready to turn on the screen.
chaviwd3bf08d2017-08-01 17:24:59 -07002480 */
Riddle Hsu4bb06be2019-07-02 01:03:07 +08002481 boolean currentLaunchCanTurnScreenOn() {
2482 return mCurrentLaunchCanTurnScreenOn;
chaviwd3bf08d2017-08-01 17:24:59 -07002483 }
2484
2485 /**
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002486 * Retrieves whether we'd like to generate a snapshot that's based solely on the theme. This is
2487 * the case when preview screenshots are disabled {@link #setDisablePreviewScreenshots} or when
2488 * we can't take a snapshot for other reasons, for example, if we have a secure window.
2489 *
2490 * @return True if we need to generate an app theme snapshot, false if we'd like to take a real
2491 * screenshot.
2492 */
2493 boolean shouldUseAppThemeSnapshot() {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002494 return mDisablePreviewScreenshots || forAllWindows(w -> (w.mAttrs.flags & FLAG_SECURE) != 0,
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002495 true /* topToBottom */);
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002496 }
2497
Jorim Jaggibe418292018-03-26 16:14:12 +02002498 SurfaceControl getAppAnimationLayer() {
Jorim Jaggi391790622018-04-18 15:30:44 +02002499 return getAppAnimationLayer(isActivityTypeHome() ? ANIMATION_LAYER_HOME
2500 : needsZBoost() ? ANIMATION_LAYER_BOOSTED
2501 : ANIMATION_LAYER_STANDARD);
Jorim Jaggibe418292018-03-26 16:14:12 +02002502 }
2503
chaviw23ee71c2017-12-18 11:29:41 -08002504 @Override
Jorim Jaggi596a1992017-12-29 14:48:02 +01002505 public SurfaceControl getAnimationLeashParent() {
Robert Carrb9506032018-02-13 13:54:00 -08002506 // For transitions in the pinned stack (menu activity) we just let them occur as a child
2507 // of the pinned stack.
Issei Suzuki71142152019-08-15 14:39:40 +02002508 // All normal app transitions take place in an animation layer which is below the pinned
2509 // stack but may be above the parent stacks of the given animating apps by default. When
2510 // a new hierarchical animation is enabled, we just let them occur as a child of the parent
2511 // stack, i.e. the hierarchy of the surfaces is unchanged.
2512 if (inPinnedWindowingMode()) {
Robert Carrb9506032018-02-13 13:54:00 -08002513 return getStack().getSurfaceControl();
Issei Suzuki71142152019-08-15 14:39:40 +02002514 } else if (WindowManagerService.sHierarchicalAnimations) {
2515 return super.getAnimationLeashParent();
2516 } else {
2517 return getAppAnimationLayer();
Robert Carrb9506032018-02-13 13:54:00 -08002518 }
chaviw23ee71c2017-12-18 11:29:41 -08002519 }
2520
lumarkb5a78b32019-04-25 20:31:30 +08002521
2522 @VisibleForTesting
2523 boolean shouldAnimate(int transit) {
Jorim Jaggic6976f02018-04-18 16:31:07 +02002524 final boolean isSplitScreenPrimary =
2525 getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
2526 final boolean allowSplitScreenPrimaryAnimation = transit != TRANSIT_WALLPAPER_OPEN;
2527
lumarkb5a78b32019-04-25 20:31:30 +08002528 // Don't animate while the task runs recents animation but only if we are in the mode
2529 // where we cancel with deferred screenshot, which means that the controller has
2530 // transformed the task.
lumark54284462019-03-05 20:44:27 +08002531 final RecentsAnimationController controller = mWmService.getRecentsAnimationController();
lumarkb5a78b32019-04-25 20:31:30 +08002532 if (controller != null && controller.isAnimatingTask(getTask())
Winson Chung7a545ae2019-07-16 14:52:13 -07002533 && controller.shouldDeferCancelUntilNextTransition()) {
lumark54284462019-03-05 20:44:27 +08002534 return false;
2535 }
2536
Jorim Jaggic6976f02018-04-18 16:31:07 +02002537 // We animate always if it's not split screen primary, and only some special cases in split
2538 // screen primary because it causes issues with stack clipping when we run an un-minimize
2539 // animation at the same time.
2540 return !isSplitScreenPrimary || allowSplitScreenPrimaryAnimation;
2541 }
2542
Vishnu Naira2977262018-07-26 13:31:26 -07002543 /**
2544 * Creates a layer to apply crop to an animation.
2545 */
2546 private SurfaceControl createAnimationBoundsLayer(Transaction t) {
2547 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.i(TAG, "Creating animation bounds layer");
2548 final SurfaceControl.Builder builder = makeAnimationLeash()
2549 .setParent(getAnimationLeashParent())
Vishnu Naire86bd982018-11-28 13:23:17 -08002550 .setName(getSurfaceControl() + " - animation-bounds");
Vishnu Naira2977262018-07-26 13:31:26 -07002551 final SurfaceControl boundsLayer = builder.build();
2552 t.show(boundsLayer);
2553 return boundsLayer;
2554 }
2555
Evan Roskyed6767f2018-10-26 17:21:06 -07002556 @Override
2557 Rect getDisplayedBounds() {
2558 final Task task = getTask();
2559 if (task != null) {
2560 final Rect overrideDisplayedBounds = task.getOverrideDisplayedBounds();
2561 if (!overrideDisplayedBounds.isEmpty()) {
2562 return overrideDisplayedBounds;
2563 }
2564 }
2565 return getBounds();
2566 }
2567
Evan Rosky641daea2019-04-24 14:45:24 -07002568 @VisibleForTesting
2569 Rect getAnimationBounds(int appStackClipMode) {
2570 if (appStackClipMode == STACK_CLIP_BEFORE_ANIM && getStack() != null) {
2571 // Using the stack bounds here effectively applies the clipping before animation.
2572 return getStack().getBounds();
2573 }
2574 // Use task-bounds if available so that activity-level letterbox (maxAspectRatio) is
2575 // included in the animation.
2576 return getTask() != null ? getTask().getBounds() : getBounds();
2577 }
2578
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002579 boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter,
2580 boolean isVoiceInteraction) {
2581
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002582 if (mWmService.mDisableTransitionAnimation || !shouldAnimate(transit)) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002583 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
Jorim Jaggic6976f02018-04-18 16:31:07 +02002584 Slog.v(TAG_WM, "applyAnimation: transition animation is disabled or skipped."
2585 + " atoken=" + this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002586 }
2587 cancelAnimation();
2588 return false;
2589 }
2590
2591 // Only apply an animation if the display isn't frozen. If it is frozen, there is no reason
2592 // to animate and it can cause strange artifacts when we unfreeze the display if some
2593 // different animation is running.
2594 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#applyAnimationLocked");
2595 if (okToAnimate()) {
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002596 final AnimationAdapter adapter;
Evan Rosky2289ba12018-11-19 18:28:18 -08002597 AnimationAdapter thumbnailAdapter = null;
Evan Rosky4fb1e912019-03-06 13:54:43 -08002598
Evan Rosky641daea2019-04-24 14:45:24 -07002599 final int appStackClipMode =
2600 getDisplayContent().mAppTransition.getAppStackClipMode();
2601
2602 // Separate position and size for use in animators.
2603 mTmpRect.set(getAnimationBounds(appStackClipMode));
Evan Rosky4fb1e912019-03-06 13:54:43 -08002604 mTmpPoint.set(mTmpRect.left, mTmpRect.top);
2605 mTmpRect.offsetTo(0, 0);
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002606
Evan Roskyec9488c2019-03-01 19:32:12 -08002607 final boolean isChanging = AppTransition.isChangeTransit(transit) && enter
2608 && getDisplayContent().mChangingApps.contains(this);
Evan Rosky2289ba12018-11-19 18:28:18 -08002609
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002610 // Delaying animation start isn't compatible with remote animations at all.
lumark588a3e82018-07-20 18:53:54 +08002611 if (getDisplayContent().mAppTransition.getRemoteAnimationController() != null
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002612 && !mSurfaceAnimator.isAnimationStartDelayed()) {
Evan Rosky2289ba12018-11-19 18:28:18 -08002613 RemoteAnimationRecord adapters =
2614 getDisplayContent().mAppTransition.getRemoteAnimationController()
2615 .createRemoteAnimationRecord(this, mTmpPoint, mTmpRect,
2616 (isChanging ? mTransitStartRect : null));
2617 adapter = adapters.mAdapter;
2618 thumbnailAdapter = adapters.mThumbnailAdapter;
2619 } else if (isChanging) {
Evan Roskycf76bed2019-01-15 10:33:58 -08002620 final float durationScale = mWmService.getTransitionAnimationScaleLocked();
Evan Rosky2289ba12018-11-19 18:28:18 -08002621 mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y);
2622 adapter = new LocalAnimationAdapter(
2623 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
Evan Roskycf76bed2019-01-15 10:33:58 -08002624 getDisplayContent().getDisplayInfo(), durationScale,
Evan Rosky2289ba12018-11-19 18:28:18 -08002625 true /* isAppAnimation */, false /* isThumbnail */),
2626 mWmService.mSurfaceAnimationRunner);
Evan Rosky966759f2019-01-15 10:33:58 -08002627 if (mThumbnail != null) {
2628 thumbnailAdapter = new LocalAnimationAdapter(
2629 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
Evan Roskycf76bed2019-01-15 10:33:58 -08002630 getDisplayContent().getDisplayInfo(), durationScale,
Evan Rosky966759f2019-01-15 10:33:58 -08002631 true /* isAppAnimation */, true /* isThumbnail */),
2632 mWmService.mSurfaceAnimationRunner);
2633 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002634 mTransit = transit;
2635 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002636 } else {
Vishnu Naira2977262018-07-26 13:31:26 -07002637 mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM);
2638
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002639 final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
2640 if (a != null) {
Lucas Dupin95acf432019-04-29 17:55:38 -07002641 // Only apply corner radius to animation if we're not in multi window mode.
2642 // We don't want rounded corners when in pip or split screen.
2643 final float windowCornerRadius = !inMultiWindowMode()
2644 ? getDisplayContent().getWindowCornerRadius()
2645 : 0;
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002646 adapter = new LocalAnimationAdapter(
2647 new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
lumark588a3e82018-07-20 18:53:54 +08002648 getDisplayContent().mAppTransition.canSkipFirstFrame(),
Vishnu Naira2977262018-07-26 13:31:26 -07002649 appStackClipMode,
Lucas Dupin3e1dc202018-12-02 15:14:20 -08002650 true /* isAppAnimation */,
Lucas Dupin95acf432019-04-29 17:55:38 -07002651 windowCornerRadius),
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002652 mWmService.mSurfaceAnimationRunner);
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002653 if (a.getZAdjustment() == Animation.ZORDER_TOP) {
2654 mNeedsZBoost = true;
2655 }
2656 mTransit = transit;
lumark588a3e82018-07-20 18:53:54 +08002657 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002658 } else {
2659 adapter = null;
chaviw23ee71c2017-12-18 11:29:41 -08002660 }
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002661 }
2662 if (adapter != null) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002663 startAnimation(getPendingTransaction(), adapter, !isVisible());
Jorim Jaggi82c17862018-02-21 17:50:18 +01002664 if (adapter.getShowWallpaper()) {
2665 mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2666 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002667 if (thumbnailAdapter != null) {
2668 mThumbnail.startAnimation(
2669 getPendingTransaction(), thumbnailAdapter, !isVisible());
2670 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002671 }
2672 } else {
2673 cancelAnimation();
2674 }
2675 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2676
2677 return isReallyAnimating();
2678 }
2679
2680 private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
2681 boolean isVoiceInteraction) {
2682 final DisplayContent displayContent = getTask().getDisplayContent();
2683 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2684 final int width = displayInfo.appWidth;
2685 final int height = displayInfo.appHeight;
2686 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG_WM,
2687 "applyAnimation: atoken=" + this);
2688
2689 // Determine the visible rect to calculate the thumbnail clip
2690 final WindowState win = findMainWindow();
2691 final Rect frame = new Rect(0, 0, width, height);
2692 final Rect displayFrame = new Rect(0, 0,
2693 displayInfo.logicalWidth, displayInfo.logicalHeight);
2694 final Rect insets = new Rect();
2695 final Rect stableInsets = new Rect();
2696 Rect surfaceInsets = null;
2697 final boolean freeform = win != null && win.inFreeformWindowingMode();
2698 if (win != null) {
2699 // Containing frame will usually cover the whole screen, including dialog windows.
2700 // For freeform workspace windows it will not cover the whole screen and it also
2701 // won't exactly match the final freeform window frame (e.g. when overlapping with
2702 // the status bar). In that case we need to use the final frame.
2703 if (freeform) {
chaviw492139a2018-07-16 16:07:35 -07002704 frame.set(win.getFrameLw());
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002705 } else if (win.isLetterboxedAppWindow()) {
2706 frame.set(getTask().getBounds());
Winson Chungc1674272018-02-21 10:15:17 -08002707 } else if (win.isDockedResizing()) {
2708 // If we are animating while docked resizing, then use the stack bounds as the
2709 // animation target (which will be different than the task bounds)
2710 frame.set(getTask().getParent().getBounds());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002711 } else {
chaviw553b0212018-07-12 13:37:01 -07002712 frame.set(win.getContainingFrame());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002713 }
2714 surfaceInsets = win.getAttrs().surfaceInsets;
Adrian Roos20e07892018-02-23 19:12:01 +01002715 // XXX(b/72757033): These are insets relative to the window frame, but we're really
2716 // interested in the insets relative to the frame we chose in the if-blocks above.
chaviw9c81e632018-07-31 11:17:52 -07002717 win.getContentInsets(insets);
2718 win.getStableInsets(stableInsets);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002719 }
2720
2721 if (mLaunchTaskBehind) {
2722 // Differentiate the two animations. This one which is briefly on the screen
2723 // gets the !enter animation, and the other activity which remains on the
2724 // screen gets the enter animation. Both appear in the mOpeningApps set.
2725 enter = false;
2726 }
2727 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "Loading animation for app transition."
2728 + " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter
2729 + " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets);
2730 final Configuration displayConfig = displayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08002731 final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002732 displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
2733 surfaceInsets, stableInsets, isVoiceInteraction, freeform, getTask().mTaskId);
2734 if (a != null) {
2735 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
2736 final int containingWidth = frame.width();
2737 final int containingHeight = frame.height();
2738 a.initialize(containingWidth, containingHeight, width, height);
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002739 a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002740 }
2741 return a;
2742 }
2743
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002744 @Override
Jorim Jaggi6de61012018-03-19 14:53:23 +01002745 public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
2746 return mAnimatingAppWindowTokenRegistry != null
2747 && mAnimatingAppWindowTokenRegistry.notifyAboutToFinish(
2748 this, endDeferFinishCallback);
2749 }
2750
2751 @Override
lumarkf6f34942019-04-29 16:56:50 +08002752 public void onAnimationLeashLost(Transaction t) {
2753 super.onAnimationLeashLost(t);
Vishnu Naira2977262018-07-26 13:31:26 -07002754 if (mAnimationBoundsLayer != null) {
Robert Carr71200f22019-02-05 09:44:53 -08002755 t.remove(mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002756 mAnimationBoundsLayer = null;
2757 }
2758
Jorim Jaggi6de61012018-03-19 14:53:23 +01002759 if (mAnimatingAppWindowTokenRegistry != null) {
2760 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
2761 }
2762 }
2763
2764 @Override
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002765 protected void setLayer(Transaction t, int layer) {
2766 if (!mSurfaceAnimator.hasLeash()) {
2767 t.setLayer(mSurfaceControl, layer);
2768 }
2769 }
2770
2771 @Override
2772 protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
2773 if (!mSurfaceAnimator.hasLeash()) {
2774 t.setRelativeLayer(mSurfaceControl, relativeTo, layer);
2775 }
2776 }
2777
2778 @Override
2779 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
2780 if (!mSurfaceAnimator.hasLeash()) {
Robert Carr10584fa2019-01-14 15:55:19 -08002781 t.reparent(mSurfaceControl, newParent);
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002782 }
2783 }
2784
2785 @Override
2786 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002787 // The leash is parented to the animation layer. We need to preserve the z-order by using
2788 // the prefix order index, but we boost if necessary.
Robert Carrb9506032018-02-13 13:54:00 -08002789 int layer = 0;
2790 if (!inPinnedWindowingMode()) {
2791 layer = getPrefixOrderIndex();
2792 } else {
2793 // Pinned stacks have animations take place within themselves rather than an animation
2794 // layer so we need to preserve the order relative to the stack (e.g. the order of our
2795 // task/parent).
2796 layer = getParent().getPrefixOrderIndex();
2797 }
2798
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002799 if (mNeedsZBoost) {
2800 layer += Z_BOOST_BASE;
2801 }
Jorim Jaggi9cd99132019-04-24 17:41:35 +02002802 if (!mNeedsAnimationBoundsLayer) {
2803 leash.setLayer(layer);
2804 }
Robert Carr2f8aa392018-01-31 14:46:51 -08002805
2806 final DisplayContent dc = getDisplayContent();
Jorim Jaggibe418292018-03-26 16:14:12 +02002807 dc.assignStackOrdering();
Evan Rosky2289ba12018-11-19 18:28:18 -08002808
2809 if (leash == mTransitChangeLeash) {
2810 // This is a temporary state so skip any animation notifications
2811 return;
2812 } else if (mTransitChangeLeash != null) {
2813 // unparent mTransitChangeLeash for clean-up
Evan Rosky25b56192019-02-06 16:10:56 -08002814 clearChangeLeash(t, false /* cancel */);
Evan Rosky2289ba12018-11-19 18:28:18 -08002815 }
2816
Jorim Jaggi6de61012018-03-19 14:53:23 +01002817 if (mAnimatingAppWindowTokenRegistry != null) {
2818 mAnimatingAppWindowTokenRegistry.notifyStarting(this);
2819 }
Vishnu Naira2977262018-07-26 13:31:26 -07002820
2821 // If the animation needs to be cropped then an animation bounds layer is created as a child
2822 // of the pinned stack or animation layer. The leash is then reparented to this new layer.
2823 if (mNeedsAnimationBoundsLayer) {
Evan Rosky7735d352019-03-18 17:27:27 -07002824 mTmpRect.setEmpty();
2825 final Task task = getTask();
2826 if (getDisplayContent().mAppTransitionController.isTransitWithinTask(
2827 getTransit(), task)) {
2828 task.getBounds(mTmpRect);
2829 } else {
2830 final TaskStack stack = getStack();
2831 if (stack == null) {
2832 return;
2833 }
2834 // Set clip rect to stack bounds.
2835 stack.getBounds(mTmpRect);
Vishnu Naira2977262018-07-26 13:31:26 -07002836 }
2837 mAnimationBoundsLayer = createAnimationBoundsLayer(t);
2838
Vishnu Naira2977262018-07-26 13:31:26 -07002839 // Crop to stack bounds.
2840 t.setWindowCrop(mAnimationBoundsLayer, mTmpRect);
Jorim Jaggi9cd99132019-04-24 17:41:35 +02002841 t.setLayer(mAnimationBoundsLayer, layer);
Vishnu Naira2977262018-07-26 13:31:26 -07002842
2843 // Reparent leash to animation bounds layer.
Robert Carr10584fa2019-01-14 15:55:19 -08002844 t.reparent(leash, mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002845 }
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002846 }
2847
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002848 /**
2849 * This must be called while inside a transaction.
2850 */
2851 void showAllWindowsLocked() {
2852 forAllWindows(windowState -> {
2853 if (DEBUG_VISIBILITY) Slog.v(TAG, "performing show on: " + windowState);
2854 windowState.performShowLocked();
2855 }, false /* traverseTopToBottom */);
Jorim Jaggia5e10572017-11-15 14:36:26 +01002856 }
2857
2858 @Override
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002859 protected void onAnimationFinished() {
2860 super.onAnimationFinished();
2861
Ian8b2822e2019-05-14 11:59:02 -07002862 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#onAnimationFinished");
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002863 mTransit = TRANSIT_UNSET;
2864 mTransitFlags = 0;
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002865 mNeedsZBoost = false;
Vishnu Naira2977262018-07-26 13:31:26 -07002866 mNeedsAnimationBoundsLayer = false;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002867
2868 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER,
2869 "AppWindowToken");
2870
Jorim Jaggi988f6682017-11-17 17:46:43 +01002871 clearThumbnail();
Jorim Jaggi752cd822018-03-29 16:29:18 +02002872 setClientHidden(isHidden() && hiddenRequested);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002873
lumarkff0ab692018-11-05 20:32:30 +08002874 getDisplayContent().computeImeTargetIfNeeded(this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002875
2876 if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + this
2877 + ": reportedVisible=" + reportedVisible
2878 + " okToDisplay=" + okToDisplay()
2879 + " okToAnimate=" + okToAnimate()
2880 + " startingDisplayed=" + startingDisplayed);
2881
Evan Rosky2289ba12018-11-19 18:28:18 -08002882 // clean up thumbnail window
2883 if (mThumbnail != null) {
2884 mThumbnail.destroy();
2885 mThumbnail = null;
2886 }
2887
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002888 // WindowState.onExitAnimationDone might modify the children list, so make a copy and then
2889 // traverse the copy.
2890 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
2891 children.forEach(WindowState::onExitAnimationDone);
2892
lumark588a3e82018-07-20 18:53:54 +08002893 getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002894 scheduleAnimation();
Jorim Jaggi9b5e3312019-03-01 18:08:00 +01002895
2896 mActivityRecord.onAnimationFinished();
Ian8b2822e2019-05-14 11:59:02 -07002897 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002898 }
2899
2900 @Override
2901 boolean isAppAnimating() {
2902 return isSelfAnimating();
2903 }
2904
2905 @Override
2906 boolean isSelfAnimating() {
2907 // If we are about to start a transition, we also need to be considered animating.
2908 return isWaitingForTransitionStart() || isReallyAnimating();
2909 }
2910
2911 /**
2912 * @return True if and only if we are actually running an animation. Note that
2913 * {@link #isSelfAnimating} also returns true if we are waiting for an animation to
2914 * start.
2915 */
2916 private boolean isReallyAnimating() {
2917 return super.isSelfAnimating();
2918 }
2919
Evan Rosky25b56192019-02-06 16:10:56 -08002920 /**
2921 * @param cancel {@code true} if clearing the leash due to cancelling instead of transferring
2922 * to another leash.
2923 */
2924 private void clearChangeLeash(Transaction t, boolean cancel) {
2925 if (mTransitChangeLeash == null) {
2926 return;
2927 }
2928 if (cancel) {
2929 clearThumbnail();
2930 SurfaceControl sc = getSurfaceControl();
2931 SurfaceControl parentSc = getParentSurfaceControl();
2932 // Don't reparent if surface is getting destroyed
2933 if (parentSc != null && sc != null) {
2934 t.reparent(sc, getParentSurfaceControl());
2935 }
2936 }
2937 t.hide(mTransitChangeLeash);
Evan Rosky08e20932019-05-14 10:54:07 -07002938 t.remove(mTransitChangeLeash);
Evan Rosky25b56192019-02-06 16:10:56 -08002939 mTransitChangeLeash = null;
2940 if (cancel) {
lumarkf6f34942019-04-29 16:56:50 +08002941 onAnimationLeashLost(t);
Evan Rosky25b56192019-02-06 16:10:56 -08002942 }
2943 }
2944
Jorim Jaggi988f6682017-11-17 17:46:43 +01002945 @Override
2946 void cancelAnimation() {
Evan Rosky2289ba12018-11-19 18:28:18 -08002947 cancelAnimationOnly();
Jorim Jaggi988f6682017-11-17 17:46:43 +01002948 clearThumbnail();
Evan Rosky25b56192019-02-06 16:10:56 -08002949 clearChangeLeash(getPendingTransaction(), true /* cancel */);
Evan Rosky2289ba12018-11-19 18:28:18 -08002950 }
2951
2952 /**
2953 * This only cancels the animation. It doesn't do other teardown like cleaning-up thumbnail
2954 * or interim leashes.
2955 * <p>
2956 * Used when canceling in preparation for starting a new animation.
2957 */
2958 void cancelAnimationOnly() {
2959 super.cancelAnimation();
Jorim Jaggi988f6682017-11-17 17:46:43 +01002960 }
2961
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002962 boolean isWaitingForTransitionStart() {
lumark588a3e82018-07-20 18:53:54 +08002963 return getDisplayContent().mAppTransition.isTransitionSet()
2964 && (getDisplayContent().mOpeningApps.contains(this)
Evan Rosky2289ba12018-11-19 18:28:18 -08002965 || getDisplayContent().mClosingApps.contains(this)
2966 || getDisplayContent().mChangingApps.contains(this));
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002967 }
2968
2969 public int getTransit() {
2970 return mTransit;
2971 }
2972
2973 int getTransitFlags() {
2974 return mTransitFlags;
2975 }
2976
Jorim Jaggi988f6682017-11-17 17:46:43 +01002977 void attachThumbnailAnimation() {
2978 if (!isReallyAnimating()) {
2979 return;
2980 }
2981 final int taskId = getTask().mTaskId;
2982 final GraphicBuffer thumbnailHeader =
lumark588a3e82018-07-20 18:53:54 +08002983 getDisplayContent().mAppTransition.getAppTransitionThumbnailHeader(taskId);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002984 if (thumbnailHeader == null) {
2985 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG, "No thumbnail header bitmap for: " + taskId);
2986 return;
2987 }
2988 clearThumbnail();
Vishnu Nair33197392019-08-30 10:29:37 -07002989 mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory, getPendingTransaction(),
2990 this, thumbnailHeader);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002991 mThumbnail.startAnimation(getPendingTransaction(), loadThumbnailAnimation(thumbnailHeader));
2992 }
2993
Tony Mak64b8d562017-12-28 17:44:02 +00002994 /**
2995 * Attaches a surface with a thumbnail for the
2996 * {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation.
2997 */
2998 void attachCrossProfileAppsThumbnailAnimation() {
2999 if (!isReallyAnimating()) {
3000 return;
3001 }
3002 clearThumbnail();
3003
3004 final WindowState win = findMainWindow();
3005 if (win == null) {
3006 return;
3007 }
chaviw492139a2018-07-16 16:07:35 -07003008 final Rect frame = win.getFrameLw();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08003009 final int thumbnailDrawableRes = getTask().mUserId == mWmService.mCurrentUserId
Tony Mak64b8d562017-12-28 17:44:02 +00003010 ? R.drawable.ic_account_circle
Tony Makda4af232018-04-27 11:01:10 +01003011 : R.drawable.ic_corp_badge;
Tony Mak64b8d562017-12-28 17:44:02 +00003012 final GraphicBuffer thumbnail =
lumark588a3e82018-07-20 18:53:54 +08003013 getDisplayContent().mAppTransition
Tony Mak64b8d562017-12-28 17:44:02 +00003014 .createCrossProfileAppsThumbnail(thumbnailDrawableRes, frame);
3015 if (thumbnail == null) {
3016 return;
3017 }
Vishnu Nair33197392019-08-30 10:29:37 -07003018 mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory,
3019 getPendingTransaction(), this, thumbnail);
Tony Mak64b8d562017-12-28 17:44:02 +00003020 final Animation animation =
lumark588a3e82018-07-20 18:53:54 +08003021 getDisplayContent().mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(
chaviw492139a2018-07-16 16:07:35 -07003022 win.getFrameLw());
Tony Mak64b8d562017-12-28 17:44:02 +00003023 mThumbnail.startAnimation(getPendingTransaction(), animation, new Point(frame.left,
3024 frame.top));
3025 }
3026
Jorim Jaggi988f6682017-11-17 17:46:43 +01003027 private Animation loadThumbnailAnimation(GraphicBuffer thumbnailHeader) {
3028 final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
3029
3030 // If this is a multi-window scenario, we use the windows frame as
3031 // destination of the thumbnail header animation. If this is a full screen
3032 // window scenario, we use the whole display as the target.
3033 WindowState win = findMainWindow();
3034 Rect appRect = win != null ? win.getContentFrameLw() :
3035 new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
chaviw9c81e632018-07-31 11:17:52 -07003036 final Rect insets = win != null ? win.getContentInsets() : null;
Jorim Jaggi988f6682017-11-17 17:46:43 +01003037 final Configuration displayConfig = mDisplayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08003038 return getDisplayContent().mAppTransition.createThumbnailAspectScaleAnimationLocked(
Jorim Jaggi988f6682017-11-17 17:46:43 +01003039 appRect, insets, thumbnailHeader, getTask().mTaskId, displayConfig.uiMode,
3040 displayConfig.orientation);
3041 }
3042
3043 private void clearThumbnail() {
3044 if (mThumbnail == null) {
3045 return;
3046 }
3047 mThumbnail.destroy();
3048 mThumbnail = null;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003049 }
3050
Jorim Jaggif84e2f62018-01-16 14:17:59 +01003051 void registerRemoteAnimations(RemoteAnimationDefinition definition) {
3052 mRemoteAnimationDefinition = definition;
3053 }
3054
3055 RemoteAnimationDefinition getRemoteAnimationDefinition() {
3056 return mRemoteAnimationDefinition;
3057 }
3058
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003059 @Override
3060 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
3061 super.dump(pw, prefix, dumpAll);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003062 if (appToken != null) {
Wale Ogunwale72919d22016-12-08 18:58:50 -08003063 pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003064 }
Winson Chung48b25652018-10-22 14:04:30 -07003065 pw.println(prefix + "component=" + mActivityComponent.flattenToShortString());
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08003066 pw.print(prefix); pw.print("task="); pw.println(getTask());
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -07003067 pw.print(prefix); pw.print(" mOccludesParent="); pw.print(mOccludesParent);
Wale Ogunwale51362492016-09-08 17:49:17 -07003068 pw.print(" mOrientation="); pw.println(mOrientation);
Wale Ogunwale89973222017-04-23 18:39:45 -07003069 pw.println(prefix + "hiddenRequested=" + hiddenRequested + " mClientHidden=" + mClientHidden
3070 + ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "")
3071 + " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible);
Craig Mautner59431632012-04-04 11:56:44 -07003072 if (paused) {
3073 pw.print(prefix); pw.print("paused="); pw.println(paused);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003074 }
Wale Ogunwale9017ec02016-02-25 08:55:25 -08003075 if (mAppStopped) {
3076 pw.print(prefix); pw.print("mAppStopped="); pw.println(mAppStopped);
3077 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07003078 if (mNumInterestingWindows != 0 || mNumDrawnWindows != 0
Jorim Jaggib0fc8172017-11-23 17:04:08 +00003079 || allDrawn || mLastAllDrawn) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07003080 pw.print(prefix); pw.print("mNumInterestingWindows=");
3081 pw.print(mNumInterestingWindows);
3082 pw.print(" mNumDrawnWindows="); pw.print(mNumDrawnWindows);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003083 pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
Craig Mautner6fbda632012-07-03 09:26:39 -07003084 pw.print(" allDrawn="); pw.print(allDrawn);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00003085 pw.print(" lastAllDrawn="); pw.print(mLastAllDrawn);
Craig Mautner6fbda632012-07-03 09:26:39 -07003086 pw.println(")");
3087 }
3088 if (inPendingTransaction) {
3089 pw.print(prefix); pw.print("inPendingTransaction=");
3090 pw.println(inPendingTransaction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003091 }
chaviwa8f07a72019-05-01 16:25:39 -07003092 if (mStartingData != null || removed || firstWindowDrawn || mIsExiting) {
3093 pw.print(prefix); pw.print("startingData="); pw.print(mStartingData);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003094 pw.print(" removed="); pw.print(removed);
Craig Mautner3d7ca312015-01-08 10:56:00 -08003095 pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
Craig Mautner799bc1d2015-01-14 10:33:48 -08003096 pw.print(" mIsExiting="); pw.println(mIsExiting);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003097 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08003098 if (startingWindow != null || startingSurface != null
Wale Ogunwale6c459212017-05-17 08:56:03 -07003099 || startingDisplayed || startingMoved || mHiddenSetFromTransferredStartingWindow) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003100 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08003101 pw.print(" startingSurface="); pw.print(startingSurface);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003102 pw.print(" startingDisplayed="); pw.print(startingDisplayed);
Wale Ogunwale6c459212017-05-17 08:56:03 -07003103 pw.print(" startingMoved="); pw.print(startingMoved);
3104 pw.println(" mHiddenSetFromTransferredStartingWindow="
3105 + mHiddenSetFromTransferredStartingWindow);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003106 }
Jorim Jaggi0429f352015-12-22 16:29:16 +01003107 if (!mFrozenBounds.isEmpty()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08003108 pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
Jorim Jaggi26c8c422016-05-09 19:57:25 -07003109 pw.print(prefix); pw.print("mFrozenMergedConfig="); pw.println(mFrozenMergedConfig);
Chong Zhangd78ddb42016-03-02 17:01:14 -08003110 }
3111 if (mPendingRelaunchCount != 0) {
3112 pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount);
Jorim Jaggi0429f352015-12-22 16:29:16 +01003113 }
Riddle Hsub398da32019-01-21 21:48:16 +08003114 if (mSizeCompatScale != 1f || mSizeCompatBounds != null) {
3115 pw.println(prefix + "mSizeCompatScale=" + mSizeCompatScale + " mSizeCompatBounds="
3116 + mSizeCompatBounds);
3117 }
Wale Ogunwalee287e192017-04-21 09:30:12 -07003118 if (mRemovingFromDisplay) {
3119 pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay);
3120 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003121 }
3122
3123 @Override
3124 void setHidden(boolean hidden) {
3125 super.setHidden(hidden);
3126 scheduleAnimation();
3127 }
3128
3129 @Override
3130 void prepareSurfaces() {
3131 // isSelfAnimating also returns true when we are about to start a transition, so we need
3132 // to check super here.
3133 final boolean reallyAnimating = super.isSelfAnimating();
3134 final boolean show = !isHidden() || reallyAnimating;
Robert Carrd8e4fb72019-01-31 11:14:30 -08003135
3136 if (mSurfaceControl != null) {
3137 if (show && !mLastSurfaceShowing) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003138 getPendingTransaction().show(mSurfaceControl);
Robert Carrd8e4fb72019-01-31 11:14:30 -08003139 } else if (!show && mLastSurfaceShowing) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003140 getPendingTransaction().hide(mSurfaceControl);
Robert Carrd8e4fb72019-01-31 11:14:30 -08003141 }
Jorim Jaggi4d1835d2017-08-31 17:28:27 +02003142 }
Jorim Jaggi988f6682017-11-17 17:46:43 +01003143 if (mThumbnail != null) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003144 mThumbnail.setShowing(getPendingTransaction(), show);
Jorim Jaggi988f6682017-11-17 17:46:43 +01003145 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003146 mLastSurfaceShowing = show;
3147 super.prepareSurfaces();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003148 }
3149
Jorim Jaggi77d0f36c2018-03-16 17:49:49 +01003150 /**
3151 * @return Whether our {@link #getSurfaceControl} is currently showing.
3152 */
3153 boolean isSurfaceShowing() {
3154 return mLastSurfaceShowing;
3155 }
3156
Jorim Jaggib0fc8172017-11-23 17:04:08 +00003157 boolean isFreezingScreen() {
3158 return mFreezingScreen;
3159 }
3160
3161 @Override
3162 boolean needsZBoost() {
3163 return mNeedsZBoost || super.needsZBoost();
3164 }
3165
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07003166 @CallSuper
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003167 @Override
Nataniel Borges023ecb52019-01-16 14:15:43 -08003168 public void writeToProto(ProtoOutputStream proto, long fieldId,
3169 @WindowTraceLogLevel int logLevel) {
3170 // Critical log level logs only visible elements to mitigate performance overheard
3171 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
3172 return;
3173 }
3174
Steven Timotiusaf03df62017-07-18 16:56:43 -07003175 final long token = proto.start(fieldId);
3176 writeNameToProto(proto, NAME);
Nataniel Borges023ecb52019-01-16 14:15:43 -08003177 super.writeToProto(proto, WINDOW_TOKEN, logLevel);
Vishnu Nair04ab4392018-01-10 11:00:06 -08003178 proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing);
3179 proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart());
3180 proto.write(IS_REALLY_ANIMATING, isReallyAnimating());
3181 if (mThumbnail != null){
3182 mThumbnail.writeToProto(proto, THUMBNAIL);
3183 }
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -07003184 proto.write(FILLS_PARENT, mOccludesParent);
Vishnu Nair04ab4392018-01-10 11:00:06 -08003185 proto.write(APP_STOPPED, mAppStopped);
3186 proto.write(HIDDEN_REQUESTED, hiddenRequested);
3187 proto.write(CLIENT_HIDDEN, mClientHidden);
3188 proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient);
3189 proto.write(REPORTED_DRAWN, reportedDrawn);
3190 proto.write(REPORTED_VISIBLE, reportedVisible);
3191 proto.write(NUM_INTERESTING_WINDOWS, mNumInterestingWindows);
3192 proto.write(NUM_DRAWN_WINDOWS, mNumDrawnWindows);
3193 proto.write(ALL_DRAWN, allDrawn);
3194 proto.write(LAST_ALL_DRAWN, mLastAllDrawn);
3195 proto.write(REMOVED, removed);
Nataniel Borges023ecb52019-01-16 14:15:43 -08003196 if (startingWindow != null) {
Vishnu Nair04ab4392018-01-10 11:00:06 -08003197 startingWindow.writeIdentifierToProto(proto, STARTING_WINDOW);
3198 }
3199 proto.write(STARTING_DISPLAYED, startingDisplayed);
3200 proto.write(STARTING_MOVED, startingMoved);
3201 proto.write(HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW,
3202 mHiddenSetFromTransferredStartingWindow);
3203 for (Rect bounds : mFrozenBounds) {
3204 bounds.writeToProto(proto, FROZEN_BOUNDS);
3205 }
Steven Timotiusaf03df62017-07-18 16:56:43 -07003206 proto.end(token);
3207 }
3208
3209 void writeNameToProto(ProtoOutputStream proto, long fieldId) {
3210 if (appToken == null) {
3211 return;
3212 }
3213 try {
3214 proto.write(fieldId, appToken.getName());
3215 } catch (RemoteException e) {
3216 // This shouldn't happen, but in this case fall back to outputting nothing
3217 Slog.e(TAG, e.toString());
3218 }
3219 }
3220
3221 @Override
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003222 public String toString() {
3223 if (stringName == null) {
3224 StringBuilder sb = new StringBuilder();
3225 sb.append("AppWindowToken{");
3226 sb.append(Integer.toHexString(System.identityHashCode(this)));
3227 sb.append(" token="); sb.append(token); sb.append('}');
3228 stringName = sb.toString();
3229 }
Wale Ogunwaleba51ca22016-09-23 06:06:54 -07003230 return stringName + ((mIsExiting) ? " mIsExiting=" : "");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003231 }
Adrian Roos20e07892018-02-23 19:12:01 +01003232
3233 Rect getLetterboxInsets() {
3234 if (mLetterbox != null) {
3235 return mLetterbox.getInsets();
3236 } else {
3237 return new Rect();
3238 }
3239 }
Adrian Roos23df3a32018-03-15 15:41:13 +01003240
Riddle Hsu69de5fb2019-02-23 01:19:50 +08003241 /** Gets the inner bounds of letterbox. The bounds will be empty if there is no letterbox. */
3242 void getLetterboxInnerBounds(Rect outBounds) {
3243 if (mLetterbox != null) {
3244 outBounds.set(mLetterbox.getInnerFrame());
3245 } else {
3246 outBounds.setEmpty();
3247 }
3248 }
3249
Adrian Roos23df3a32018-03-15 15:41:13 +01003250 /**
Riddle Hsu69de5fb2019-02-23 01:19:50 +08003251 * @return {@code true} if there is a letterbox and any part of that letterbox overlaps with
Adrian Roos23df3a32018-03-15 15:41:13 +01003252 * the given {@code rect}.
3253 */
3254 boolean isLetterboxOverlappingWith(Rect rect) {
3255 return mLetterbox != null && mLetterbox.isOverlappingWith(rect);
3256 }
chaviw4ad54912018-05-30 11:05:44 -07003257
3258 /**
3259 * Sets if this AWT is in the process of closing or entering PIP.
3260 * {@link #mWillCloseOrEnterPip}}
3261 */
3262 void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
3263 mWillCloseOrEnterPip = willCloseOrEnterPip;
3264 }
3265
3266 /**
3267 * Returns whether this AWT is considered closing. Conditions are either
3268 * 1. Is this app animating and was requested to be hidden
3269 * 2. App is delayed closing since it might enter PIP.
3270 */
3271 boolean isClosingOrEnteringPip() {
3272 return (isAnimating() && hiddenRequested) || mWillCloseOrEnterPip;
3273 }
Jorim Jaggiaf0d6d22018-06-08 15:25:35 +02003274
3275 /**
3276 * @return Whether we are allowed to show non-starting windows at the moment. We disallow
3277 * showing windows during transitions in case we have windows that have wide-color-gamut
3278 * color mode set to avoid jank in the middle of the transition.
3279 */
3280 boolean canShowWindows() {
3281 return allDrawn && !(isReallyAnimating() && hasNonDefaultColorWindow());
3282 }
3283
3284 /**
3285 * @return true if we have a window that has a non-default color mode set; false otherwise.
3286 */
3287 private boolean hasNonDefaultColorWindow() {
3288 return forAllWindows(ws -> ws.mAttrs.getColorMode() != COLOR_MODE_DEFAULT,
3289 true /* topToBottom */);
3290 }
lumark588a3e82018-07-20 18:53:54 +08003291
chaviwdcf76ec2019-01-11 16:48:46 -08003292 private void updateColorTransform() {
3293 if (mSurfaceControl != null && mLastAppSaturationInfo != null) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003294 getPendingTransaction().setColorTransform(mSurfaceControl,
3295 mLastAppSaturationInfo.mMatrix, mLastAppSaturationInfo.mTranslation);
chaviwdcf76ec2019-01-11 16:48:46 -08003296 mWmService.scheduleAnimationLocked();
3297 }
3298 }
3299
3300 private static class AppSaturationInfo {
3301 float[] mMatrix = new float[9];
3302 float[] mTranslation = new float[3];
3303
3304 void setSaturation(@Size(9) float[] matrix, @Size(3) float[] translation) {
3305 System.arraycopy(matrix, 0, mMatrix, 0, mMatrix.length);
3306 System.arraycopy(translation, 0, mTranslation, 0, mTranslation.length);
3307 }
3308 }
Jeff Browne9bdb312012-04-05 15:30:10 -07003309}