blob: 266862820017e791ae209e29eb43b88073ae308a [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;
Adrian Roosb125e0b2019-10-02 14:55:14 +020065import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
66import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
67import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
68import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
69import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
70import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
chaviw9c81e632018-07-31 11:17:52 -070071import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
chaviw9c81e632018-07-31 11:17:52 -070072import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
chaviw9c81e632018-07-31 11:17:52 -070073import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
chaviw9c81e632018-07-31 11:17:52 -070074import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
chaviw9c81e632018-07-31 11:17:52 -070075import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
76import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
77import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN;
78import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
79import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
80import static com.android.server.wm.WindowManagerService.logWithStack;
chaviw15ad49f2019-04-24 15:05:39 -070081import static com.android.server.wm.WindowState.LEGACY_POLICY_VISIBILITY;
Jorim Jaggi6ec52d42019-07-03 15:45:59 +020082import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
Vishnu Naira2977262018-07-26 13:31:26 -070083import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
Evan Rosky641daea2019-04-24 14:45:24 -070084import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080085
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070086import android.annotation.CallSuper;
chaviwdcf76ec2019-01-11 16:48:46 -080087import android.annotation.Size;
Jorim Jaggid635a4a2017-05-03 15:21:26 +020088import android.app.Activity;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080089import android.app.ActivityManager;
Winson Chung48b25652018-10-22 14:04:30 -070090import android.content.ComponentName;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080091import android.content.res.CompatibilityInfo;
Jorim Jaggi26c8c422016-05-09 19:57:25 -070092import android.content.res.Configuration;
Jorim Jaggi988f6682017-11-17 17:46:43 +010093import android.graphics.GraphicBuffer;
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -070094import android.graphics.PixelFormat;
Jorim Jaggif5f9e122017-10-24 18:21:09 +020095import android.graphics.Point;
Jorim Jaggi0429f352015-12-22 16:29:16 +010096import android.graphics.Rect;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -070097import android.os.Binder;
Tiger Huang51c5a1d2018-12-11 20:24:51 +080098import android.os.Build;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -080099import android.os.Debug;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700100import android.os.IBinder;
Steven Timotiusaf03df62017-07-18 16:56:43 -0700101import android.os.RemoteException;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800102import android.os.SystemClock;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200103import android.os.Trace;
Evan Rosky2289ba12018-11-19 18:28:18 -0800104import android.util.ArraySet;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800105import android.util.Slog;
Steven Timotiusaf03df62017-07-18 16:56:43 -0700106import android.util.proto.ProtoOutputStream;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200107import android.view.DisplayInfo;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800108import android.view.IApplicationToken;
Robert Carr788f5742018-07-30 17:46:45 -0700109import android.view.InputApplicationHandle;
Evan Rosky966759f2019-01-15 10:33:58 -0800110import android.view.RemoteAnimationAdapter;
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100111import android.view.RemoteAnimationDefinition;
Robert Carr6914f082017-03-20 19:04:30 -0700112import android.view.SurfaceControl;
Tony Mak64b8d562017-12-28 17:44:02 +0000113import android.view.SurfaceControl.Transaction;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800114import android.view.WindowManager;
Jorim Jaggi87fdbcb2017-08-17 13:41:11 +0200115import android.view.WindowManager.LayoutParams;
Tony Mak64b8d562017-12-28 17:44:02 +0000116import android.view.animation.Animation;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800117
Tony Mak64b8d562017-12-28 17:44:02 +0000118import com.android.internal.R;
Riddle Hsua118b3a2018-10-11 22:05:06 +0800119import com.android.internal.annotations.VisibleForTesting;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800120import com.android.internal.util.ToBooleanFunction;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800121import com.android.server.AttributeCache;
chaviwdcf76ec2019-01-11 16:48:46 -0800122import com.android.server.LocalServices;
Christine Franks0ada2772019-02-25 13:54:57 -0800123import com.android.server.display.color.ColorDisplayService;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800124import com.android.server.policy.WindowManagerPolicy;
Adrian Roose99bc052017-11-20 17:55:31 +0100125import com.android.server.policy.WindowManagerPolicy.StartingSurface;
Adrian Roosb125e0b2019-10-02 14:55:14 +0200126import com.android.server.protolog.common.ProtoLog;
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) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200391 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Finish starting %s"
392 + ": first real window is shown, no animation", win.mToken);
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800393 // 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 }
Adrian Roosb125e0b2019-10-02 14:55:14 +0200483 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
484 "setClientHidden: %s clientHidden=%b Callers=%s", this, hideClient,
485 Debug.getCallers(5));
Wale Ogunwale89973222017-04-23 18:39:45 -0700486 mClientHidden = hideClient;
487 sendAppVisibilityToClients();
488 }
489
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800490 void setVisibility(boolean visible, boolean deferHidingClient) {
491 final AppTransition appTransition = getDisplayContent().mAppTransition;
492
493 // Don't set visibility to false if we were already not visible. This prevents WM from
494 // adding the app to the closing app list which doesn't make sense for something that is
495 // already not visible. However, set visibility to true even if we are already visible.
496 // This makes sure the app is added to the opening apps list so that the right
497 // transition can be selected.
498 // TODO: Probably a good idea to separate the concept of opening/closing apps from the
499 // concept of setting visibility...
500 if (!visible && hiddenRequested) {
501
502 if (!deferHidingClient && mDeferHidingClient) {
503 // We previously deferred telling the client to hide itself when visibility was
504 // initially set to false. Now we would like it to hide, so go ahead and set it.
505 mDeferHidingClient = deferHidingClient;
506 setClientHidden(true);
507 }
508 return;
509 }
510
Adrian Roosb125e0b2019-10-02 14:55:14 +0200511 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
512 "setAppVisibility(%s, visible=%b): %s hidden=%b hiddenRequested=%b Callers=%s",
513 appToken, visible, appTransition, isHidden(), hiddenRequested,
514 Debug.getCallers(6));
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800515
516 final DisplayContent displayContent = getDisplayContent();
517 displayContent.mOpeningApps.remove(this);
518 displayContent.mClosingApps.remove(this);
Evan Roskyb1e75f72019-04-26 20:23:26 -0700519 if (isInChangeTransition()) {
520 clearChangeLeash(getPendingTransaction(), true /* cancel */);
521 }
522 displayContent.mChangingApps.remove(this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800523 waitingToShow = false;
524 hiddenRequested = !visible;
525 mDeferHidingClient = deferHidingClient;
526
527 if (!visible) {
528 // If the app is dead while it was visible, we kept its dead window on screen.
529 // Now that the app is going invisible, we can remove it. It will be restarted
530 // if made visible again.
531 removeDeadWindows();
532 } else {
533 if (!appTransition.isTransitionSet()
534 && appTransition.isReady()) {
535 // Add the app mOpeningApps if transition is unset but ready. This means
536 // we're doing a screen freeze, and the unfreeze will wait for all opening
537 // apps to be ready.
538 displayContent.mOpeningApps.add(this);
539 }
540 startingMoved = false;
541 // If the token is currently hidden (should be the common case), or has been
542 // stopped, then we need to set up to wait for its windows to be ready.
543 if (isHidden() || mAppStopped) {
544 clearAllDrawn();
545
546 // If the app was already visible, don't reset the waitingToShow state.
547 if (isHidden()) {
548 waitingToShow = true;
Jorim Jaggi6ec52d42019-07-03 15:45:59 +0200549
wilsonshih78e55422019-09-10 09:44:51 +0800550 // If the client isn't hidden, we don't need to reset the drawing state.
551 if (isClientHidden()) {
552 // Let's reset the draw state in order to prevent the starting window to be
553 // immediately dismissed when the app still has the surface.
554 forAllWindows(w -> {
555 if (w.mWinAnimator.mDrawState == HAS_DRAWN) {
556 w.mWinAnimator.resetDrawState();
Jorim Jaggi6ec52d42019-07-03 15:45:59 +0200557
wilsonshih78e55422019-09-10 09:44:51 +0800558 // Force add to mResizingWindows, so that we are guaranteed to get
559 // another reportDrawn callback.
560 w.resetLastContentInsets();
561 }
562 }, true /* traverseTopToBottom */);
563 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800564 }
565 }
566
567 // In the case where we are making an app visible but holding off for a transition,
568 // we still need to tell the client to make its windows visible so they get drawn.
569 // Otherwise, we will wait on performing the transition until all windows have been
570 // drawn, they never will be, and we are sad.
571 setClientHidden(false);
572
573 requestUpdateWallpaperIfNeeded();
574
Adrian Roosb125e0b2019-10-02 14:55:14 +0200575 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "No longer Stopped: %s", this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800576 mAppStopped = false;
577
578 transferStartingWindowFromHiddenAboveTokenIfNeeded();
579 }
580
581 // If we are preparing an app transition, then delay changing
582 // the visibility of this token until we execute that transition.
583 if (okToAnimate() && appTransition.isTransitionSet()) {
584 inPendingTransaction = true;
585 if (visible) {
586 displayContent.mOpeningApps.add(this);
587 mEnteringAnimation = true;
588 } else {
589 displayContent.mClosingApps.add(this);
590 mEnteringAnimation = false;
591 }
Louis Chang37317152019-05-09 09:53:58 +0800592 if (appTransition.getAppTransition() == TRANSIT_TASK_OPEN_BEHIND) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800593 // We're launchingBehind, add the launching activity to mOpeningApps.
594 final WindowState win = getDisplayContent().findFocusedWindow();
595 if (win != null) {
596 final AppWindowToken focusedToken = win.mAppToken;
597 if (focusedToken != null) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200598 ProtoLog.d(WM_DEBUG_APP_TRANSITIONS,
599 "TRANSIT_TASK_OPEN_BEHIND, adding %s to mOpeningApps",
600 focusedToken);
601
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800602 // Force animation to be loaded.
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800603 displayContent.mOpeningApps.add(focusedToken);
604 }
605 }
606 }
Garfield Tanb6776602019-02-20 14:44:26 -0800607 // Changes in opening apps and closing apps may cause orientation change.
608 reportDescendantOrientationChangeIfNeeded();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800609 return;
610 }
611
612 commitVisibility(null, visible, TRANSIT_UNSET, true, mVoiceInteraction);
613 updateReportedVisibilityLocked();
614 }
615
616 boolean commitVisibility(WindowManager.LayoutParams lp,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700617 boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
618
619 boolean delayed = false;
620 inPendingTransaction = false;
Wale Ogunwale9e4721f2017-05-23 19:37:30 -0700621 // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually
622 // been set by the app now.
623 mHiddenSetFromTransferredStartingWindow = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700624
625 // Allow for state changes and animation to be applied if:
626 // * token is transitioning visibility state
627 // * or the token was marked as hidden and is exiting before we had a chance to play the
628 // transition animation
Louis Chang37317152019-05-09 09:53:58 +0800629 // * or this is an opening app and windows are being replaced
630 // * or the token is the opening app and visible while opening task behind existing one.
631 final DisplayContent displayContent = getDisplayContent();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700632 boolean visibilityChanged = false;
Louis Chang37317152019-05-09 09:53:58 +0800633 if (isHidden() == visible || (isHidden() && mIsExiting)
634 || (visible && waitingForReplacement())
635 || (visible && displayContent.mOpeningApps.contains(this)
636 && displayContent.mAppTransition.getAppTransition() == TRANSIT_TASK_OPEN_BEHIND)) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800637 final AccessibilityController accessibilityController =
638 mWmService.mAccessibilityController;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700639 boolean changed = false;
Adrian Roosb125e0b2019-10-02 14:55:14 +0200640 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
641 "Changing app %s hidden=%b performLayout=%b", this, isHidden(),
642 performLayout);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700643
644 boolean runningAppAnimation = false;
645
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100646 if (transit != WindowManager.TRANSIT_UNSET) {
Tiger Huangc9d0d002019-05-29 22:55:29 +0800647 if (mUseTransferredAnimation) {
648 runningAppAnimation = isReallyAnimating();
649 } else if (applyAnimationLocked(lp, transit, visible, isVoiceInteraction)) {
650 runningAppAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700651 }
Tiger Huangc9d0d002019-05-29 22:55:29 +0800652 delayed = runningAppAnimation;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700653 final WindowState window = findMainWindow();
Rhed Jao02655dc2018-10-30 20:44:52 +0800654 if (window != null && accessibilityController != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700655 accessibilityController.onAppWindowTransitionLocked(window, transit);
656 }
657 changed = true;
658 }
659
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700660 final int windowsCount = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700661 for (int i = 0; i < windowsCount; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700662 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700663 changed |= win.onAppVisibilityChanged(visible, runningAppAnimation);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700664 }
665
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200666 setHidden(!visible);
667 hiddenRequested = !visible;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700668 visibilityChanged = true;
669 if (!visible) {
670 stopFreezingScreen(true, true);
671 } else {
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700672 // If we are being set visible, and the starting window is not yet displayed,
673 // then make sure it doesn't get displayed.
674 if (startingWindow != null && !startingWindow.isDrawnLw()) {
chaviw15ad49f2019-04-24 15:05:39 -0700675 startingWindow.clearPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY);
676 startingWindow.mLegacyPolicyVisibilityAfterAnim = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700677 }
Jorim Jaggi38d44ec2017-06-14 16:04:59 -0700678
679 // We are becoming visible, so better freeze the screen with the windows that are
680 // getting visible so we also wait for them.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800681 forAllWindows(mWmService::makeWindowFreezingScreenIfNeededLocked, true);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700682 }
683
Adrian Roosb125e0b2019-10-02 14:55:14 +0200684 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
685 "commitVisibility: %s: hidden=%b hiddenRequested=%b", this,
686 isHidden(), hiddenRequested);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700687
688 if (changed) {
Louis Chang37317152019-05-09 09:53:58 +0800689 displayContent.getInputMonitor().setUpdateInputWindowsNeededLw();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700690 if (performLayout) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800691 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700692 false /*updateInputWindows*/);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800693 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700694 }
Louis Chang37317152019-05-09 09:53:58 +0800695 displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700696 }
697 }
Tiger Huangc9d0d002019-05-29 22:55:29 +0800698 mUseTransferredAnimation = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700699
lumarkd14173e2019-03-27 19:14:33 +0800700 if (isReallyAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700701 delayed = true;
Jorim Jaggiab9fcb22018-03-15 23:46:12 +0100702 } else {
703
704 // We aren't animating anything, but exiting windows rely on the animation finished
705 // callback being called in case the AppWindowToken was pretending to be animating,
706 // which we might have done because we were in closing/opening apps list.
707 onAnimationFinished();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700708 }
709
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700710 for (int i = mChildren.size() - 1; i >= 0 && !delayed; i--) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100711 if ((mChildren.get(i)).isSelfOrChildAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700712 delayed = true;
713 }
714 }
715
716 if (visibilityChanged) {
717 if (visible && !delayed) {
718 // The token was made immediately visible, there will be no entrance animation.
719 // We need to inform the client the enter animation was finished.
720 mEnteringAnimation = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800721 mWmService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(
722 token);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700723 }
Robert Carr61b81112017-07-17 18:08:15 -0700724
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800725 // If we're becoming visible, immediately change client visibility as well. there seem
726 // to be some edge cases where we change our visibility but client visibility never gets
727 // updated.
Jorim Jaggi110839b2018-01-22 12:49:04 +0100728 // If we're becoming invisible, update the client visibility if we are not running an
729 // animation. Otherwise, we'll update client visibility in onAnimationFinished.
Jorim Jaggi3cad57f2018-02-20 18:32:01 +0100730 if (visible || !isReallyAnimating()) {
Jorim Jaggi110839b2018-01-22 12:49:04 +0100731 setClientHidden(!visible);
Jorim Jaggi4876b4a2018-01-11 15:43:49 +0100732 }
733
Louis Chang37317152019-05-09 09:53:58 +0800734 if (!displayContent.mClosingApps.contains(this)
735 && !displayContent.mOpeningApps.contains(this)) {
chaviwa953fcf2018-03-01 12:00:39 -0800736 // The token is not closing nor opening, so even if there is an animation set, that
737 // doesn't mean that it goes through the normal app transition cycle so we have
738 // to inform the docked controller about visibility change.
739 // TODO(multi-display): notify docked divider on all displays where visibility was
740 // affected.
Louis Chang37317152019-05-09 09:53:58 +0800741 displayContent.getDockedDividerController().notifyAppVisibilityChanged();
chaviwa953fcf2018-03-01 12:00:39 -0800742
743 // Take the screenshot before possibly hiding the WSA, otherwise the screenshot
744 // will not be taken.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800745 mWmService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible);
chaviwa953fcf2018-03-01 12:00:39 -0800746 }
747
Robert Carre7cc44d2017-03-20 19:04:30 -0700748 // If we are hidden but there is no delay needed we immediately
749 // apply the Surface transaction so that the ActivityManager
Robert Carr61b81112017-07-17 18:08:15 -0700750 // can have some guarantee on the Surface state following
751 // setting the visibility. This captures cases like dismissing
752 // the docked or pinned stack where there is no app transition.
753 //
754 // In the case of a "Null" animation, there will be
755 // no animation but there will still be a transition set.
756 // We still need to delay hiding the surface such that it
757 // can be synchronized with showing the next surface in the transition.
Louis Chang37317152019-05-09 09:53:58 +0800758 if (isHidden() && !delayed && !displayContent.mAppTransition.isTransitionSet()) {
Robert Carr6914f082017-03-20 19:04:30 -0700759 SurfaceControl.openTransaction();
760 for (int i = mChildren.size() - 1; i >= 0; i--) {
761 mChildren.get(i).mWinAnimator.hide("immediately hidden");
762 }
763 SurfaceControl.closeTransaction();
764 }
Garfield Tanb6776602019-02-20 14:44:26 -0800765
766 // Visibility changes may cause orientation request change.
767 reportDescendantOrientationChangeIfNeeded();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700768 }
769
770 return delayed;
771 }
772
Garfield Tanb6776602019-02-20 14:44:26 -0800773 private void reportDescendantOrientationChangeIfNeeded() {
774 // Orientation request is exposed only when we're visible. Therefore visibility change
775 // will change requested orientation. Notify upward the hierarchy ladder to adjust
776 // configuration. This is important to cases where activities with incompatible
777 // orientations launch, or user goes back from an activity of bi-orientation to an
778 // activity with specified orientation.
779 if (mActivityRecord.getRequestedConfigurationOrientation() == getConfiguration().orientation
780 || getOrientationIgnoreVisibility() == SCREEN_ORIENTATION_UNSET) {
781 return;
782 }
783
784 final IBinder freezeToken =
785 mActivityRecord.mayFreezeScreenLocked(mActivityRecord.app)
786 ? mActivityRecord.appToken : null;
787 onDescendantOrientationChanged(freezeToken, mActivityRecord);
788 }
789
Jorim Jaggi87fdbcb2017-08-17 13:41:11 +0200790 /**
791 * @return The to top most child window for which {@link LayoutParams#isFullscreen()} returns
792 * true.
793 */
794 WindowState getTopFullscreenWindow() {
795 for (int i = mChildren.size() - 1; i >= 0; i--) {
796 final WindowState win = mChildren.get(i);
797 if (win != null && win.mAttrs.isFullscreen()) {
798 return win;
799 }
800 }
801 return null;
802 }
803
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800804 WindowState findMainWindow() {
Matthew Ng53e66b22018-01-12 17:13:13 -0800805 return findMainWindow(true);
806 }
807
808 /**
809 * Finds the main window that either has type base application or application starting if
810 * requested.
811 *
812 * @param includeStartingApp Allow to search application-starting windows to also be returned.
813 * @return The main window of type base application or application starting if requested.
814 */
815 WindowState findMainWindow(boolean includeStartingApp) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700816 WindowState candidate = null;
Matthew Ng53e66b22018-01-12 17:13:13 -0800817 for (int j = mChildren.size() - 1; j >= 0; --j) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700818 final WindowState win = mChildren.get(j);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700819 final int type = win.mAttrs.type;
820 // No need to loop through child window as base application and starting types can't be
821 // child windows.
Matthew Ng53e66b22018-01-12 17:13:13 -0800822 if (type == TYPE_BASE_APPLICATION
823 || (includeStartingApp && type == TYPE_APPLICATION_STARTING)) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700824 // In cases where there are multiple windows, we prefer the non-exiting window. This
Sungsoo Lim0d3d1f82015-12-02 14:47:59 +0900825 // happens for example when replacing windows during an activity relaunch. When
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700826 // constructing the animation, we want the new window, not the exiting one.
Wale Ogunwalec48a3542016-02-19 15:18:45 -0800827 if (win.mAnimatingExit) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700828 candidate = win;
829 } else {
830 return win;
831 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800832 }
833 }
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700834 return candidate;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800835 }
836
Wale Ogunwale6cae7652015-12-26 07:36:26 -0800837 boolean windowsAreFocusable() {
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800838 if (mTargetSdk < Build.VERSION_CODES.Q) {
839 final int pid = mActivityRecord != null
840 ? (mActivityRecord.app != null ? mActivityRecord.app.getPid() : 0) : 0;
841 final AppWindowToken topFocusedAppOfMyProcess =
842 mWmService.mRoot.mTopFocusedAppByProcess.get(pid);
843 if (topFocusedAppOfMyProcess != null && topFocusedAppOfMyProcess != this) {
844 // For the apps below Q, there can be only one app which has the focused window per
845 // process, because legacy apps may not be ready for a multi-focus system.
846 return false;
847 }
848 }
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700849 return getWindowConfiguration().canReceiveKeys() || mAlwaysFocusable;
Wale Ogunwaled045c822015-12-02 09:14:28 -0800850 }
851
Wale Ogunwale571771c2016-08-26 13:18:50 -0700852 @Override
Wale Ogunwale44f21802016-09-02 12:49:48 -0700853 boolean isVisible() {
Wale Ogunwalee471be62016-10-03 07:53:55 -0700854 // If the app token isn't hidden then it is considered visible and there is no need to check
855 // its children windows to see if they are visible.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200856 return !isHidden();
Wale Ogunwale44f21802016-09-02 12:49:48 -0700857 }
858
859 @Override
Wale Ogunwalee287e192017-04-21 09:30:12 -0700860 void removeImmediately() {
861 onRemovedFromDisplay();
Yunfan Chen3a77f282018-12-12 15:47:52 -0800862 if (mActivityRecord != null) {
863 mActivityRecord.unregisterConfigurationChangeListener(this);
864 }
Wale Ogunwalee287e192017-04-21 09:30:12 -0700865 super.removeImmediately();
866 }
867
868 @Override
Wale Ogunwale571771c2016-08-26 13:18:50 -0700869 void removeIfPossible() {
Craig Mautnere3119b72015-01-20 15:02:36 -0800870 mIsExiting = false;
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800871 removeAllWindowsIfPossible();
Bryce Lee6d410262017-02-28 15:30:17 -0800872 removeImmediately();
Craig Mautnere3119b72015-01-20 15:02:36 -0800873 }
874
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700875 @Override
876 boolean checkCompleteDeferredRemoval() {
877 if (mIsExiting) {
878 removeIfPossible();
879 }
880 return super.checkCompleteDeferredRemoval();
881 }
882
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700883 void onRemovedFromDisplay() {
Wale Ogunwalee287e192017-04-21 09:30:12 -0700884 if (mRemovingFromDisplay) {
885 return;
886 }
887 mRemovingFromDisplay = true;
888
Adrian Roosb125e0b2019-10-02 14:55:14 +0200889 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Removing app token: %s", this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700890
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800891 boolean delayed = commitVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700892
lumark588a3e82018-07-20 18:53:54 +0800893 getDisplayContent().mOpeningApps.remove(this);
Evan Rosky2289ba12018-11-19 18:28:18 -0800894 getDisplayContent().mChangingApps.remove(this);
lumark588a3e82018-07-20 18:53:54 +0800895 getDisplayContent().mUnknownAppVisibilityController.appRemovedOrHidden(this);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800896 mWmService.mTaskSnapshotController.onAppRemoved(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700897 waitingToShow = false;
lumark588a3e82018-07-20 18:53:54 +0800898 if (getDisplayContent().mClosingApps.contains(this)) {
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700899 delayed = true;
lumark588a3e82018-07-20 18:53:54 +0800900 } else if (getDisplayContent().mAppTransition.isTransitionSet()) {
901 getDisplayContent().mClosingApps.add(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700902 delayed = true;
903 }
904
Adrian Roosb125e0b2019-10-02 14:55:14 +0200905 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
906 "Removing app %s delayed=%b animation=%s animating=%b", this, delayed,
907 getAnimation(), isSelfAnimating());
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700908
Adrian Roosb125e0b2019-10-02 14:55:14 +0200909 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "removeAppToken: %s"
910 + " delayed=%b Callers=%s", this, delayed, Debug.getCallers(4));
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700911
chaviwa8f07a72019-05-01 16:25:39 -0700912 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800913 removeStartingWindow();
Jorim Jaggi19be6052017-08-03 18:33:43 +0200914 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800915
Winson Chung87e5d552017-04-05 11:49:38 -0700916 // If this window was animating, then we need to ensure that the app transition notifies
lumark588a3e82018-07-20 18:53:54 +0800917 // that animations have completed in DisplayContent.handleAnimatingStoppedAndTransition(),
918 // so add to that list now
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200919 if (isSelfAnimating()) {
lumark588a3e82018-07-20 18:53:54 +0800920 getDisplayContent().mNoAnimationNotifyOnTransitionFinished.add(token);
Winson Chung87e5d552017-04-05 11:49:38 -0700921 }
922
Wale Ogunwalee287e192017-04-21 09:30:12 -0700923 final TaskStack stack = getStack();
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700924 if (delayed && !isEmpty()) {
925 // set the token aside because it has an active animation to be finished
Adrian Roosb125e0b2019-10-02 14:55:14 +0200926 ProtoLog.v(WM_DEBUG_ADD_REMOVE,
927 "removeAppToken make exiting: %s", this);
Wale Ogunwalee287e192017-04-21 09:30:12 -0700928 if (stack != null) {
929 stack.mExitingAppTokens.add(this);
930 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700931 mIsExiting = true;
932 } else {
933 // Make sure there is no animation running on this token, so any windows associated
934 // with it will be removed as soon as their animations are complete
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200935 cancelAnimation();
Wale Ogunwale3106ae012017-05-16 08:56:37 -0700936 if (stack != null) {
937 stack.mExitingAppTokens.remove(this);
938 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700939 removeIfPossible();
940 }
941
942 removed = true;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700943 stopFreezingScreen(true, true);
Bryce Lee6d410262017-02-28 15:30:17 -0800944
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800945 final DisplayContent dc = getDisplayContent();
946 if (dc.mFocusedApp == this) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200947 ProtoLog.v(WM_DEBUG_FOCUS_LIGHT,
948 "Removing focused app token:%s displayId=%d", this,
949 dc.getDisplayId());
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800950 dc.setFocusedApp(null);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800951 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700952 }
Riddle Hsu192fe762019-01-15 23:41:57 +0800953 if (mLetterbox != null) {
954 mLetterbox.destroy();
955 mLetterbox = null;
956 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700957
958 if (!delayed) {
959 updateReportedVisibilityLocked();
960 }
Wale Ogunwalee287e192017-04-21 09:30:12 -0700961
Hongwei Wang75b6e6c2019-09-17 10:07:56 -0700962 // Reset the last saved PiP snap fraction on removal.
963 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(mActivityComponent);
964
Wale Ogunwalee287e192017-04-21 09:30:12 -0700965 mRemovingFromDisplay = false;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700966 }
967
Chong Zhange05bcb12016-07-26 17:47:29 -0700968 void clearAnimatingFlags() {
Chong Zhangb0d26702016-08-12 16:03:29 -0700969 boolean wallpaperMightChange = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700970 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700971 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700972 wallpaperMightChange |= win.clearAnimatingFlags();
Chong Zhange05bcb12016-07-26 17:47:29 -0700973 }
Chong Zhangb0d26702016-08-12 16:03:29 -0700974 if (wallpaperMightChange) {
975 requestUpdateWallpaperIfNeeded();
976 }
Chong Zhange05bcb12016-07-26 17:47:29 -0700977 }
978
Robert Carre12aece2016-02-02 22:43:27 -0800979 void destroySurfaces() {
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700980 destroySurfaces(false /*cleanupOnResume*/);
981 }
982
983 /**
984 * Destroy surfaces which have been marked as eligible by the animator, taking care to ensure
985 * the client has finished with them.
986 *
987 * @param cleanupOnResume whether this is done when app is resumed without fully stopped. If
988 * set to true, destroy only surfaces of removed windows, and clear relevant flags of the
989 * others so that they are ready to be reused. If set to false (common case), destroy all
990 * surfaces that's eligible, if the app is already stopped.
991 */
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700992 private void destroySurfaces(boolean cleanupOnResume) {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700993 boolean destroyedSomething = false;
Jorim Jaggia5e10572017-11-15 14:36:26 +0100994
995 // Copying to a different list as multiple children can be removed.
Jorim Jaggi59f3e922018-01-05 15:40:32 +0100996 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
Jorim Jaggia5e10572017-11-15 14:36:26 +0100997 for (int i = children.size() - 1; i >= 0; i--) {
998 final WindowState win = children.get(i);
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700999 destroyedSomething |= win.destroySurface(cleanupOnResume, mAppStopped);
Robert Carre12aece2016-02-02 22:43:27 -08001000 }
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001001 if (destroyedSomething) {
1002 final DisplayContent dc = getDisplayContent();
Wale Ogunwalec69694a2016-10-18 13:51:15 -07001003 dc.assignWindowLayers(true /*setLayoutNeeded*/);
Adrian Roos23df3a32018-03-15 15:41:13 +01001004 updateLetterboxSurface(null);
Robert Carre12aece2016-02-02 22:43:27 -08001005 }
1006 }
1007
Wale Ogunwale8d5a5422016-03-03 18:28:21 -08001008 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001009 * Notify that the app is now resumed, and it was not stopped before, perform a clean
1010 * up of the surfaces
Wale Ogunwale8d5a5422016-03-03 18:28:21 -08001011 */
Jorim Jaggibae01b12017-04-11 16:29:10 -07001012 void notifyAppResumed(boolean wasStopped) {
Adrian Roosb125e0b2019-10-02 14:55:14 +02001013 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "notifyAppResumed: wasStopped=%b %s",
1014 wasStopped, this);
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001015 mAppStopped = false;
chaviwd3bf08d2017-08-01 17:24:59 -07001016 // Allow the window to turn the screen on once the app is resumed again.
Riddle Hsu4bb06be2019-07-02 01:03:07 +08001017 setCurrentLaunchCanTurnScreenOn(true);
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001018 if (!wasStopped) {
1019 destroySurfaces(true /*cleanupOnResume*/);
Wale Ogunwale8d5a5422016-03-03 18:28:21 -08001020 }
Robert Carre12aece2016-02-02 22:43:27 -08001021 }
1022
Chong Zhangbef461f2015-10-27 11:38:24 -07001023 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001024 * Notify that the app has stopped, and it is okay to destroy any surfaces which were
1025 * keeping alive in case they were still being used.
1026 */
1027 void notifyAppStopped() {
Adrian Roosb125e0b2019-10-02 14:55:14 +02001028 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "notifyAppStopped: %s", this);
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001029 mAppStopped = true;
Hongwei Wanga5799f82019-07-01 15:52:50 -07001030 // Reset the last saved PiP snap fraction on app stop.
Hongwei Wang43a752b2019-09-17 20:20:30 +00001031 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(mActivityComponent);
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001032 destroySurfaces();
1033 // Remove any starting window that was added for this app if they are still around.
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001034 removeStartingWindow();
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001035 }
1036
Chong Zhang92147042016-05-09 12:47:11 -07001037 void clearAllDrawn() {
1038 allDrawn = false;
1039 deferClearAllDrawn = false;
Chong Zhangbef461f2015-10-27 11:38:24 -07001040 }
1041
Bryce Lee6d410262017-02-28 15:30:17 -08001042 Task getTask() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001043 return (Task) getParent();
Bryce Lee6d410262017-02-28 15:30:17 -08001044 }
1045
Jorim Jaggi3878ca32017-02-02 17:13:05 -08001046 TaskStack getStack() {
1047 final Task task = getTask();
1048 if (task != null) {
1049 return task.mStack;
1050 } else {
1051 return null;
1052 }
1053 }
1054
Bryce Lee6d410262017-02-28 15:30:17 -08001055 @Override
Riddle Hsu3a4bb612019-01-31 00:02:22 +08001056 void onParentChanged() {
1057 super.onParentChanged();
Bryce Lee6d410262017-02-28 15:30:17 -08001058
Robert Carred3e83b2017-04-21 13:26:55 -07001059 final Task task = getTask();
1060
Bryce Lee6d410262017-02-28 15:30:17 -08001061 // When the associated task is {@code null}, the {@link AppWindowToken} can no longer
1062 // access visual elements like the {@link DisplayContent}. We must remove any associations
1063 // such as animations.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001064 if (!mReparenting) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001065 if (task == null) {
1066 // It is possible we have been marked as a closing app earlier. We must remove ourselves
1067 // from this list so we do not participate in any future animations.
lumark588a3e82018-07-20 18:53:54 +08001068 getDisplayContent().mClosingApps.remove(this);
Robert Carred3e83b2017-04-21 13:26:55 -07001069 } else if (mLastParent != null && mLastParent.mStack != null) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001070 task.mStack.mExitingAppTokens.remove(this);
1071 }
Bryce Lee6d410262017-02-28 15:30:17 -08001072 }
Jorim Jaggi6de61012018-03-19 14:53:23 +01001073 final TaskStack stack = getStack();
1074
1075 // If we reparent, make sure to remove ourselves from the old animation registry.
1076 if (mAnimatingAppWindowTokenRegistry != null) {
1077 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
1078 }
1079 mAnimatingAppWindowTokenRegistry = stack != null
1080 ? stack.getAnimatingAppWindowTokenRegistry()
1081 : null;
1082
Robert Carred3e83b2017-04-21 13:26:55 -07001083 mLastParent = task;
chaviwdcf76ec2019-01-11 16:48:46 -08001084
1085 updateColorTransform();
Bryce Lee6d410262017-02-28 15:30:17 -08001086 }
1087
Wale Ogunwalefa854eb2016-09-20 13:43:52 -07001088 void postWindowRemoveStartingWindowCleanup(WindowState win) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001089 // TODO: Something smells about the code below...Is there a better way?
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001090 if (startingWindow == win) {
Adrian Roosb125e0b2019-10-02 14:55:14 +02001091 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Notify removed startingWindow %s", win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001092 removeStartingWindow();
Wale Ogunwale6c459212017-05-17 08:56:03 -07001093 } else if (mChildren.size() == 0) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001094 // If this is the last window and we had requested a starting transition window,
1095 // well there is no point now.
Adrian Roosb125e0b2019-10-02 14:55:14 +02001096 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Nulling last startingData");
chaviwa8f07a72019-05-01 16:25:39 -07001097 mStartingData = null;
Wale Ogunwale6c459212017-05-17 08:56:03 -07001098 if (mHiddenSetFromTransferredStartingWindow) {
1099 // We set the hidden state to false for the token from a transferred starting window.
1100 // We now reset it back to true since the starting window was the last window in the
1101 // token.
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001102 setHidden(true);
Wale Ogunwale6c459212017-05-17 08:56:03 -07001103 }
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01001104 } else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001105 // If this is the last window except for a starting transition window,
1106 // we need to get rid of the starting transition.
Adrian Roosb125e0b2019-10-02 14:55:14 +02001107 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Last window, removing starting window %s", win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001108 removeStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001109 }
1110 }
1111
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001112 void removeDeadWindows() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001113 for (int winNdx = mChildren.size() - 1; winNdx >= 0; --winNdx) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001114 WindowState win = mChildren.get(winNdx);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001115 if (win.mAppDied) {
Adrian Roosb125e0b2019-10-02 14:55:14 +02001116 ProtoLog.w(WM_DEBUG_ADD_REMOVE,
1117 "removeDeadWindows: %s", win);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001118 // Set mDestroying, we don't want any animation or delayed removal here.
1119 win.mDestroying = true;
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001120 // Also removes child windows.
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001121 win.removeIfPossible();
Chong Zhang112eb8c2015-11-02 11:17:00 -08001122 }
1123 }
1124 }
1125
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001126 boolean hasWindowsAlive() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001127 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001128 // No need to loop through child windows as the answer should be the same as that of the
1129 // parent window.
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001130 if (!(mChildren.get(i)).mAppDied) {
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001131 return true;
1132 }
1133 }
1134 return false;
1135 }
1136
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001137 void setWillReplaceWindows(boolean animate) {
Adrian Roosb125e0b2019-10-02 14:55:14 +02001138 ProtoLog.d(WM_DEBUG_ADD_REMOVE,
1139 "Marking app token %s with replacing windows.", this);
Robert Carra1eb4392015-12-10 12:43:51 -08001140
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001141 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001142 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001143 w.setWillReplaceWindow(animate);
Robert Carra1eb4392015-12-10 12:43:51 -08001144 }
Robert Carra1eb4392015-12-10 12:43:51 -08001145 }
1146
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001147 void setWillReplaceChildWindows() {
Adrian Roosb125e0b2019-10-02 14:55:14 +02001148 ProtoLog.d(WM_DEBUG_ADD_REMOVE, "Marking app token %s"
1149 + " with replacing child windows.", this);
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001150 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001151 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001152 w.setWillReplaceChildWindows();
Robert Carr23fa16b2016-01-13 13:19:58 -08001153 }
1154 }
1155
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001156 void clearWillReplaceWindows() {
Adrian Roosb125e0b2019-10-02 14:55:14 +02001157 ProtoLog.d(WM_DEBUG_ADD_REMOVE,
1158 "Resetting app token %s of replacing window marks.", this);
Chong Zhangf596cd52016-01-05 13:42:44 -08001159
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001160 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001161 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001162 w.clearWillReplaceWindow();
Chong Zhangf596cd52016-01-05 13:42:44 -08001163 }
1164 }
1165
Chong Zhang4d7369a2016-04-25 16:09:14 -07001166 void requestUpdateWallpaperIfNeeded() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001167 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001168 final WindowState w = mChildren.get(i);
Chong Zhang4d7369a2016-04-25 16:09:14 -07001169 w.requestUpdateWallpaperIfNeeded();
1170 }
1171 }
1172
Chong Zhangd78ddb42016-03-02 17:01:14 -08001173 boolean isRelaunching() {
1174 return mPendingRelaunchCount > 0;
1175 }
1176
Robert Carr68375192017-06-13 12:41:53 -07001177 boolean shouldFreezeBounds() {
1178 final Task task = getTask();
1179
1180 // For freeform windows, we can't freeze the bounds at the moment because this would make
1181 // the resizing unresponsive.
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001182 if (task == null || task.inFreeformWindowingMode()) {
Robert Carr68375192017-06-13 12:41:53 -07001183 return false;
1184 }
1185
1186 // We freeze the bounds while drag resizing to deal with the time between
1187 // the divider/drag handle being released, and the handling it's new
1188 // configuration. If we are relaunched outside of the drag resizing state,
1189 // we need to be careful not to do this.
1190 return getTask().isDragResizing();
1191 }
1192
Chong Zhangd78ddb42016-03-02 17:01:14 -08001193 void startRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001194 if (shouldFreezeBounds()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08001195 freezeBounds();
1196 }
Robert Carrd5c7dd62017-03-08 10:39:30 -08001197
1198 // In the process of tearing down before relaunching, the app will
1199 // try and clean up it's child surfaces. We need to prevent this from
1200 // happening, so we sever the children, transfering their ownership
1201 // from the client it-self to the parent surface (owned by us).
Robert Carr29daa922018-04-27 11:56:48 -07001202 detachChildren();
1203
1204 mPendingRelaunchCount++;
1205 }
1206
1207 void detachChildren() {
Robert Carrfd8e93b2018-05-10 13:40:25 -07001208 SurfaceControl.openTransaction();
Robert Carrd5c7dd62017-03-08 10:39:30 -08001209 for (int i = mChildren.size() - 1; i >= 0; i--) {
1210 final WindowState w = mChildren.get(i);
1211 w.mWinAnimator.detachChildren();
1212 }
Robert Carrfd8e93b2018-05-10 13:40:25 -07001213 SurfaceControl.closeTransaction();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001214 }
1215
1216 void finishRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001217 unfreezeBounds();
1218
Chong Zhangd78ddb42016-03-02 17:01:14 -08001219 if (mPendingRelaunchCount > 0) {
1220 mPendingRelaunchCount--;
Bryce Lee081554b2017-05-25 07:52:12 -07001221 } else {
1222 // Update keyguard flags upon finishing relaunch.
1223 checkKeyguardFlagsChanged();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001224 }
1225 }
1226
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001227 void clearRelaunching() {
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001228 if (mPendingRelaunchCount == 0) {
1229 return;
1230 }
Robert Carr68375192017-06-13 12:41:53 -07001231 unfreezeBounds();
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001232 mPendingRelaunchCount = 0;
1233 }
1234
Wale Ogunwale07bcab72016-10-14 15:30:09 -07001235 /**
1236 * Returns true if the new child window we are adding to this token is considered greater than
1237 * the existing child window in this token in terms of z-order.
1238 */
1239 @Override
1240 protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
1241 WindowState existingWindow) {
1242 final int type1 = newWindow.mAttrs.type;
1243 final int type2 = existingWindow.mAttrs.type;
1244
1245 // Base application windows should be z-ordered BELOW all other windows in the app token.
1246 if (type1 == TYPE_BASE_APPLICATION && type2 != TYPE_BASE_APPLICATION) {
1247 return false;
1248 } else if (type1 != TYPE_BASE_APPLICATION && type2 == TYPE_BASE_APPLICATION) {
1249 return true;
1250 }
1251
1252 // Starting windows should be z-ordered ABOVE all other windows in the app token.
1253 if (type1 == TYPE_APPLICATION_STARTING && type2 != TYPE_APPLICATION_STARTING) {
1254 return true;
1255 } else if (type1 != TYPE_APPLICATION_STARTING && type2 == TYPE_APPLICATION_STARTING) {
1256 return false;
1257 }
1258
1259 // Otherwise the new window is greater than the existing window.
1260 return true;
1261 }
1262
Tarandeep Singh69ab1042019-07-30 13:30:03 -07001263 /**
1264 * @return {@code true} if starting window is in app's hierarchy.
1265 */
1266 boolean hasStartingWindow() {
1267 if (startingDisplayed || mStartingData != null) {
1268 return true;
1269 }
1270 for (int i = mChildren.size() - 1; i >= 0; i--) {
1271 if (getChildAt(i).mAttrs.type == TYPE_APPLICATION_STARTING) {
1272 return true;
1273 }
1274 }
1275 return false;
1276 }
1277
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001278 @Override
Robert Carra1eb4392015-12-10 12:43:51 -08001279 void addWindow(WindowState w) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001280 super.addWindow(w);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001281
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001282 boolean gotReplacementWindow = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001283 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001284 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001285 gotReplacementWindow |= candidate.setReplacementWindowIfNeeded(w);
1286 }
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001287
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001288 // if we got a replacement window, reset the timeout to give drawing more time
1289 if (gotReplacementWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001290 mWmService.scheduleWindowReplacementTimeouts(this);
Robert Carra1eb4392015-12-10 12:43:51 -08001291 }
Jorim Jaggife762342016-10-13 14:33:27 +02001292 checkKeyguardFlagsChanged();
1293 }
1294
1295 @Override
1296 void removeChild(WindowState child) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001297 if (!mChildren.contains(child)) {
1298 // This can be true when testing.
1299 return;
1300 }
Jorim Jaggife762342016-10-13 14:33:27 +02001301 super.removeChild(child);
1302 checkKeyguardFlagsChanged();
Adrian Roos23df3a32018-03-15 15:41:13 +01001303 updateLetterboxSurface(child);
Robert Carra1eb4392015-12-10 12:43:51 -08001304 }
1305
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001306 private boolean waitingForReplacement() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001307 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001308 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001309 if (candidate.waitingForReplacement()) {
Robert Carra1eb4392015-12-10 12:43:51 -08001310 return true;
1311 }
1312 }
1313 return false;
1314 }
1315
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001316 void onWindowReplacementTimeout() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001317 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001318 (mChildren.get(i)).onWindowReplacementTimeout();
Robert Carra1eb4392015-12-10 12:43:51 -08001319 }
1320 }
1321
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001322 void reparent(Task task, int position) {
Adrian Roosb125e0b2019-10-02 14:55:14 +02001323 ProtoLog.i(WM_DEBUG_ADD_REMOVE, "reparent: moving app token=%s"
1324 + " to task=%d at %d", this, task.mTaskId, position);
1325
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001326 if (task == null) {
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001327 throw new IllegalArgumentException("reparent: could not find task");
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001328 }
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001329 final Task currentTask = getTask();
1330 if (task == currentTask) {
Winson Chung30480042017-01-26 10:55:34 -08001331 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001332 "window token=" + this + " already child of task=" + currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001333 }
Bryce Lee6d410262017-02-28 15:30:17 -08001334
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001335 if (currentTask.mStack != task.mStack) {
Bryce Lee6d410262017-02-28 15:30:17 -08001336 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001337 "window token=" + this + " current task=" + currentTask
Bryce Lee6d410262017-02-28 15:30:17 -08001338 + " belongs to a different stack than " + task);
1339 }
1340
Adrian Roosb125e0b2019-10-02 14:55:14 +02001341 ProtoLog.i(WM_DEBUG_ADD_REMOVE, "reParentWindowToken: removing window token=%s"
1342 + " from task=%s" , this, currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001343 final DisplayContent prevDisplayContent = getDisplayContent();
1344
Bryce Lee6d410262017-02-28 15:30:17 -08001345 mReparenting = true;
1346
Winson Chung30480042017-01-26 10:55:34 -08001347 getParent().removeChild(this);
1348 task.addChild(this, position);
1349
Bryce Lee6d410262017-02-28 15:30:17 -08001350 mReparenting = false;
1351
Winson Chung30480042017-01-26 10:55:34 -08001352 // Relayout display(s).
1353 final DisplayContent displayContent = task.getDisplayContent();
1354 displayContent.setLayoutNeeded();
1355 if (prevDisplayContent != displayContent) {
1356 onDisplayChanged(displayContent);
1357 prevDisplayContent.setLayoutNeeded();
1358 }
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001359 getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
Winson Chung30480042017-01-26 10:55:34 -08001360 }
1361
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001362 @Override
1363 void onDisplayChanged(DisplayContent dc) {
1364 DisplayContent prevDc = mDisplayContent;
1365 super.onDisplayChanged(dc);
Evan Roskyb1e75f72019-04-26 20:23:26 -07001366 if (prevDc == null || prevDc == mDisplayContent) {
Evan Rosky25b56192019-02-06 16:10:56 -08001367 return;
1368 }
Wale Ogunwaleb8e6b632019-06-28 15:19:25 +00001369
1370 if (prevDc.mOpeningApps.remove(this)) {
1371 // Transfer opening transition to new display.
1372 mDisplayContent.mOpeningApps.add(this);
1373 mDisplayContent.prepareAppTransition(prevDc.mAppTransition.getAppTransition(), true);
1374 mDisplayContent.executeAppTransition();
1375 }
1376
1377 if (prevDc.mChangingApps.remove(this)) {
Evan Rosky25b56192019-02-06 16:10:56 -08001378 // This gets called *after* the AppWindowToken has been reparented to the new display.
1379 // That reparenting resulted in this window changing modes (eg. FREEFORM -> FULLSCREEN),
1380 // so this token is now "frozen" while waiting for the animation to start on prevDc
1381 // (which will be cancelled since the window is no-longer a child). However, since this
1382 // is no longer a child of prevDc, this won't be notified of the cancelled animation,
1383 // so we need to cancel the change transition here.
1384 clearChangeLeash(getPendingTransaction(), true /* cancel */);
1385 }
Wale Ogunwaleb8e6b632019-06-28 15:19:25 +00001386 prevDc.mClosingApps.remove(this);
1387
Evan Rosky25b56192019-02-06 16:10:56 -08001388 if (prevDc.mFocusedApp == this) {
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001389 prevDc.setFocusedApp(null);
lumarkbf844642018-11-23 17:11:36 +08001390 final TaskStack stack = dc.getTopStack();
1391 if (stack != null) {
1392 final Task task = stack.getTopChild();
1393 if (task != null && task.getTopChild() == this) {
1394 dc.setFocusedApp(this);
1395 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001396 }
1397 }
Riddle Hsu192fe762019-01-15 23:41:57 +08001398
Evan Roskyb1e75f72019-04-26 20:23:26 -07001399 if (mLetterbox != null) {
Riddle Hsu192fe762019-01-15 23:41:57 +08001400 mLetterbox.onMovedToDisplay(mDisplayContent.getDisplayId());
1401 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001402 }
1403
Jorim Jaggi0429f352015-12-22 16:29:16 +01001404 /**
1405 * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds
1406 * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even
1407 * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen
1408 * with a queue.
1409 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001410 private void freezeBounds() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001411 final Task task = getTask();
1412 mFrozenBounds.offer(new Rect(task.mPreparedFrozenBounds));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001413
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001414 if (task.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001415 // We didn't call prepareFreezingBounds on the task, so use the current value.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001416 mFrozenMergedConfig.offer(new Configuration(task.getConfiguration()));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001417 } else {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001418 mFrozenMergedConfig.offer(new Configuration(task.mPreparedFrozenMergedConfig));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001419 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001420 // Calling unset() to make it equal to Configuration.EMPTY.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001421 task.mPreparedFrozenMergedConfig.unset();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001422 }
1423
1424 /**
1425 * Unfreezes the previously frozen bounds. See {@link #freezeBounds}.
1426 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001427 private void unfreezeBounds() {
Robert Carr68375192017-06-13 12:41:53 -07001428 if (mFrozenBounds.isEmpty()) {
1429 return;
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001430 }
Robert Carr68375192017-06-13 12:41:53 -07001431 mFrozenBounds.remove();
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001432 if (!mFrozenMergedConfig.isEmpty()) {
1433 mFrozenMergedConfig.remove();
1434 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001435 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001436 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001437 win.onUnfreezeBounds();
Jorim Jaggi4846ee32016-01-07 17:39:12 +01001438 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001439 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001440 }
1441
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001442 void setAppLayoutChanges(int changes, String reason) {
1443 if (!mChildren.isEmpty()) {
1444 final DisplayContent dc = getDisplayContent();
1445 dc.pendingLayoutChanges |= changes;
1446 if (DEBUG_LAYOUT_REPEATS) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001447 mWmService.mWindowPlacerLocked.debugLayoutRepeats(reason, dc.pendingLayoutChanges);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001448 }
1449 }
1450 }
1451
1452 void removeReplacedWindowIfNeeded(WindowState replacement) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001453 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001454 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001455 if (win.removeReplacedWindowIfNeeded(replacement)) {
1456 return;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001457 }
1458 }
1459 }
1460
1461 void startFreezingScreen() {
Adrian Roosb125e0b2019-10-02 14:55:14 +02001462 ProtoLog.i(WM_DEBUG_ORIENTATION,
1463 "Set freezing of %s: hidden=%b freezing=%b hiddenRequested=%b. %s",
1464 appToken, isHidden(), mFreezingScreen, hiddenRequested,
1465 new RuntimeException().fillInStackTrace());
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001466 if (!hiddenRequested) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001467 if (!mFreezingScreen) {
1468 mFreezingScreen = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001469 mWmService.registerAppFreezeListener(this);
1470 mWmService.mAppsFreezingScreen++;
1471 if (mWmService.mAppsFreezingScreen == 1) {
1472 mWmService.startFreezingDisplayLocked(0, 0, getDisplayContent());
1473 mWmService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
1474 mWmService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001475 }
1476 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001477 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001478 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001479 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001480 w.onStartFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001481 }
1482 }
1483 }
1484
1485 void stopFreezingScreen(boolean unfreezeSurfaceNow, boolean force) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001486 if (!mFreezingScreen) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001487 return;
1488 }
Adrian Roosb125e0b2019-10-02 14:55:14 +02001489 ProtoLog.v(WM_DEBUG_ORIENTATION,
1490 "Clear freezing of %s force=%b", this, force);
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001491 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001492 boolean unfrozeWindows = false;
1493 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001494 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001495 unfrozeWindows |= w.onStopFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001496 }
1497 if (force || unfrozeWindows) {
Adrian Roosb125e0b2019-10-02 14:55:14 +02001498 ProtoLog.v(WM_DEBUG_ORIENTATION, "No longer freezing: %s", this);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001499 mFreezingScreen = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001500 mWmService.unregisterAppFreezeListener(this);
1501 mWmService.mAppsFreezingScreen--;
1502 mWmService.mLastFinishedFreezeSource = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001503 }
1504 if (unfreezeSurfaceNow) {
1505 if (unfrozeWindows) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001506 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001507 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001508 mWmService.stopFreezingDisplayLocked();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001509 }
1510 }
1511
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001512 @Override
1513 public void onAppFreezeTimeout() {
1514 Slog.w(TAG_WM, "Force clearing freeze: " + this);
1515 stopFreezingScreen(true, true);
1516 }
1517
Jorim Jaggi60f9c972018-02-01 19:21:07 +01001518 /**
1519 * Tries to transfer the starting window from a token that's above ourselves in the task but
1520 * not visible anymore. This is a common scenario apps use: Trampoline activity T start main
1521 * activity M in the same task. Now, when reopening the task, T starts on top of M but then
1522 * immediately finishes after, so we have to transfer T to M.
1523 */
1524 void transferStartingWindowFromHiddenAboveTokenIfNeeded() {
1525 final Task task = getTask();
1526 for (int i = task.mChildren.size() - 1; i >= 0; i--) {
1527 final AppWindowToken fromToken = task.mChildren.get(i);
1528 if (fromToken == this) {
1529 return;
1530 }
1531 if (fromToken.hiddenRequested && transferStartingWindow(fromToken.token)) {
1532 return;
1533 }
1534 }
1535 }
1536
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001537 boolean transferStartingWindow(IBinder transferFrom) {
Wale Ogunwale02319a62016-09-26 15:21:22 -07001538 final AppWindowToken fromToken = getDisplayContent().getAppWindowToken(transferFrom);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001539 if (fromToken == null) {
1540 return false;
1541 }
1542
1543 final WindowState tStartingWindow = fromToken.startingWindow;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08001544 if (tStartingWindow != null && fromToken.startingSurface != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001545 // In this case, the starting icon has already been displayed, so start
1546 // letting windows get shown immediately without any more transitions.
lumark588a3e82018-07-20 18:53:54 +08001547 getDisplayContent().mSkipAppTransitionAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001548
Adrian Roosb125e0b2019-10-02 14:55:14 +02001549 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Moving existing starting %s"
1550 + " from %s to %s", tStartingWindow, fromToken, this);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001551
1552 final long origId = Binder.clearCallingIdentity();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001553 try {
1554 // Transfer the starting window over to the new token.
chaviwa8f07a72019-05-01 16:25:39 -07001555 mStartingData = fromToken.mStartingData;
Peter Visontay3556a3b2017-11-01 17:23:17 +00001556 startingSurface = fromToken.startingSurface;
1557 startingDisplayed = fromToken.startingDisplayed;
1558 fromToken.startingDisplayed = false;
1559 startingWindow = tStartingWindow;
1560 reportedVisible = fromToken.reportedVisible;
chaviwa8f07a72019-05-01 16:25:39 -07001561 fromToken.mStartingData = null;
Peter Visontay3556a3b2017-11-01 17:23:17 +00001562 fromToken.startingSurface = null;
1563 fromToken.startingWindow = null;
1564 fromToken.startingMoved = true;
1565 tStartingWindow.mToken = this;
1566 tStartingWindow.mAppToken = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001567
Adrian Roosb125e0b2019-10-02 14:55:14 +02001568 ProtoLog.v(WM_DEBUG_ADD_REMOVE,
1569 "Removing starting %s from %s", tStartingWindow, fromToken);
Peter Visontay3556a3b2017-11-01 17:23:17 +00001570 fromToken.removeChild(tStartingWindow);
1571 fromToken.postWindowRemoveStartingWindowCleanup(tStartingWindow);
1572 fromToken.mHiddenSetFromTransferredStartingWindow = false;
1573 addWindow(tStartingWindow);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001574
Peter Visontay3556a3b2017-11-01 17:23:17 +00001575 // Propagate other interesting state between the tokens. If the old token is displayed,
1576 // we should immediately force the new one to be displayed. If it is animating, we need
1577 // to move that animation to the new one.
1578 if (fromToken.allDrawn) {
1579 allDrawn = true;
1580 deferClearAllDrawn = fromToken.deferClearAllDrawn;
1581 }
1582 if (fromToken.firstWindowDrawn) {
1583 firstWindowDrawn = true;
1584 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001585 if (!fromToken.isHidden()) {
1586 setHidden(false);
Peter Visontay3556a3b2017-11-01 17:23:17 +00001587 hiddenRequested = false;
1588 mHiddenSetFromTransferredStartingWindow = true;
1589 }
1590 setClientHidden(fromToken.mClientHidden);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001591
Jorim Jaggi980c9de2017-11-17 01:41:37 +01001592 transferAnimation(fromToken);
1593
1594 // When transferring an animation, we no longer need to apply an animation to the
Tiger Huangc9d0d002019-05-29 22:55:29 +08001595 // the token we transfer the animation over. Thus, set this flag to indicate we've
1596 // transferred the animation.
1597 mUseTransferredAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001598
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001599 mWmService.updateFocusedWindowLocked(
Peter Visontay3556a3b2017-11-01 17:23:17 +00001600 UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/);
1601 getDisplayContent().setLayoutNeeded();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001602 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001603 } finally {
1604 Binder.restoreCallingIdentity(origId);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001605 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001606 return true;
chaviwa8f07a72019-05-01 16:25:39 -07001607 } else if (fromToken.mStartingData != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001608 // The previous app was getting ready to show a
1609 // starting window, but hasn't yet done so. Steal it!
Adrian Roosb125e0b2019-10-02 14:55:14 +02001610 ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
1611 "Moving pending starting from %s to %s", fromToken, this);
chaviwa8f07a72019-05-01 16:25:39 -07001612 mStartingData = fromToken.mStartingData;
1613 fromToken.mStartingData = null;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001614 fromToken.startingMoved = true;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001615 scheduleAddStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001616 return true;
1617 }
1618
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001619 // TODO: Transfer thumbnail
1620
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001621 return false;
1622 }
1623
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001624 boolean isLastWindow(WindowState win) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001625 return mChildren.size() == 1 && mChildren.get(0) == win;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001626 }
1627
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001628 @Override
1629 void onAppTransitionDone() {
1630 sendingToBottom = false;
1631 }
1632
Wale Ogunwale51362492016-09-08 17:49:17 -07001633 /**
1634 * We override because this class doesn't want its children affecting its reported orientation
1635 * in anyway.
1636 */
1637 @Override
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001638 int getOrientation(int candidate) {
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001639 if (candidate == SCREEN_ORIENTATION_BEHIND) {
1640 // Allow app to specify orientation regardless of its visibility state if the current
1641 // candidate want us to use orientation behind. I.e. the visible app on-top of this one
1642 // wants us to use the orientation of the app behind it.
1643 return mOrientation;
1644 }
1645
Bryce Lee61fbcbc2017-03-10 14:14:03 -08001646 // The {@link AppWindowToken} should only specify an orientation when it is not closing or
1647 // going to the bottom. Allowing closing {@link AppWindowToken} to participate can lead to
1648 // an Activity in another task being started in the wrong orientation during the transition.
lumark588a3e82018-07-20 18:53:54 +08001649 if (!(sendingToBottom || getDisplayContent().mClosingApps.contains(this))
1650 && (isVisible() || getDisplayContent().mOpeningApps.contains(this))) {
Bryce Leea163b762017-01-24 11:05:01 -08001651 return mOrientation;
Wale Ogunwale51362492016-09-08 17:49:17 -07001652 }
Bryce Leea163b762017-01-24 11:05:01 -08001653
1654 return SCREEN_ORIENTATION_UNSET;
Wale Ogunwale51362492016-09-08 17:49:17 -07001655 }
1656
Wale Ogunwaleb198b742016-12-01 08:44:09 -08001657 /** Returns the app's preferred orientation regardless of its currently visibility state. */
1658 int getOrientationIgnoreVisibility() {
1659 return mOrientation;
1660 }
1661
Riddle Hsub398da32019-01-21 21:48:16 +08001662 /** @return {@code true} if the compatibility bounds is taking effect. */
1663 boolean inSizeCompatMode() {
1664 return mSizeCompatBounds != null;
1665 }
1666
1667 @Override
1668 float getSizeCompatScale() {
1669 return inSizeCompatMode() ? mSizeCompatScale : super.getSizeCompatScale();
1670 }
1671
1672 /**
1673 * @return Non-empty bounds if the activity has override bounds.
1674 * @see ActivityRecord#resolveOverrideConfiguration(Configuration)
1675 */
1676 Rect getResolvedOverrideBounds() {
1677 // Get bounds from resolved override configuration because it is computed with orientation.
1678 return getResolvedOverrideConfiguration().windowConfiguration.getBounds();
1679 }
1680
Craig Mautnerdbb79912012-03-01 18:59:14 -08001681 @Override
Winson Chunge55c0192017-08-24 14:50:48 -07001682 public void onConfigurationChanged(Configuration newParentConfig) {
1683 final int prevWinMode = getWindowingMode();
Evan Rosky2289ba12018-11-19 18:28:18 -08001684 mTmpPrevBounds.set(getBounds());
Winson Chunge55c0192017-08-24 14:50:48 -07001685 super.onConfigurationChanged(newParentConfig);
Riddle Hsub398da32019-01-21 21:48:16 +08001686
1687 final Task task = getTask();
1688 final Rect overrideBounds = getResolvedOverrideBounds();
1689 if (task != null && !overrideBounds.isEmpty()
1690 // If the changes come from change-listener, the incoming parent configuration is
1691 // still the old one. Make sure their orientations are the same to reduce computing
1692 // the compatibility bounds for the intermediate state.
Riddle Hsu04164182019-03-07 18:03:27 +08001693 && (task.mTaskRecord == null || task.mTaskRecord
1694 .getConfiguration().orientation == newParentConfig.orientation)) {
Riddle Hsub398da32019-01-21 21:48:16 +08001695 final Rect taskBounds = task.getBounds();
1696 // Since we only center the activity horizontally, if only the fixed height is smaller
1697 // than its container, the override bounds don't need to take effect.
1698 if ((overrideBounds.width() != taskBounds.width()
1699 || overrideBounds.height() > taskBounds.height())) {
1700 calculateCompatBoundsTransformation(newParentConfig);
1701 updateSurfacePosition();
1702 } else if (mSizeCompatBounds != null) {
1703 mSizeCompatBounds = null;
1704 mSizeCompatScale = 1f;
1705 updateSurfacePosition();
1706 }
1707 }
1708
Winson Chunge55c0192017-08-24 14:50:48 -07001709 final int winMode = getWindowingMode();
1710
1711 if (prevWinMode == winMode) {
1712 return;
1713 }
1714
Hongwei Wang43a752b2019-09-17 20:20:30 +00001715 if (prevWinMode == WINDOWING_MODE_PINNED && winMode != WINDOWING_MODE_UNDEFINED
Winson Chung82267ce2018-04-06 16:38:26 -07001716 && !isHidden()) {
Winson Chunge55c0192017-08-24 14:50:48 -07001717 // Leaving PiP to fullscreen, save the snap fraction based on the pre-animation bounds
1718 // for the next re-entry into PiP (assuming the activity is not hidden or destroyed)
1719 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
1720 if (pinnedStack != null) {
Winson Chung8efa1652018-06-06 09:34:23 -07001721 final Rect stackBounds;
1722 if (pinnedStack.lastAnimatingBoundsWasToFullscreen()) {
1723 // We are animating the bounds, use the pre-animation bounds to save the snap
1724 // fraction
1725 stackBounds = pinnedStack.mPreAnimationBounds;
1726 } else {
1727 // We skip the animation if the fullscreen configuration is not compatible, so
1728 // use the current bounds to calculate the saved snap fraction instead
1729 // (see PinnedActivityStack.skipResizeAnimation())
1730 stackBounds = mTmpRect;
1731 pinnedStack.getBounds(stackBounds);
1732 }
Hongwei Wang43a752b2019-09-17 20:20:30 +00001733 mDisplayContent.mPinnedStackControllerLocked.saveReentrySnapFraction(
1734 mActivityComponent, stackBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001735 }
Evan Rosky2289ba12018-11-19 18:28:18 -08001736 } else if (shouldStartChangeTransition(prevWinMode, winMode)) {
1737 initializeChangeTransition(mTmpPrevBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001738 }
1739 }
1740
Evan Rosky2289ba12018-11-19 18:28:18 -08001741 private boolean shouldStartChangeTransition(int prevWinMode, int newWinMode) {
Evan Rosky25b56192019-02-06 16:10:56 -08001742 if (mWmService.mDisableTransitionAnimation
1743 || !isVisible()
1744 || getDisplayContent().mAppTransition.isTransitionSet()
1745 || getSurfaceControl() == null) {
Evan Rosky2289ba12018-11-19 18:28:18 -08001746 return false;
1747 }
1748 // Only do an animation into and out-of freeform mode for now. Other mode
1749 // transition animations are currently handled by system-ui.
1750 return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
1751 }
1752
1753 /**
1754 * Initializes a change transition. Because the app is visible already, there is a small period
1755 * of time where the user can see the app content/window update before the transition starts.
1756 * To prevent this, we immediately take a snapshot and place the app/snapshot into a leash which
1757 * "freezes" the location/crop until the transition starts.
1758 * <p>
1759 * Here's a walk-through of the process:
1760 * 1. Create a temporary leash ("interim-change-leash") and reparent the app to it.
1761 * 2. Set the temporary leash's position/crop to the current state.
1762 * 3. Create a snapshot and place that at the top of the leash to cover up content changes.
1763 * 4. Once the transition is ready, it will reparent the app to the animation leash.
1764 * 5. Detach the interim-change-leash.
1765 */
1766 private void initializeChangeTransition(Rect startBounds) {
1767 mDisplayContent.prepareAppTransition(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
1768 false /* alwaysKeepCurrent */, 0, false /* forceOverride */);
1769 mDisplayContent.mChangingApps.add(this);
1770 mTransitStartRect.set(startBounds);
1771
1772 final SurfaceControl.Builder builder = makeAnimationLeash()
1773 .setParent(getAnimationLeashParent())
1774 .setName(getSurfaceControl() + " - interim-change-leash");
1775 mTransitChangeLeash = builder.build();
1776 Transaction t = getPendingTransaction();
1777 t.setWindowCrop(mTransitChangeLeash, startBounds.width(), startBounds.height());
1778 t.setPosition(mTransitChangeLeash, startBounds.left, startBounds.top);
1779 t.show(mTransitChangeLeash);
1780 t.reparent(getSurfaceControl(), mTransitChangeLeash);
1781 onAnimationLeashCreated(t, mTransitChangeLeash);
1782
Evan Rosky966759f2019-01-15 10:33:58 -08001783 // Skip creating snapshot if this transition is controlled by a remote animator which
1784 // doesn't need it.
1785 ArraySet<Integer> activityTypes = new ArraySet<>();
1786 activityTypes.add(getActivityType());
1787 RemoteAnimationAdapter adapter =
1788 mDisplayContent.mAppTransitionController.getRemoteAnimationOverride(
1789 this, TRANSIT_TASK_CHANGE_WINDOWING_MODE, activityTypes);
1790 if (adapter != null && !adapter.getChangeNeedsSnapshot()) {
1791 return;
1792 }
1793
Evan Rosky08e20932019-05-14 10:54:07 -07001794 Task task = getTask();
1795 if (mThumbnail == null && task != null && !hasCommittedReparentToAnimationLeash()) {
1796 SurfaceControl.ScreenshotGraphicBuffer snapshot =
1797 mWmService.mTaskSnapshotController.createTaskSnapshot(
1798 task, 1 /* scaleFraction */);
Yunfan Chendcb1fcf2019-02-07 19:08:41 +09001799 if (snapshot != null) {
Vishnu Nair33197392019-08-30 10:29:37 -07001800 mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory, t, this,
1801 snapshot.getGraphicBuffer(), true /* relative */);
Yunfan Chendcb1fcf2019-02-07 19:08:41 +09001802 }
Evan Rosky2289ba12018-11-19 18:28:18 -08001803 }
1804 }
1805
1806 boolean isInChangeTransition() {
Evan Roskyec9488c2019-03-01 19:32:12 -08001807 return mTransitChangeLeash != null || AppTransition.isChangeTransit(mTransit);
Evan Rosky2289ba12018-11-19 18:28:18 -08001808 }
1809
Evan Rosky966759f2019-01-15 10:33:58 -08001810 @VisibleForTesting
1811 AppWindowThumbnail getThumbnail() {
1812 return mThumbnail;
1813 }
1814
Riddle Hsub398da32019-01-21 21:48:16 +08001815 /**
1816 * Calculates the scale and offset to horizontal center the size compatibility bounds into the
1817 * region which is available to application.
1818 */
1819 private void calculateCompatBoundsTransformation(Configuration newParentConfig) {
1820 final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds();
Riddle Hsu74826262019-04-17 14:57:42 +08001821 final Rect parentBounds = newParentConfig.windowConfiguration.getBounds();
1822 final Rect viewportBounds = parentAppBounds != null ? parentAppBounds : parentBounds;
Riddle Hsu04164182019-03-07 18:03:27 +08001823 final Rect appBounds = getWindowConfiguration().getAppBounds();
1824 final Rect contentBounds = appBounds != null ? appBounds : getResolvedOverrideBounds();
Riddle Hsub398da32019-01-21 21:48:16 +08001825 final float contentW = contentBounds.width();
1826 final float contentH = contentBounds.height();
1827 final float viewportW = viewportBounds.width();
1828 final float viewportH = viewportBounds.height();
1829 // Only allow to scale down.
1830 mSizeCompatScale = (contentW <= viewportW && contentH <= viewportH)
1831 ? 1 : Math.min(viewportW / contentW, viewportH / contentH);
1832 final int offsetX = (int) ((viewportW - contentW * mSizeCompatScale + 1) * 0.5f)
1833 + viewportBounds.left;
1834
1835 if (mSizeCompatBounds == null) {
1836 mSizeCompatBounds = new Rect();
1837 }
1838 mSizeCompatBounds.set(contentBounds);
1839 mSizeCompatBounds.offsetTo(0, 0);
1840 mSizeCompatBounds.scale(mSizeCompatScale);
Riddle Hsu74826262019-04-17 14:57:42 +08001841 // Ensure to align the top with the parent.
1842 mSizeCompatBounds.top = parentBounds.top;
Riddle Hsu04164182019-03-07 18:03:27 +08001843 // The decor inset is included in height.
1844 mSizeCompatBounds.bottom += viewportBounds.top;
Riddle Hsub398da32019-01-21 21:48:16 +08001845 mSizeCompatBounds.left += offsetX;
1846 mSizeCompatBounds.right += offsetX;
1847 }
1848
1849 @Override
1850 public Rect getBounds() {
1851 if (mSizeCompatBounds != null) {
1852 return mSizeCompatBounds;
1853 }
1854 return super.getBounds();
1855 }
1856
1857 @Override
1858 public boolean matchParentBounds() {
1859 if (super.matchParentBounds()) {
1860 return true;
1861 }
1862 // An activity in size compatibility mode may have override bounds which equals to its
1863 // parent bounds, so the exact bounds should also be checked.
1864 final WindowContainer parent = getParent();
1865 return parent == null || parent.getBounds().equals(getResolvedOverrideBounds());
1866 }
1867
Winson Chunge55c0192017-08-24 14:50:48 -07001868 @Override
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001869 void checkAppWindowsReadyToShow() {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001870 if (allDrawn == mLastAllDrawn) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001871 return;
1872 }
1873
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001874 mLastAllDrawn = allDrawn;
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001875 if (!allDrawn) {
1876 return;
1877 }
1878
1879 // The token has now changed state to having all windows shown... what to do, what to do?
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001880 if (mFreezingScreen) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001881 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001882 stopFreezingScreen(false, true);
Adrian Roosb125e0b2019-10-02 14:55:14 +02001883 ProtoLog.i(WM_DEBUG_ORIENTATION,
1884 "Setting mOrientationChangeComplete=true because wtoken %s "
1885 + "numInteresting=%d numDrawn=%d",
1886 this, mNumInterestingWindows, mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001887 // This will set mOrientationChangeComplete and cause a pass through layout.
1888 setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001889 "checkAppWindowsReadyToShow: freezingScreen");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001890 } else {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001891 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001892
1893 // We can now show all of the drawn windows!
lumark588a3e82018-07-20 18:53:54 +08001894 if (!getDisplayContent().mOpeningApps.contains(this) && canShowWindows()) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001895 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001896 }
1897 }
1898 }
1899
Matthew Ng5d23afa2017-06-21 16:16:24 -07001900 /**
Bryce Leed390deb2017-06-22 13:14:28 -07001901 * Returns whether the drawn window states of this {@link AppWindowToken} has considered every
1902 * child {@link WindowState}. A child is considered if it has been passed into
1903 * {@link #updateDrawnWindowStates(WindowState)} after being added. This is used to determine
1904 * whether states, such as {@code allDrawn}, can be set, which relies on state variables such as
1905 * {@code mNumInterestingWindows}, which depend on all {@link WindowState}s being considered.
1906 *
1907 * @return {@code true} If all children have been considered, {@code false}.
1908 */
1909 private boolean allDrawnStatesConsidered() {
Bryce Lee6311c4b2017-07-06 14:09:29 -07001910 for (int i = mChildren.size() - 1; i >= 0; --i) {
1911 final WindowState child = mChildren.get(i);
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001912 if (child.mightAffectAllDrawn() && !child.getDrawnStateEvaluated()) {
Bryce Leed390deb2017-06-22 13:14:28 -07001913 return false;
1914 }
1915 }
1916 return true;
1917 }
1918
1919 /**
Matthew Ng5d23afa2017-06-21 16:16:24 -07001920 * Determines if the token has finished drawing. This should only be called from
1921 * {@link DisplayContent#applySurfaceChangesTransaction}
1922 */
Matthew Ng498c71d2017-04-18 13:55:45 -07001923 void updateAllDrawn() {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001924 if (!allDrawn) {
Matthew Ng498c71d2017-04-18 13:55:45 -07001925 // Number of drawn windows can be less when a window is being relaunched, wait for
Bryce Leed390deb2017-06-22 13:14:28 -07001926 // all windows to be launched and drawn for this token be considered all drawn.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001927 final int numInteresting = mNumInterestingWindows;
Bryce Leed390deb2017-06-22 13:14:28 -07001928
1929 // We must make sure that all present children have been considered (determined by
1930 // {@link #allDrawnStatesConsidered}) before evaluating whether everything has been
1931 // drawn.
1932 if (numInteresting > 0 && allDrawnStatesConsidered()
1933 && mNumDrawnWindows >= numInteresting && !isRelaunching()) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001934 if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawn: " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001935 + " interesting=" + numInteresting + " drawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001936 allDrawn = true;
1937 // Force an additional layout pass where
1938 // WindowStateAnimator#commitFinishDrawingLocked() will call performShowLocked().
Matthew Ng498c71d2017-04-18 13:55:45 -07001939 if (mDisplayContent != null) {
1940 mDisplayContent.setLayoutNeeded();
1941 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001942 mWmService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
Robert Carrecc06b32017-04-18 14:25:10 -07001943
Winson Chunge7ba6862017-05-24 12:13:33 -07001944 // Notify the pinned stack upon all windows drawn. If there was an animation in
1945 // progress then this signal will resume that animation.
Wale Ogunwale61911492017-10-11 08:50:50 -07001946 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
Winson Chunge7ba6862017-05-24 12:13:33 -07001947 if (pinnedStack != null) {
1948 pinnedStack.onAllWindowsDrawn();
Robert Carrecc06b32017-04-18 14:25:10 -07001949 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001950 }
1951 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001952 }
1953
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001954 boolean keyDispatchingTimedOut(String reason, int windowPid) {
1955 return mActivityRecord != null && mActivityRecord.keyDispatchingTimedOut(reason, windowPid);
1956 }
1957
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001958 /**
1959 * Updated this app token tracking states for interesting and drawn windows based on the window.
1960 *
1961 * @return Returns true if the input window is considered interesting and drawn while all the
1962 * windows in this app token where not considered drawn as of the last pass.
1963 */
1964 boolean updateDrawnWindowStates(WindowState w) {
Bryce Leed390deb2017-06-22 13:14:28 -07001965 w.setDrawnStateEvaluated(true /*evaluated*/);
1966
Jorim Jaggie4b0f282017-05-17 15:10:29 +02001967 if (DEBUG_STARTING_WINDOW_VERBOSE && w == startingWindow) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001968 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + w.isOnScreen()
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001969 + " allDrawn=" + allDrawn + " freezingScreen=" + mFreezingScreen);
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001970 }
1971
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001972 if (allDrawn && !mFreezingScreen) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001973 return false;
1974 }
1975
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001976 if (mLastTransactionSequence != mWmService.mTransactionSequence) {
1977 mLastTransactionSequence = mWmService.mTransactionSequence;
Matthew Ng53e66b22018-01-12 17:13:13 -08001978 mNumDrawnWindows = 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001979 startingDisplayed = false;
Matthew Ng53e66b22018-01-12 17:13:13 -08001980
1981 // There is the main base application window, even if it is exiting, wait for it
1982 mNumInterestingWindows = findMainWindow(false /* includeStartingApp */) != null ? 1 : 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001983 }
1984
1985 final WindowStateAnimator winAnimator = w.mWinAnimator;
1986
1987 boolean isInterestingAndDrawn = false;
1988
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001989 if (!allDrawn && w.mightAffectAllDrawn()) {
Adrian Roosb125e0b2019-10-02 14:55:14 +02001990 if (DEBUG_VISIBILITY || WM_DEBUG_ORIENTATION.isLogToLogcat()) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001991 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001992 + ", isAnimationSet=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001993 if (!w.isDrawnLw()) {
1994 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController
chaviw15ad49f2019-04-24 15:05:39 -07001995 + " pv=" + w.isVisibleByPolicy()
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001996 + " mDrawState=" + winAnimator.drawStateToString()
1997 + " ph=" + w.isParentWindowHidden() + " th=" + hiddenRequested
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001998 + " a=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001999 }
2000 }
2001
2002 if (w != startingWindow) {
2003 if (w.isInteresting()) {
Matthew Ng53e66b22018-01-12 17:13:13 -08002004 // Add non-main window as interesting since the main app has already been added
2005 if (findMainWindow(false /* includeStartingApp */) != w) {
2006 mNumInterestingWindows++;
2007 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002008 if (w.isDrawnLw()) {
2009 mNumDrawnWindows++;
2010
Adrian Roosb125e0b2019-10-02 14:55:14 +02002011 if (DEBUG_VISIBILITY || WM_DEBUG_ORIENTATION.isLogToLogcat()) {
2012 Slog.v(TAG, "tokenMayBeDrawn: "
2013 + this + " w=" + w + " numInteresting=" + mNumInterestingWindows
2014 + " freezingScreen=" + mFreezingScreen
2015 + " mAppFreezing=" + w.mAppFreezing);
2016 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002017
2018 isInterestingAndDrawn = true;
2019 }
2020 }
2021 } else if (w.isDrawnLw()) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002022 if (mActivityRecord != null) {
2023 mActivityRecord.onStartingWindowDrawn(SystemClock.uptimeMillis());
Jorim Jaggi3878ca32017-02-02 17:13:05 -08002024 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002025 startingDisplayed = true;
2026 }
2027 }
2028
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002029 return isInterestingAndDrawn;
2030 }
2031
Adrian Roos23df3a32018-03-15 15:41:13 +01002032 void layoutLetterbox(WindowState winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002033 final WindowState w = findMainWindow();
Adrian Roosf93b6d22018-03-21 13:48:26 +01002034 if (w == null || winHint != null && w != winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002035 return;
2036 }
Jorim Jaggia32da382018-03-28 18:01:22 +02002037 final boolean surfaceReady = w.isDrawnLw() // Regular case
Adrian Roosf93b6d22018-03-21 13:48:26 +01002038 || w.mWinAnimator.mSurfaceDestroyDeferred // The preserved surface is still ready.
2039 || w.isDragResizeChanged(); // Waiting for relayoutWindow to call preserveSurface.
Jorim Jaggi4981f152019-03-26 18:58:45 +01002040 final boolean needsLetterbox = surfaceReady && w.isLetterboxedAppWindow() && fillsParent();
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002041 if (needsLetterbox) {
2042 if (mLetterbox == null) {
Vishnu Nair33197392019-08-30 10:29:37 -07002043 mLetterbox = new Letterbox(() -> makeChildSurface(null),
2044 mWmService.mTransactionFactory);
Riddle Hsu192fe762019-01-15 23:41:57 +08002045 mLetterbox.attachInput(w);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002046 }
Adrian Roos7af9d972018-11-30 15:26:27 +01002047 getPosition(mTmpPoint);
Evan Rosky67c15642019-04-24 13:17:28 -07002048 // Get the bounds of the "space-to-fill". In multi-window mode, the task-level
2049 // represents this. In fullscreen-mode, the stack does (since the orientation letterbox
2050 // is also applied to the task).
2051 Rect spaceToFill = (inMultiWindowMode() || getStack() == null)
2052 ? getTask().getDisplayedBounds() : getStack().getDisplayedBounds();
Evan Rosky4fb1e912019-03-06 13:54:43 -08002053 mLetterbox.layout(spaceToFill, w.getFrameLw(), mTmpPoint);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002054 } else if (mLetterbox != null) {
Adrian Roos23df3a32018-03-15 15:41:13 +01002055 mLetterbox.hide();
2056 }
2057 }
2058
2059 void updateLetterboxSurface(WindowState winHint) {
2060 final WindowState w = findMainWindow();
2061 if (w != winHint && winHint != null && w != null) {
2062 return;
2063 }
2064 layoutLetterbox(winHint);
2065 if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) {
Tiger Huanged6794e2019-05-07 20:07:59 +08002066 mLetterbox.applySurfaceChanges(getPendingTransaction());
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002067 }
2068 }
2069
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07002070 @Override
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002071 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002072 // For legacy reasons we process the TaskStack.mExitingAppTokens first in DisplayContent
2073 // before the non-exiting app tokens. So, we skip the exiting app tokens here.
2074 // TODO: Investigate if we need to continue to do this or if we can just process them
2075 // in-order.
2076 if (mIsExiting && !waitingForReplacement()) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002077 return false;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002078 }
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002079 return forAllWindowsUnchecked(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002080 }
2081
lumark588a3e82018-07-20 18:53:54 +08002082 @Override
2083 void forAllAppWindows(Consumer<AppWindowToken> callback) {
2084 callback.accept(this);
2085 }
2086
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002087 boolean forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback,
2088 boolean traverseTopToBottom) {
2089 return super.forAllWindows(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002090 }
2091
2092 @Override
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002093 AppWindowToken asAppWindowToken() {
2094 // I am an app window token!
2095 return this;
2096 }
2097
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002098 boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
2099 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
2100 IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
2101 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
2102 // If the display is frozen, we won't do anything until the actual window is
2103 // displayed so there is no reason to put in the starting window.
2104 if (!okToDisplay()) {
2105 return false;
2106 }
2107
chaviwa8f07a72019-05-01 16:25:39 -07002108 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002109 return false;
2110 }
2111
2112 final WindowState mainWin = findMainWindow();
2113 if (mainWin != null && mainWin.mWinAnimator.getShown()) {
2114 // App already has a visible window...why would you want a starting window?
2115 return false;
2116 }
2117
2118 final ActivityManager.TaskSnapshot snapshot =
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002119 mWmService.mTaskSnapshotController.getSnapshot(
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002120 getTask().mTaskId, getTask().mUserId,
2121 false /* restoreFromDisk */, false /* reducedResolution */);
2122 final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
2123 allowTaskSnapshot, activityCreated, fromRecents, snapshot);
2124
2125 if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
2126 return createSnapshot(snapshot);
2127 }
2128
2129 // If this is a translucent window, then don't show a starting window -- the current
2130 // effect (a full-screen opaque starting window that fades away to the real contents
2131 // when it is ready) does not work for this.
Adrian Roosb125e0b2019-10-02 14:55:14 +02002132 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Checking theme of starting window: 0x%x", theme);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002133 if (theme != 0) {
2134 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
2135 com.android.internal.R.styleable.Window,
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002136 mWmService.mCurrentUserId);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002137 if (ent == null) {
2138 // Whoops! App doesn't exist. Um. Okay. We'll just pretend like we didn't
2139 // see that.
2140 return false;
2141 }
2142 final boolean windowIsTranslucent = ent.array.getBoolean(
2143 com.android.internal.R.styleable.Window_windowIsTranslucent, false);
2144 final boolean windowIsFloating = ent.array.getBoolean(
2145 com.android.internal.R.styleable.Window_windowIsFloating, false);
2146 final boolean windowShowWallpaper = ent.array.getBoolean(
2147 com.android.internal.R.styleable.Window_windowShowWallpaper, false);
2148 final boolean windowDisableStarting = ent.array.getBoolean(
2149 com.android.internal.R.styleable.Window_windowDisablePreview, false);
Adrian Roosb125e0b2019-10-02 14:55:14 +02002150 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Translucent=%s Floating=%s ShowWallpaper=%s",
2151 windowIsTranslucent, windowIsFloating, windowShowWallpaper);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002152 if (windowIsTranslucent) {
2153 return false;
2154 }
2155 if (windowIsFloating || windowDisableStarting) {
2156 return false;
2157 }
2158 if (windowShowWallpaper) {
2159 if (getDisplayContent().mWallpaperController
2160 .getWallpaperTarget() == null) {
2161 // If this theme is requesting a wallpaper, and the wallpaper
2162 // is not currently visible, then this effectively serves as
2163 // an opaque window and our starting window transition animation
2164 // can still work. We just need to make sure the starting window
2165 // is also showing the wallpaper.
2166 windowFlags |= FLAG_SHOW_WALLPAPER;
2167 } else {
2168 return false;
2169 }
2170 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002171 }
Yunfan Chen8a8c0ed2018-12-18 16:46:32 -08002172
2173 if (transferStartingWindow(transferFrom)) {
2174 return true;
2175 }
2176
2177 // There is no existing starting window, and we don't want to create a splash screen, so
2178 // that's it!
2179 if (type != STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
2180 return false;
2181 }
2182
Adrian Roosb125e0b2019-10-02 14:55:14 +02002183 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Creating SplashScreenStartingData");
chaviwa8f07a72019-05-01 16:25:39 -07002184 mStartingData = new SplashScreenStartingData(mWmService, pkg,
Yunfan Chen8a8c0ed2018-12-18 16:46:32 -08002185 theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
2186 getMergedOverrideConfiguration());
2187 scheduleAddStartingWindow();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002188 return true;
2189 }
2190
2191
2192 private boolean createSnapshot(ActivityManager.TaskSnapshot snapshot) {
2193 if (snapshot == null) {
2194 return false;
2195 }
2196
Adrian Roosb125e0b2019-10-02 14:55:14 +02002197 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Creating SnapshotStartingData");
chaviwa8f07a72019-05-01 16:25:39 -07002198 mStartingData = new SnapshotStartingData(mWmService, snapshot);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002199 scheduleAddStartingWindow();
2200 return true;
2201 }
2202
2203 void scheduleAddStartingWindow() {
2204 // Note: we really want to do sendMessageAtFrontOfQueue() because we
2205 // want to process the message ASAP, before any other queued
2206 // messages.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002207 if (!mWmService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
Adrian Roosb125e0b2019-10-02 14:55:14 +02002208 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Enqueueing ADD_STARTING");
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002209 mWmService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002210 }
2211 }
2212
2213 private final Runnable mAddStartingWindow = new Runnable() {
2214
2215 @Override
2216 public void run() {
chaviwa8f07a72019-05-01 16:25:39 -07002217 // Can be accessed without holding the global lock
2218 final StartingData startingData;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002219 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002220 // There can only be one adding request, silly caller!
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002221 mWmService.mAnimationHandler.removeCallbacks(this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002222
chaviwa8f07a72019-05-01 16:25:39 -07002223 if (mStartingData == null) {
2224 // Animation has been canceled... do nothing.
Adrian Roosb125e0b2019-10-02 14:55:14 +02002225 ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
2226 "startingData was nulled out before handling"
2227 + " mAddStartingWindow: %s", AppWindowToken.this);
chaviwa8f07a72019-05-01 16:25:39 -07002228 return;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002229 }
chaviwa8f07a72019-05-01 16:25:39 -07002230 startingData = mStartingData;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002231 }
2232
Adrian Roosb125e0b2019-10-02 14:55:14 +02002233 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Add starting %s: startingData=%s",
2234 this, startingData);
2235
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002236
2237 WindowManagerPolicy.StartingSurface surface = null;
2238 try {
2239 surface = startingData.createStartingSurface(AppWindowToken.this);
2240 } catch (Exception e) {
2241 Slog.w(TAG, "Exception when adding starting window", e);
2242 }
2243 if (surface != null) {
2244 boolean abort = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002245 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002246 // If the window was successfully added, then
2247 // we need to remove it.
chaviwa8f07a72019-05-01 16:25:39 -07002248 if (removed || mStartingData == null) {
Adrian Roosb125e0b2019-10-02 14:55:14 +02002249 ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
2250 "Aborted starting %s: removed=%b startingData=%s",
2251 AppWindowToken.this, removed, mStartingData);
2252
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002253 startingWindow = null;
chaviwa8f07a72019-05-01 16:25:39 -07002254 mStartingData = null;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002255 abort = true;
2256 } else {
2257 startingSurface = surface;
2258 }
Adrian Roosb125e0b2019-10-02 14:55:14 +02002259 if (!abort) {
2260 ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
2261 "Added starting %s: startingWindow=%s startingView=%s",
2262 AppWindowToken.this, startingWindow, startingSurface);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002263 }
2264 }
2265 if (abort) {
2266 surface.remove();
2267 }
Adrian Roosb125e0b2019-10-02 14:55:14 +02002268 } else {
2269 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Surface returned was null: %s",
2270 AppWindowToken.this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002271 }
2272 }
2273 };
2274
2275 private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
2276 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents,
2277 ActivityManager.TaskSnapshot snapshot) {
2278 if (getDisplayContent().mAppTransition.getAppTransition()
2279 == TRANSIT_DOCK_TASK_FROM_RECENTS) {
2280 // TODO(b/34099271): Remove this statement to add back the starting window and figure
2281 // out why it causes flickering, the starting window appears over the thumbnail while
2282 // the docked from recents transition occurs
2283 return STARTING_WINDOW_TYPE_NONE;
2284 } else if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
2285 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2286 } else if (taskSwitch && allowTaskSnapshot) {
Kevin716a9db2018-12-18 16:53:39 -08002287 if (mWmService.mLowRamTaskSnapshotsAndRecents) {
Kevin58b47f12018-12-17 14:09:01 -08002288 // For low RAM devices, we use the splash screen starting window instead of the
2289 // task snapshot starting window.
2290 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2291 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002292 return snapshot == null ? STARTING_WINDOW_TYPE_NONE
2293 : snapshotOrientationSameAsTask(snapshot) || fromRecents
2294 ? STARTING_WINDOW_TYPE_SNAPSHOT : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2295 } else {
2296 return STARTING_WINDOW_TYPE_NONE;
2297 }
2298 }
2299
2300
2301 private boolean snapshotOrientationSameAsTask(ActivityManager.TaskSnapshot snapshot) {
2302 if (snapshot == null) {
2303 return false;
2304 }
2305 return getTask().getConfiguration().orientation == snapshot.getOrientation();
2306 }
2307
2308 void removeStartingWindow() {
2309 if (startingWindow == null) {
chaviwa8f07a72019-05-01 16:25:39 -07002310 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002311 // Starting window has not been added yet, but it is scheduled to be added.
2312 // Go ahead and cancel the request.
Adrian Roosb125e0b2019-10-02 14:55:14 +02002313 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Clearing startingData for token=%s", this);
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) {
Adrian Roosb125e0b2019-10-02 14:55:14 +02002327 ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
2328 "startingWindow was set but startingSurface==null, couldn't "
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002329 + "remove");
Adrian Roosb125e0b2019-10-02 14:55:14 +02002330
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002331 return;
2332 }
2333 } else {
Adrian Roosb125e0b2019-10-02 14:55:14 +02002334 ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
2335 "Tried to remove starting window but startingWindow was null: %s",
2336 this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002337 return;
2338 }
2339
Adrian Roosb125e0b2019-10-02 14:55:14 +02002340 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Schedule remove starting %s startingWindow=%s"
2341 + " startingView=%s Callers=%s",
2342 this, startingWindow, startingSurface, Debug.getCallers(5));
2343
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002344
2345 // Use the same thread to remove the window as we used to add it, as otherwise we end up
2346 // with things in the view hierarchy being called from different threads.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002347 mWmService.mAnimationHandler.post(() -> {
Adrian Roosb125e0b2019-10-02 14:55:14 +02002348 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Removing startingView=%s", surface);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002349 try {
2350 surface.remove();
2351 } catch (Exception e) {
2352 Slog.w(TAG_WM, "Exception when removing starting window", e);
2353 }
2354 });
2355 }
2356
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002357 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -07002358 boolean fillsParent() {
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -07002359 return occludesParent();
Wale Ogunwale51362492016-09-08 17:49:17 -07002360 }
2361
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -07002362 /** Returns true if this activity is opaque and fills the entire space of this task. */
2363 boolean occludesParent() {
2364 return mOccludesParent;
2365 }
2366
2367 boolean setOccludesParent(boolean occludesParent) {
2368 final boolean changed = occludesParent != mOccludesParent;
2369 mOccludesParent = occludesParent;
2370 setMainWindowOpaque(occludesParent);
2371 mWmService.mWindowPlacerLocked.requestTraversal();
2372 return changed;
2373 }
2374
2375 void setMainWindowOpaque(boolean isOpaque) {
2376 final WindowState win = findMainWindow();
2377 if (win == null) {
2378 return;
2379 }
2380 isOpaque = isOpaque & !PixelFormat.formatHasAlpha(win.getAttrs().format);
2381 win.mWinAnimator.setOpaqueLocked(isOpaque);
Wale Ogunwale51362492016-09-08 17:49:17 -07002382 }
2383
Jorim Jaggife762342016-10-13 14:33:27 +02002384 boolean containsDismissKeyguardWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002385 // Window state is transient during relaunch. We are not guaranteed to be frozen during the
2386 // entirety of the relaunch.
2387 if (isRelaunching()) {
2388 return mLastContainsDismissKeyguardWindow;
2389 }
2390
Jorim Jaggife762342016-10-13 14:33:27 +02002391 for (int i = mChildren.size() - 1; i >= 0; i--) {
2392 if ((mChildren.get(i).mAttrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
2393 return true;
2394 }
2395 }
2396 return false;
2397 }
2398
2399 boolean containsShowWhenLockedWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002400 // When we are relaunching, it is possible for us to be unfrozen before our previous
2401 // windows have been added back. Using the cached value ensures that our previous
2402 // showWhenLocked preference is honored until relaunching is complete.
2403 if (isRelaunching()) {
2404 return mLastContainsShowWhenLockedWindow;
2405 }
2406
Jorim Jaggife762342016-10-13 14:33:27 +02002407 for (int i = mChildren.size() - 1; i >= 0; i--) {
2408 if ((mChildren.get(i).mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
2409 return true;
2410 }
2411 }
Bryce Lee081554b2017-05-25 07:52:12 -07002412
Jorim Jaggife762342016-10-13 14:33:27 +02002413 return false;
2414 }
2415
2416 void checkKeyguardFlagsChanged() {
2417 final boolean containsDismissKeyguard = containsDismissKeyguardWindow();
2418 final boolean containsShowWhenLocked = containsShowWhenLockedWindow();
2419 if (containsDismissKeyguard != mLastContainsDismissKeyguardWindow
2420 || containsShowWhenLocked != mLastContainsShowWhenLockedWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002421 mWmService.notifyKeyguardFlagsChanged(null /* callback */,
lumark588a3e82018-07-20 18:53:54 +08002422 getDisplayContent().getDisplayId());
Jorim Jaggife762342016-10-13 14:33:27 +02002423 }
2424 mLastContainsDismissKeyguardWindow = containsDismissKeyguard;
2425 mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
2426 }
2427
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002428 WindowState getImeTargetBelowWindow(WindowState w) {
2429 final int index = mChildren.indexOf(w);
2430 if (index > 0) {
2431 final WindowState target = mChildren.get(index - 1);
2432 if (target.canBeImeTarget()) {
2433 return target;
2434 }
2435 }
2436 return null;
2437 }
2438
2439 WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
2440 WindowState candidate = null;
2441 for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
2442 final WindowState w = mChildren.get(i);
2443 if (w.mRemoved) {
2444 continue;
2445 }
Jorim Jaggi35d328a2018-08-14 17:00:20 +02002446 if (candidate == null) {
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002447 candidate = w;
2448 }
2449 }
2450 return candidate;
2451 }
2452
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002453 /**
2454 * See {@link Activity#setDisablePreviewScreenshots}.
2455 */
2456 void setDisablePreviewScreenshots(boolean disable) {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002457 mDisablePreviewScreenshots = disable;
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002458 }
2459
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002460 /**
Riddle Hsu4bb06be2019-07-02 01:03:07 +08002461 * Sets whether the current launch can turn the screen on.
2462 * @see #currentLaunchCanTurnScreenOn()
chaviwd3bf08d2017-08-01 17:24:59 -07002463 */
Riddle Hsu4bb06be2019-07-02 01:03:07 +08002464 void setCurrentLaunchCanTurnScreenOn(boolean currentLaunchCanTurnScreenOn) {
2465 mCurrentLaunchCanTurnScreenOn = currentLaunchCanTurnScreenOn;
chaviwd3bf08d2017-08-01 17:24:59 -07002466 }
2467
2468 /**
2469 * Indicates whether the current launch can turn the screen on. This is to prevent multiple
2470 * relayouts from turning the screen back on. The screen should only turn on at most
2471 * once per activity resume.
Riddle Hsu4bb06be2019-07-02 01:03:07 +08002472 * <p>
2473 * Note this flag is only meaningful when {@link WindowManager.LayoutParams#FLAG_TURN_SCREEN_ON}
2474 * or {@link ActivityRecord#canTurnScreenOn} is set.
chaviwd3bf08d2017-08-01 17:24:59 -07002475 *
Riddle Hsu4bb06be2019-07-02 01:03:07 +08002476 * @return {@code true} if the activity is ready to turn on the screen.
chaviwd3bf08d2017-08-01 17:24:59 -07002477 */
Riddle Hsu4bb06be2019-07-02 01:03:07 +08002478 boolean currentLaunchCanTurnScreenOn() {
2479 return mCurrentLaunchCanTurnScreenOn;
chaviwd3bf08d2017-08-01 17:24:59 -07002480 }
2481
2482 /**
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002483 * Retrieves whether we'd like to generate a snapshot that's based solely on the theme. This is
2484 * the case when preview screenshots are disabled {@link #setDisablePreviewScreenshots} or when
2485 * we can't take a snapshot for other reasons, for example, if we have a secure window.
2486 *
2487 * @return True if we need to generate an app theme snapshot, false if we'd like to take a real
2488 * screenshot.
2489 */
2490 boolean shouldUseAppThemeSnapshot() {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002491 return mDisablePreviewScreenshots || forAllWindows(w -> (w.mAttrs.flags & FLAG_SECURE) != 0,
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002492 true /* topToBottom */);
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002493 }
2494
Jorim Jaggibe418292018-03-26 16:14:12 +02002495 SurfaceControl getAppAnimationLayer() {
Jorim Jaggi391790622018-04-18 15:30:44 +02002496 return getAppAnimationLayer(isActivityTypeHome() ? ANIMATION_LAYER_HOME
2497 : needsZBoost() ? ANIMATION_LAYER_BOOSTED
2498 : ANIMATION_LAYER_STANDARD);
Jorim Jaggibe418292018-03-26 16:14:12 +02002499 }
2500
chaviw23ee71c2017-12-18 11:29:41 -08002501 @Override
Jorim Jaggi596a1992017-12-29 14:48:02 +01002502 public SurfaceControl getAnimationLeashParent() {
Robert Carrb9506032018-02-13 13:54:00 -08002503 // For transitions in the pinned stack (menu activity) we just let them occur as a child
2504 // of the pinned stack.
Issei Suzuki71142152019-08-15 14:39:40 +02002505 // All normal app transitions take place in an animation layer which is below the pinned
2506 // stack but may be above the parent stacks of the given animating apps by default. When
2507 // a new hierarchical animation is enabled, we just let them occur as a child of the parent
2508 // stack, i.e. the hierarchy of the surfaces is unchanged.
2509 if (inPinnedWindowingMode()) {
Robert Carrb9506032018-02-13 13:54:00 -08002510 return getStack().getSurfaceControl();
Issei Suzuki71142152019-08-15 14:39:40 +02002511 } else if (WindowManagerService.sHierarchicalAnimations) {
2512 return super.getAnimationLeashParent();
2513 } else {
2514 return getAppAnimationLayer();
Robert Carrb9506032018-02-13 13:54:00 -08002515 }
chaviw23ee71c2017-12-18 11:29:41 -08002516 }
2517
lumarkb5a78b32019-04-25 20:31:30 +08002518
2519 @VisibleForTesting
2520 boolean shouldAnimate(int transit) {
Jorim Jaggic6976f02018-04-18 16:31:07 +02002521 final boolean isSplitScreenPrimary =
2522 getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
2523 final boolean allowSplitScreenPrimaryAnimation = transit != TRANSIT_WALLPAPER_OPEN;
2524
lumarkb5a78b32019-04-25 20:31:30 +08002525 // Don't animate while the task runs recents animation but only if we are in the mode
2526 // where we cancel with deferred screenshot, which means that the controller has
2527 // transformed the task.
lumark54284462019-03-05 20:44:27 +08002528 final RecentsAnimationController controller = mWmService.getRecentsAnimationController();
lumarkb5a78b32019-04-25 20:31:30 +08002529 if (controller != null && controller.isAnimatingTask(getTask())
Winson Chung7a545ae2019-07-16 14:52:13 -07002530 && controller.shouldDeferCancelUntilNextTransition()) {
lumark54284462019-03-05 20:44:27 +08002531 return false;
2532 }
2533
Jorim Jaggic6976f02018-04-18 16:31:07 +02002534 // We animate always if it's not split screen primary, and only some special cases in split
2535 // screen primary because it causes issues with stack clipping when we run an un-minimize
2536 // animation at the same time.
2537 return !isSplitScreenPrimary || allowSplitScreenPrimaryAnimation;
2538 }
2539
Vishnu Naira2977262018-07-26 13:31:26 -07002540 /**
2541 * Creates a layer to apply crop to an animation.
2542 */
2543 private SurfaceControl createAnimationBoundsLayer(Transaction t) {
Adrian Roosb125e0b2019-10-02 14:55:14 +02002544 ProtoLog.i(WM_DEBUG_APP_TRANSITIONS_ANIM, "Creating animation bounds layer");
Vishnu Naira2977262018-07-26 13:31:26 -07002545 final SurfaceControl.Builder builder = makeAnimationLeash()
2546 .setParent(getAnimationLeashParent())
Vishnu Naire86bd982018-11-28 13:23:17 -08002547 .setName(getSurfaceControl() + " - animation-bounds");
Vishnu Naira2977262018-07-26 13:31:26 -07002548 final SurfaceControl boundsLayer = builder.build();
2549 t.show(boundsLayer);
2550 return boundsLayer;
2551 }
2552
Evan Roskyed6767f2018-10-26 17:21:06 -07002553 @Override
2554 Rect getDisplayedBounds() {
2555 final Task task = getTask();
2556 if (task != null) {
2557 final Rect overrideDisplayedBounds = task.getOverrideDisplayedBounds();
2558 if (!overrideDisplayedBounds.isEmpty()) {
2559 return overrideDisplayedBounds;
2560 }
2561 }
2562 return getBounds();
2563 }
2564
Evan Rosky641daea2019-04-24 14:45:24 -07002565 @VisibleForTesting
2566 Rect getAnimationBounds(int appStackClipMode) {
2567 if (appStackClipMode == STACK_CLIP_BEFORE_ANIM && getStack() != null) {
2568 // Using the stack bounds here effectively applies the clipping before animation.
2569 return getStack().getBounds();
2570 }
2571 // Use task-bounds if available so that activity-level letterbox (maxAspectRatio) is
2572 // included in the animation.
2573 return getTask() != null ? getTask().getBounds() : getBounds();
2574 }
2575
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002576 boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter,
2577 boolean isVoiceInteraction) {
2578
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002579 if (mWmService.mDisableTransitionAnimation || !shouldAnimate(transit)) {
Adrian Roosb125e0b2019-10-02 14:55:14 +02002580 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
2581 "applyAnimation: transition animation is disabled or skipped. "
2582 + "atoken=%s", this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002583 cancelAnimation();
2584 return false;
2585 }
2586
2587 // Only apply an animation if the display isn't frozen. If it is frozen, there is no reason
2588 // to animate and it can cause strange artifacts when we unfreeze the display if some
2589 // different animation is running.
2590 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#applyAnimationLocked");
2591 if (okToAnimate()) {
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002592 final AnimationAdapter adapter;
Evan Rosky2289ba12018-11-19 18:28:18 -08002593 AnimationAdapter thumbnailAdapter = null;
Evan Rosky4fb1e912019-03-06 13:54:43 -08002594
Evan Rosky641daea2019-04-24 14:45:24 -07002595 final int appStackClipMode =
2596 getDisplayContent().mAppTransition.getAppStackClipMode();
2597
2598 // Separate position and size for use in animators.
2599 mTmpRect.set(getAnimationBounds(appStackClipMode));
Evan Rosky4fb1e912019-03-06 13:54:43 -08002600 mTmpPoint.set(mTmpRect.left, mTmpRect.top);
2601 mTmpRect.offsetTo(0, 0);
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002602
Evan Roskyec9488c2019-03-01 19:32:12 -08002603 final boolean isChanging = AppTransition.isChangeTransit(transit) && enter
2604 && getDisplayContent().mChangingApps.contains(this);
Evan Rosky2289ba12018-11-19 18:28:18 -08002605
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002606 // Delaying animation start isn't compatible with remote animations at all.
lumark588a3e82018-07-20 18:53:54 +08002607 if (getDisplayContent().mAppTransition.getRemoteAnimationController() != null
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002608 && !mSurfaceAnimator.isAnimationStartDelayed()) {
Evan Rosky2289ba12018-11-19 18:28:18 -08002609 RemoteAnimationRecord adapters =
2610 getDisplayContent().mAppTransition.getRemoteAnimationController()
2611 .createRemoteAnimationRecord(this, mTmpPoint, mTmpRect,
2612 (isChanging ? mTransitStartRect : null));
2613 adapter = adapters.mAdapter;
2614 thumbnailAdapter = adapters.mThumbnailAdapter;
2615 } else if (isChanging) {
Evan Roskycf76bed2019-01-15 10:33:58 -08002616 final float durationScale = mWmService.getTransitionAnimationScaleLocked();
Evan Rosky2289ba12018-11-19 18:28:18 -08002617 mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y);
2618 adapter = new LocalAnimationAdapter(
2619 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
Evan Roskycf76bed2019-01-15 10:33:58 -08002620 getDisplayContent().getDisplayInfo(), durationScale,
Evan Rosky2289ba12018-11-19 18:28:18 -08002621 true /* isAppAnimation */, false /* isThumbnail */),
2622 mWmService.mSurfaceAnimationRunner);
Evan Rosky966759f2019-01-15 10:33:58 -08002623 if (mThumbnail != null) {
2624 thumbnailAdapter = new LocalAnimationAdapter(
2625 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
Evan Roskycf76bed2019-01-15 10:33:58 -08002626 getDisplayContent().getDisplayInfo(), durationScale,
Evan Rosky966759f2019-01-15 10:33:58 -08002627 true /* isAppAnimation */, true /* isThumbnail */),
2628 mWmService.mSurfaceAnimationRunner);
2629 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002630 mTransit = transit;
2631 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002632 } else {
Vishnu Naira2977262018-07-26 13:31:26 -07002633 mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM);
2634
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002635 final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
2636 if (a != null) {
Lucas Dupin95acf432019-04-29 17:55:38 -07002637 // Only apply corner radius to animation if we're not in multi window mode.
2638 // We don't want rounded corners when in pip or split screen.
2639 final float windowCornerRadius = !inMultiWindowMode()
2640 ? getDisplayContent().getWindowCornerRadius()
2641 : 0;
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002642 adapter = new LocalAnimationAdapter(
2643 new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
lumark588a3e82018-07-20 18:53:54 +08002644 getDisplayContent().mAppTransition.canSkipFirstFrame(),
Vishnu Naira2977262018-07-26 13:31:26 -07002645 appStackClipMode,
Lucas Dupin3e1dc202018-12-02 15:14:20 -08002646 true /* isAppAnimation */,
Lucas Dupin95acf432019-04-29 17:55:38 -07002647 windowCornerRadius),
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002648 mWmService.mSurfaceAnimationRunner);
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002649 if (a.getZAdjustment() == Animation.ZORDER_TOP) {
2650 mNeedsZBoost = true;
2651 }
2652 mTransit = transit;
lumark588a3e82018-07-20 18:53:54 +08002653 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002654 } else {
2655 adapter = null;
chaviw23ee71c2017-12-18 11:29:41 -08002656 }
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002657 }
2658 if (adapter != null) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002659 startAnimation(getPendingTransaction(), adapter, !isVisible());
Jorim Jaggi82c17862018-02-21 17:50:18 +01002660 if (adapter.getShowWallpaper()) {
2661 mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2662 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002663 if (thumbnailAdapter != null) {
2664 mThumbnail.startAnimation(
2665 getPendingTransaction(), thumbnailAdapter, !isVisible());
2666 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002667 }
2668 } else {
2669 cancelAnimation();
2670 }
2671 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2672
2673 return isReallyAnimating();
2674 }
2675
2676 private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
2677 boolean isVoiceInteraction) {
2678 final DisplayContent displayContent = getTask().getDisplayContent();
2679 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2680 final int width = displayInfo.appWidth;
2681 final int height = displayInfo.appHeight;
Adrian Roosb125e0b2019-10-02 14:55:14 +02002682 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
2683 "applyAnimation: atoken=%s", this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002684
2685 // Determine the visible rect to calculate the thumbnail clip
2686 final WindowState win = findMainWindow();
2687 final Rect frame = new Rect(0, 0, width, height);
2688 final Rect displayFrame = new Rect(0, 0,
2689 displayInfo.logicalWidth, displayInfo.logicalHeight);
2690 final Rect insets = new Rect();
2691 final Rect stableInsets = new Rect();
2692 Rect surfaceInsets = null;
2693 final boolean freeform = win != null && win.inFreeformWindowingMode();
2694 if (win != null) {
2695 // Containing frame will usually cover the whole screen, including dialog windows.
2696 // For freeform workspace windows it will not cover the whole screen and it also
2697 // won't exactly match the final freeform window frame (e.g. when overlapping with
2698 // the status bar). In that case we need to use the final frame.
2699 if (freeform) {
chaviw492139a2018-07-16 16:07:35 -07002700 frame.set(win.getFrameLw());
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002701 } else if (win.isLetterboxedAppWindow()) {
2702 frame.set(getTask().getBounds());
Winson Chungc1674272018-02-21 10:15:17 -08002703 } else if (win.isDockedResizing()) {
2704 // If we are animating while docked resizing, then use the stack bounds as the
2705 // animation target (which will be different than the task bounds)
2706 frame.set(getTask().getParent().getBounds());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002707 } else {
chaviw553b0212018-07-12 13:37:01 -07002708 frame.set(win.getContainingFrame());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002709 }
2710 surfaceInsets = win.getAttrs().surfaceInsets;
Adrian Roos20e07892018-02-23 19:12:01 +01002711 // XXX(b/72757033): These are insets relative to the window frame, but we're really
2712 // interested in the insets relative to the frame we chose in the if-blocks above.
chaviw9c81e632018-07-31 11:17:52 -07002713 win.getContentInsets(insets);
2714 win.getStableInsets(stableInsets);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002715 }
2716
2717 if (mLaunchTaskBehind) {
2718 // Differentiate the two animations. This one which is briefly on the screen
2719 // gets the !enter animation, and the other activity which remains on the
2720 // screen gets the enter animation. Both appear in the mOpeningApps set.
2721 enter = false;
2722 }
Adrian Roosb125e0b2019-10-02 14:55:14 +02002723 ProtoLog.d(WM_DEBUG_APP_TRANSITIONS,
2724 "Loading animation for app transition. transit=%s enter=%b frame=%s insets=%s "
2725 + "surfaceInsets=%s",
2726 AppTransition.appTransitionToString(transit), enter, frame, insets, surfaceInsets);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002727 final Configuration displayConfig = displayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08002728 final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002729 displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
2730 surfaceInsets, stableInsets, isVoiceInteraction, freeform, getTask().mTaskId);
2731 if (a != null) {
2732 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
2733 final int containingWidth = frame.width();
2734 final int containingHeight = frame.height();
2735 a.initialize(containingWidth, containingHeight, width, height);
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002736 a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002737 }
2738 return a;
2739 }
2740
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002741 @Override
Jorim Jaggi6de61012018-03-19 14:53:23 +01002742 public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
2743 return mAnimatingAppWindowTokenRegistry != null
2744 && mAnimatingAppWindowTokenRegistry.notifyAboutToFinish(
2745 this, endDeferFinishCallback);
2746 }
2747
2748 @Override
lumarkf6f34942019-04-29 16:56:50 +08002749 public void onAnimationLeashLost(Transaction t) {
2750 super.onAnimationLeashLost(t);
Vishnu Naira2977262018-07-26 13:31:26 -07002751 if (mAnimationBoundsLayer != null) {
Robert Carr71200f22019-02-05 09:44:53 -08002752 t.remove(mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002753 mAnimationBoundsLayer = null;
2754 }
2755
Jorim Jaggi6de61012018-03-19 14:53:23 +01002756 if (mAnimatingAppWindowTokenRegistry != null) {
2757 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
2758 }
2759 }
2760
2761 @Override
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002762 protected void setLayer(Transaction t, int layer) {
2763 if (!mSurfaceAnimator.hasLeash()) {
2764 t.setLayer(mSurfaceControl, layer);
2765 }
2766 }
2767
2768 @Override
2769 protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
2770 if (!mSurfaceAnimator.hasLeash()) {
2771 t.setRelativeLayer(mSurfaceControl, relativeTo, layer);
2772 }
2773 }
2774
2775 @Override
2776 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
2777 if (!mSurfaceAnimator.hasLeash()) {
Robert Carr10584fa2019-01-14 15:55:19 -08002778 t.reparent(mSurfaceControl, newParent);
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002779 }
2780 }
2781
2782 @Override
2783 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002784 // The leash is parented to the animation layer. We need to preserve the z-order by using
2785 // the prefix order index, but we boost if necessary.
Robert Carrb9506032018-02-13 13:54:00 -08002786 int layer = 0;
2787 if (!inPinnedWindowingMode()) {
2788 layer = getPrefixOrderIndex();
2789 } else {
2790 // Pinned stacks have animations take place within themselves rather than an animation
2791 // layer so we need to preserve the order relative to the stack (e.g. the order of our
2792 // task/parent).
2793 layer = getParent().getPrefixOrderIndex();
2794 }
2795
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002796 if (mNeedsZBoost) {
2797 layer += Z_BOOST_BASE;
2798 }
Jorim Jaggi9cd99132019-04-24 17:41:35 +02002799 if (!mNeedsAnimationBoundsLayer) {
2800 leash.setLayer(layer);
2801 }
Robert Carr2f8aa392018-01-31 14:46:51 -08002802
2803 final DisplayContent dc = getDisplayContent();
Jorim Jaggibe418292018-03-26 16:14:12 +02002804 dc.assignStackOrdering();
Evan Rosky2289ba12018-11-19 18:28:18 -08002805
2806 if (leash == mTransitChangeLeash) {
2807 // This is a temporary state so skip any animation notifications
2808 return;
2809 } else if (mTransitChangeLeash != null) {
2810 // unparent mTransitChangeLeash for clean-up
Evan Rosky25b56192019-02-06 16:10:56 -08002811 clearChangeLeash(t, false /* cancel */);
Evan Rosky2289ba12018-11-19 18:28:18 -08002812 }
2813
Jorim Jaggi6de61012018-03-19 14:53:23 +01002814 if (mAnimatingAppWindowTokenRegistry != null) {
2815 mAnimatingAppWindowTokenRegistry.notifyStarting(this);
2816 }
Vishnu Naira2977262018-07-26 13:31:26 -07002817
2818 // If the animation needs to be cropped then an animation bounds layer is created as a child
2819 // of the pinned stack or animation layer. The leash is then reparented to this new layer.
2820 if (mNeedsAnimationBoundsLayer) {
Evan Rosky7735d352019-03-18 17:27:27 -07002821 mTmpRect.setEmpty();
2822 final Task task = getTask();
2823 if (getDisplayContent().mAppTransitionController.isTransitWithinTask(
2824 getTransit(), task)) {
2825 task.getBounds(mTmpRect);
2826 } else {
2827 final TaskStack stack = getStack();
2828 if (stack == null) {
2829 return;
2830 }
2831 // Set clip rect to stack bounds.
2832 stack.getBounds(mTmpRect);
Vishnu Naira2977262018-07-26 13:31:26 -07002833 }
2834 mAnimationBoundsLayer = createAnimationBoundsLayer(t);
2835
Vishnu Naira2977262018-07-26 13:31:26 -07002836 // Crop to stack bounds.
2837 t.setWindowCrop(mAnimationBoundsLayer, mTmpRect);
Jorim Jaggi9cd99132019-04-24 17:41:35 +02002838 t.setLayer(mAnimationBoundsLayer, layer);
Vishnu Naira2977262018-07-26 13:31:26 -07002839
2840 // Reparent leash to animation bounds layer.
Robert Carr10584fa2019-01-14 15:55:19 -08002841 t.reparent(leash, mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002842 }
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002843 }
2844
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002845 /**
2846 * This must be called while inside a transaction.
2847 */
2848 void showAllWindowsLocked() {
2849 forAllWindows(windowState -> {
2850 if (DEBUG_VISIBILITY) Slog.v(TAG, "performing show on: " + windowState);
2851 windowState.performShowLocked();
2852 }, false /* traverseTopToBottom */);
Jorim Jaggia5e10572017-11-15 14:36:26 +01002853 }
2854
2855 @Override
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002856 protected void onAnimationFinished() {
2857 super.onAnimationFinished();
2858
Ian8b2822e2019-05-14 11:59:02 -07002859 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#onAnimationFinished");
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002860 mTransit = TRANSIT_UNSET;
2861 mTransitFlags = 0;
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002862 mNeedsZBoost = false;
Vishnu Naira2977262018-07-26 13:31:26 -07002863 mNeedsAnimationBoundsLayer = false;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002864
2865 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER,
2866 "AppWindowToken");
2867
Jorim Jaggi988f6682017-11-17 17:46:43 +01002868 clearThumbnail();
Jorim Jaggi752cd822018-03-29 16:29:18 +02002869 setClientHidden(isHidden() && hiddenRequested);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002870
lumarkff0ab692018-11-05 20:32:30 +08002871 getDisplayContent().computeImeTargetIfNeeded(this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002872
2873 if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + this
2874 + ": reportedVisible=" + reportedVisible
2875 + " okToDisplay=" + okToDisplay()
2876 + " okToAnimate=" + okToAnimate()
2877 + " startingDisplayed=" + startingDisplayed);
2878
Evan Rosky2289ba12018-11-19 18:28:18 -08002879 // clean up thumbnail window
2880 if (mThumbnail != null) {
2881 mThumbnail.destroy();
2882 mThumbnail = null;
2883 }
2884
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002885 // WindowState.onExitAnimationDone might modify the children list, so make a copy and then
2886 // traverse the copy.
2887 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
2888 children.forEach(WindowState::onExitAnimationDone);
2889
lumark588a3e82018-07-20 18:53:54 +08002890 getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002891 scheduleAnimation();
Jorim Jaggi9b5e3312019-03-01 18:08:00 +01002892
2893 mActivityRecord.onAnimationFinished();
Ian8b2822e2019-05-14 11:59:02 -07002894 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002895 }
2896
2897 @Override
2898 boolean isAppAnimating() {
2899 return isSelfAnimating();
2900 }
2901
2902 @Override
2903 boolean isSelfAnimating() {
2904 // If we are about to start a transition, we also need to be considered animating.
2905 return isWaitingForTransitionStart() || isReallyAnimating();
2906 }
2907
2908 /**
2909 * @return True if and only if we are actually running an animation. Note that
2910 * {@link #isSelfAnimating} also returns true if we are waiting for an animation to
2911 * start.
2912 */
2913 private boolean isReallyAnimating() {
2914 return super.isSelfAnimating();
2915 }
2916
Evan Rosky25b56192019-02-06 16:10:56 -08002917 /**
2918 * @param cancel {@code true} if clearing the leash due to cancelling instead of transferring
2919 * to another leash.
2920 */
2921 private void clearChangeLeash(Transaction t, boolean cancel) {
2922 if (mTransitChangeLeash == null) {
2923 return;
2924 }
2925 if (cancel) {
2926 clearThumbnail();
2927 SurfaceControl sc = getSurfaceControl();
2928 SurfaceControl parentSc = getParentSurfaceControl();
2929 // Don't reparent if surface is getting destroyed
2930 if (parentSc != null && sc != null) {
2931 t.reparent(sc, getParentSurfaceControl());
2932 }
2933 }
2934 t.hide(mTransitChangeLeash);
Evan Rosky08e20932019-05-14 10:54:07 -07002935 t.remove(mTransitChangeLeash);
Evan Rosky25b56192019-02-06 16:10:56 -08002936 mTransitChangeLeash = null;
2937 if (cancel) {
lumarkf6f34942019-04-29 16:56:50 +08002938 onAnimationLeashLost(t);
Evan Rosky25b56192019-02-06 16:10:56 -08002939 }
2940 }
2941
Jorim Jaggi988f6682017-11-17 17:46:43 +01002942 @Override
2943 void cancelAnimation() {
Evan Rosky2289ba12018-11-19 18:28:18 -08002944 cancelAnimationOnly();
Jorim Jaggi988f6682017-11-17 17:46:43 +01002945 clearThumbnail();
Evan Rosky25b56192019-02-06 16:10:56 -08002946 clearChangeLeash(getPendingTransaction(), true /* cancel */);
Evan Rosky2289ba12018-11-19 18:28:18 -08002947 }
2948
2949 /**
2950 * This only cancels the animation. It doesn't do other teardown like cleaning-up thumbnail
2951 * or interim leashes.
2952 * <p>
2953 * Used when canceling in preparation for starting a new animation.
2954 */
2955 void cancelAnimationOnly() {
2956 super.cancelAnimation();
Jorim Jaggi988f6682017-11-17 17:46:43 +01002957 }
2958
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002959 boolean isWaitingForTransitionStart() {
lumark588a3e82018-07-20 18:53:54 +08002960 return getDisplayContent().mAppTransition.isTransitionSet()
2961 && (getDisplayContent().mOpeningApps.contains(this)
Evan Rosky2289ba12018-11-19 18:28:18 -08002962 || getDisplayContent().mClosingApps.contains(this)
2963 || getDisplayContent().mChangingApps.contains(this));
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002964 }
2965
2966 public int getTransit() {
2967 return mTransit;
2968 }
2969
2970 int getTransitFlags() {
2971 return mTransitFlags;
2972 }
2973
Jorim Jaggi988f6682017-11-17 17:46:43 +01002974 void attachThumbnailAnimation() {
2975 if (!isReallyAnimating()) {
2976 return;
2977 }
2978 final int taskId = getTask().mTaskId;
2979 final GraphicBuffer thumbnailHeader =
lumark588a3e82018-07-20 18:53:54 +08002980 getDisplayContent().mAppTransition.getAppTransitionThumbnailHeader(taskId);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002981 if (thumbnailHeader == null) {
Adrian Roosb125e0b2019-10-02 14:55:14 +02002982 ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, "No thumbnail header bitmap for: %d", taskId);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002983 return;
2984 }
2985 clearThumbnail();
Vishnu Nair33197392019-08-30 10:29:37 -07002986 mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory, getPendingTransaction(),
2987 this, thumbnailHeader);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002988 mThumbnail.startAnimation(getPendingTransaction(), loadThumbnailAnimation(thumbnailHeader));
2989 }
2990
Tony Mak64b8d562017-12-28 17:44:02 +00002991 /**
2992 * Attaches a surface with a thumbnail for the
2993 * {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation.
2994 */
2995 void attachCrossProfileAppsThumbnailAnimation() {
2996 if (!isReallyAnimating()) {
2997 return;
2998 }
2999 clearThumbnail();
3000
3001 final WindowState win = findMainWindow();
3002 if (win == null) {
3003 return;
3004 }
chaviw492139a2018-07-16 16:07:35 -07003005 final Rect frame = win.getFrameLw();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08003006 final int thumbnailDrawableRes = getTask().mUserId == mWmService.mCurrentUserId
Tony Mak64b8d562017-12-28 17:44:02 +00003007 ? R.drawable.ic_account_circle
Tony Makda4af232018-04-27 11:01:10 +01003008 : R.drawable.ic_corp_badge;
Tony Mak64b8d562017-12-28 17:44:02 +00003009 final GraphicBuffer thumbnail =
lumark588a3e82018-07-20 18:53:54 +08003010 getDisplayContent().mAppTransition
Tony Mak64b8d562017-12-28 17:44:02 +00003011 .createCrossProfileAppsThumbnail(thumbnailDrawableRes, frame);
3012 if (thumbnail == null) {
3013 return;
3014 }
Vishnu Nair33197392019-08-30 10:29:37 -07003015 mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory,
3016 getPendingTransaction(), this, thumbnail);
Tony Mak64b8d562017-12-28 17:44:02 +00003017 final Animation animation =
lumark588a3e82018-07-20 18:53:54 +08003018 getDisplayContent().mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(
chaviw492139a2018-07-16 16:07:35 -07003019 win.getFrameLw());
Tony Mak64b8d562017-12-28 17:44:02 +00003020 mThumbnail.startAnimation(getPendingTransaction(), animation, new Point(frame.left,
3021 frame.top));
3022 }
3023
Jorim Jaggi988f6682017-11-17 17:46:43 +01003024 private Animation loadThumbnailAnimation(GraphicBuffer thumbnailHeader) {
3025 final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
3026
3027 // If this is a multi-window scenario, we use the windows frame as
3028 // destination of the thumbnail header animation. If this is a full screen
3029 // window scenario, we use the whole display as the target.
3030 WindowState win = findMainWindow();
3031 Rect appRect = win != null ? win.getContentFrameLw() :
3032 new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
chaviw9c81e632018-07-31 11:17:52 -07003033 final Rect insets = win != null ? win.getContentInsets() : null;
Jorim Jaggi988f6682017-11-17 17:46:43 +01003034 final Configuration displayConfig = mDisplayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08003035 return getDisplayContent().mAppTransition.createThumbnailAspectScaleAnimationLocked(
Jorim Jaggi988f6682017-11-17 17:46:43 +01003036 appRect, insets, thumbnailHeader, getTask().mTaskId, displayConfig.uiMode,
3037 displayConfig.orientation);
3038 }
3039
3040 private void clearThumbnail() {
3041 if (mThumbnail == null) {
3042 return;
3043 }
3044 mThumbnail.destroy();
3045 mThumbnail = null;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003046 }
3047
Jorim Jaggif84e2f62018-01-16 14:17:59 +01003048 void registerRemoteAnimations(RemoteAnimationDefinition definition) {
3049 mRemoteAnimationDefinition = definition;
3050 }
3051
3052 RemoteAnimationDefinition getRemoteAnimationDefinition() {
3053 return mRemoteAnimationDefinition;
3054 }
3055
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003056 @Override
3057 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
3058 super.dump(pw, prefix, dumpAll);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003059 if (appToken != null) {
Wale Ogunwale72919d22016-12-08 18:58:50 -08003060 pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003061 }
Winson Chung48b25652018-10-22 14:04:30 -07003062 pw.println(prefix + "component=" + mActivityComponent.flattenToShortString());
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08003063 pw.print(prefix); pw.print("task="); pw.println(getTask());
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -07003064 pw.print(prefix); pw.print(" mOccludesParent="); pw.print(mOccludesParent);
Wale Ogunwale51362492016-09-08 17:49:17 -07003065 pw.print(" mOrientation="); pw.println(mOrientation);
Wale Ogunwale89973222017-04-23 18:39:45 -07003066 pw.println(prefix + "hiddenRequested=" + hiddenRequested + " mClientHidden=" + mClientHidden
3067 + ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "")
3068 + " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible);
Craig Mautner59431632012-04-04 11:56:44 -07003069 if (paused) {
3070 pw.print(prefix); pw.print("paused="); pw.println(paused);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003071 }
Wale Ogunwale9017ec02016-02-25 08:55:25 -08003072 if (mAppStopped) {
3073 pw.print(prefix); pw.print("mAppStopped="); pw.println(mAppStopped);
3074 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07003075 if (mNumInterestingWindows != 0 || mNumDrawnWindows != 0
Jorim Jaggib0fc8172017-11-23 17:04:08 +00003076 || allDrawn || mLastAllDrawn) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07003077 pw.print(prefix); pw.print("mNumInterestingWindows=");
3078 pw.print(mNumInterestingWindows);
3079 pw.print(" mNumDrawnWindows="); pw.print(mNumDrawnWindows);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003080 pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
Craig Mautner6fbda632012-07-03 09:26:39 -07003081 pw.print(" allDrawn="); pw.print(allDrawn);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00003082 pw.print(" lastAllDrawn="); pw.print(mLastAllDrawn);
Craig Mautner6fbda632012-07-03 09:26:39 -07003083 pw.println(")");
3084 }
3085 if (inPendingTransaction) {
3086 pw.print(prefix); pw.print("inPendingTransaction=");
3087 pw.println(inPendingTransaction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003088 }
chaviwa8f07a72019-05-01 16:25:39 -07003089 if (mStartingData != null || removed || firstWindowDrawn || mIsExiting) {
3090 pw.print(prefix); pw.print("startingData="); pw.print(mStartingData);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003091 pw.print(" removed="); pw.print(removed);
Craig Mautner3d7ca312015-01-08 10:56:00 -08003092 pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
Craig Mautner799bc1d2015-01-14 10:33:48 -08003093 pw.print(" mIsExiting="); pw.println(mIsExiting);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003094 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08003095 if (startingWindow != null || startingSurface != null
Wale Ogunwale6c459212017-05-17 08:56:03 -07003096 || startingDisplayed || startingMoved || mHiddenSetFromTransferredStartingWindow) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003097 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08003098 pw.print(" startingSurface="); pw.print(startingSurface);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003099 pw.print(" startingDisplayed="); pw.print(startingDisplayed);
Wale Ogunwale6c459212017-05-17 08:56:03 -07003100 pw.print(" startingMoved="); pw.print(startingMoved);
3101 pw.println(" mHiddenSetFromTransferredStartingWindow="
3102 + mHiddenSetFromTransferredStartingWindow);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003103 }
Jorim Jaggi0429f352015-12-22 16:29:16 +01003104 if (!mFrozenBounds.isEmpty()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08003105 pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
Jorim Jaggi26c8c422016-05-09 19:57:25 -07003106 pw.print(prefix); pw.print("mFrozenMergedConfig="); pw.println(mFrozenMergedConfig);
Chong Zhangd78ddb42016-03-02 17:01:14 -08003107 }
3108 if (mPendingRelaunchCount != 0) {
3109 pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount);
Jorim Jaggi0429f352015-12-22 16:29:16 +01003110 }
Riddle Hsub398da32019-01-21 21:48:16 +08003111 if (mSizeCompatScale != 1f || mSizeCompatBounds != null) {
3112 pw.println(prefix + "mSizeCompatScale=" + mSizeCompatScale + " mSizeCompatBounds="
3113 + mSizeCompatBounds);
3114 }
Wale Ogunwalee287e192017-04-21 09:30:12 -07003115 if (mRemovingFromDisplay) {
3116 pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay);
3117 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003118 }
3119
3120 @Override
3121 void setHidden(boolean hidden) {
3122 super.setHidden(hidden);
3123 scheduleAnimation();
3124 }
3125
3126 @Override
3127 void prepareSurfaces() {
3128 // isSelfAnimating also returns true when we are about to start a transition, so we need
3129 // to check super here.
3130 final boolean reallyAnimating = super.isSelfAnimating();
3131 final boolean show = !isHidden() || reallyAnimating;
Robert Carrd8e4fb72019-01-31 11:14:30 -08003132
3133 if (mSurfaceControl != null) {
3134 if (show && !mLastSurfaceShowing) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003135 getPendingTransaction().show(mSurfaceControl);
Robert Carrd8e4fb72019-01-31 11:14:30 -08003136 } else if (!show && mLastSurfaceShowing) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003137 getPendingTransaction().hide(mSurfaceControl);
Robert Carrd8e4fb72019-01-31 11:14:30 -08003138 }
Jorim Jaggi4d1835d2017-08-31 17:28:27 +02003139 }
Jorim Jaggi988f6682017-11-17 17:46:43 +01003140 if (mThumbnail != null) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003141 mThumbnail.setShowing(getPendingTransaction(), show);
Jorim Jaggi988f6682017-11-17 17:46:43 +01003142 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003143 mLastSurfaceShowing = show;
3144 super.prepareSurfaces();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003145 }
3146
Jorim Jaggi77d0f36c2018-03-16 17:49:49 +01003147 /**
3148 * @return Whether our {@link #getSurfaceControl} is currently showing.
3149 */
3150 boolean isSurfaceShowing() {
3151 return mLastSurfaceShowing;
3152 }
3153
Jorim Jaggib0fc8172017-11-23 17:04:08 +00003154 boolean isFreezingScreen() {
3155 return mFreezingScreen;
3156 }
3157
3158 @Override
3159 boolean needsZBoost() {
3160 return mNeedsZBoost || super.needsZBoost();
3161 }
3162
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07003163 @CallSuper
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003164 @Override
Nataniel Borges023ecb52019-01-16 14:15:43 -08003165 public void writeToProto(ProtoOutputStream proto, long fieldId,
3166 @WindowTraceLogLevel int logLevel) {
3167 // Critical log level logs only visible elements to mitigate performance overheard
3168 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
3169 return;
3170 }
3171
Steven Timotiusaf03df62017-07-18 16:56:43 -07003172 final long token = proto.start(fieldId);
3173 writeNameToProto(proto, NAME);
Nataniel Borges023ecb52019-01-16 14:15:43 -08003174 super.writeToProto(proto, WINDOW_TOKEN, logLevel);
Vishnu Nair04ab4392018-01-10 11:00:06 -08003175 proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing);
3176 proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart());
3177 proto.write(IS_REALLY_ANIMATING, isReallyAnimating());
3178 if (mThumbnail != null){
3179 mThumbnail.writeToProto(proto, THUMBNAIL);
3180 }
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -07003181 proto.write(FILLS_PARENT, mOccludesParent);
Vishnu Nair04ab4392018-01-10 11:00:06 -08003182 proto.write(APP_STOPPED, mAppStopped);
3183 proto.write(HIDDEN_REQUESTED, hiddenRequested);
3184 proto.write(CLIENT_HIDDEN, mClientHidden);
3185 proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient);
3186 proto.write(REPORTED_DRAWN, reportedDrawn);
3187 proto.write(REPORTED_VISIBLE, reportedVisible);
3188 proto.write(NUM_INTERESTING_WINDOWS, mNumInterestingWindows);
3189 proto.write(NUM_DRAWN_WINDOWS, mNumDrawnWindows);
3190 proto.write(ALL_DRAWN, allDrawn);
3191 proto.write(LAST_ALL_DRAWN, mLastAllDrawn);
3192 proto.write(REMOVED, removed);
Nataniel Borges023ecb52019-01-16 14:15:43 -08003193 if (startingWindow != null) {
Vishnu Nair04ab4392018-01-10 11:00:06 -08003194 startingWindow.writeIdentifierToProto(proto, STARTING_WINDOW);
3195 }
3196 proto.write(STARTING_DISPLAYED, startingDisplayed);
3197 proto.write(STARTING_MOVED, startingMoved);
3198 proto.write(HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW,
3199 mHiddenSetFromTransferredStartingWindow);
3200 for (Rect bounds : mFrozenBounds) {
3201 bounds.writeToProto(proto, FROZEN_BOUNDS);
3202 }
Steven Timotiusaf03df62017-07-18 16:56:43 -07003203 proto.end(token);
3204 }
3205
3206 void writeNameToProto(ProtoOutputStream proto, long fieldId) {
3207 if (appToken == null) {
3208 return;
3209 }
3210 try {
3211 proto.write(fieldId, appToken.getName());
3212 } catch (RemoteException e) {
3213 // This shouldn't happen, but in this case fall back to outputting nothing
3214 Slog.e(TAG, e.toString());
3215 }
3216 }
3217
3218 @Override
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003219 public String toString() {
3220 if (stringName == null) {
3221 StringBuilder sb = new StringBuilder();
3222 sb.append("AppWindowToken{");
3223 sb.append(Integer.toHexString(System.identityHashCode(this)));
3224 sb.append(" token="); sb.append(token); sb.append('}');
3225 stringName = sb.toString();
3226 }
Wale Ogunwaleba51ca22016-09-23 06:06:54 -07003227 return stringName + ((mIsExiting) ? " mIsExiting=" : "");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003228 }
Adrian Roos20e07892018-02-23 19:12:01 +01003229
3230 Rect getLetterboxInsets() {
3231 if (mLetterbox != null) {
3232 return mLetterbox.getInsets();
3233 } else {
3234 return new Rect();
3235 }
3236 }
Adrian Roos23df3a32018-03-15 15:41:13 +01003237
Riddle Hsu69de5fb2019-02-23 01:19:50 +08003238 /** Gets the inner bounds of letterbox. The bounds will be empty if there is no letterbox. */
3239 void getLetterboxInnerBounds(Rect outBounds) {
3240 if (mLetterbox != null) {
3241 outBounds.set(mLetterbox.getInnerFrame());
3242 } else {
3243 outBounds.setEmpty();
3244 }
3245 }
3246
Adrian Roos23df3a32018-03-15 15:41:13 +01003247 /**
Riddle Hsu69de5fb2019-02-23 01:19:50 +08003248 * @return {@code true} if there is a letterbox and any part of that letterbox overlaps with
Adrian Roos23df3a32018-03-15 15:41:13 +01003249 * the given {@code rect}.
3250 */
3251 boolean isLetterboxOverlappingWith(Rect rect) {
3252 return mLetterbox != null && mLetterbox.isOverlappingWith(rect);
3253 }
chaviw4ad54912018-05-30 11:05:44 -07003254
3255 /**
3256 * Sets if this AWT is in the process of closing or entering PIP.
3257 * {@link #mWillCloseOrEnterPip}}
3258 */
3259 void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
3260 mWillCloseOrEnterPip = willCloseOrEnterPip;
3261 }
3262
3263 /**
3264 * Returns whether this AWT is considered closing. Conditions are either
3265 * 1. Is this app animating and was requested to be hidden
3266 * 2. App is delayed closing since it might enter PIP.
3267 */
3268 boolean isClosingOrEnteringPip() {
3269 return (isAnimating() && hiddenRequested) || mWillCloseOrEnterPip;
3270 }
Jorim Jaggiaf0d6d22018-06-08 15:25:35 +02003271
3272 /**
3273 * @return Whether we are allowed to show non-starting windows at the moment. We disallow
3274 * showing windows during transitions in case we have windows that have wide-color-gamut
3275 * color mode set to avoid jank in the middle of the transition.
3276 */
3277 boolean canShowWindows() {
3278 return allDrawn && !(isReallyAnimating() && hasNonDefaultColorWindow());
3279 }
3280
3281 /**
3282 * @return true if we have a window that has a non-default color mode set; false otherwise.
3283 */
3284 private boolean hasNonDefaultColorWindow() {
3285 return forAllWindows(ws -> ws.mAttrs.getColorMode() != COLOR_MODE_DEFAULT,
3286 true /* topToBottom */);
3287 }
lumark588a3e82018-07-20 18:53:54 +08003288
chaviwdcf76ec2019-01-11 16:48:46 -08003289 private void updateColorTransform() {
3290 if (mSurfaceControl != null && mLastAppSaturationInfo != null) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003291 getPendingTransaction().setColorTransform(mSurfaceControl,
3292 mLastAppSaturationInfo.mMatrix, mLastAppSaturationInfo.mTranslation);
chaviwdcf76ec2019-01-11 16:48:46 -08003293 mWmService.scheduleAnimationLocked();
3294 }
3295 }
3296
3297 private static class AppSaturationInfo {
3298 float[] mMatrix = new float[9];
3299 float[] mTranslation = new float[3];
3300
3301 void setSaturation(@Size(9) float[] matrix, @Size(3) float[] translation) {
3302 System.arraycopy(matrix, 0, mMatrix, 0, mMatrix.length);
3303 System.arraycopy(translation, 0, mTranslation, 0, mTranslation.length);
3304 }
3305 }
Jeff Browne9bdb312012-04-05 15:30:10 -07003306}