blob: 48da52b8f8d2ecac21cb73c164891143de077ff6 [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;
chaviw9c81e632018-07-31 11:17:52 -070036import static android.view.WindowManager.TRANSIT_UNSET;
Jorim Jaggic6976f02018-04-18 16:31:07 +020037import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
chaviw9c81e632018-07-31 11:17:52 -070038
Adrian Roose99bc052017-11-20 17:55:31 +010039import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
40import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070041import static com.android.server.wm.AppWindowTokenProto.ALL_DRAWN;
42import static com.android.server.wm.AppWindowTokenProto.APP_STOPPED;
43import static com.android.server.wm.AppWindowTokenProto.CLIENT_HIDDEN;
44import static com.android.server.wm.AppWindowTokenProto.DEFER_HIDING_CLIENT;
45import static com.android.server.wm.AppWindowTokenProto.FILLS_PARENT;
46import static com.android.server.wm.AppWindowTokenProto.FROZEN_BOUNDS;
47import static com.android.server.wm.AppWindowTokenProto.HIDDEN_REQUESTED;
48import static com.android.server.wm.AppWindowTokenProto.HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW;
49import static com.android.server.wm.AppWindowTokenProto.IS_REALLY_ANIMATING;
50import static com.android.server.wm.AppWindowTokenProto.IS_WAITING_FOR_TRANSITION_START;
51import static com.android.server.wm.AppWindowTokenProto.LAST_ALL_DRAWN;
52import static com.android.server.wm.AppWindowTokenProto.LAST_SURFACE_SHOWING;
53import static com.android.server.wm.AppWindowTokenProto.NAME;
54import static com.android.server.wm.AppWindowTokenProto.NUM_DRAWN_WINDOWS;
55import static com.android.server.wm.AppWindowTokenProto.NUM_INTERESTING_WINDOWS;
56import static com.android.server.wm.AppWindowTokenProto.REMOVED;
57import static com.android.server.wm.AppWindowTokenProto.REPORTED_DRAWN;
58import static com.android.server.wm.AppWindowTokenProto.REPORTED_VISIBLE;
59import static com.android.server.wm.AppWindowTokenProto.STARTING_DISPLAYED;
60import static com.android.server.wm.AppWindowTokenProto.STARTING_MOVED;
61import static com.android.server.wm.AppWindowTokenProto.STARTING_WINDOW;
62import static com.android.server.wm.AppWindowTokenProto.THUMBNAIL;
63import static com.android.server.wm.AppWindowTokenProto.WINDOW_TOKEN;
chaviw9c81e632018-07-31 11:17:52 -070064import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
65import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
66import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
67import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
68import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
69import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
70import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
71import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
72import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
73import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
74import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
75import 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;
Vishnu Naira2977262018-07-26 13:31:26 -070082import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
Evan Rosky641daea2019-04-24 14:45:24 -070083import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080084
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070085import android.annotation.CallSuper;
chaviwdcf76ec2019-01-11 16:48:46 -080086import android.annotation.Size;
Jorim Jaggid635a4a2017-05-03 15:21:26 +020087import android.app.Activity;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080088import android.app.ActivityManager;
Winson Chung48b25652018-10-22 14:04:30 -070089import android.content.ComponentName;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080090import android.content.res.CompatibilityInfo;
Jorim Jaggi26c8c422016-05-09 19:57:25 -070091import android.content.res.Configuration;
Jorim Jaggi988f6682017-11-17 17:46:43 +010092import android.graphics.GraphicBuffer;
Jorim Jaggif5f9e122017-10-24 18:21:09 +020093import android.graphics.Point;
Jorim Jaggi0429f352015-12-22 16:29:16 +010094import android.graphics.Rect;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -070095import android.os.Binder;
Tiger Huang51c5a1d2018-12-11 20:24:51 +080096import android.os.Build;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -080097import android.os.Debug;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -070098import android.os.IBinder;
Steven Timotiusaf03df62017-07-18 16:56:43 -070099import android.os.RemoteException;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800100import android.os.SystemClock;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200101import android.os.Trace;
Evan Rosky2289ba12018-11-19 18:28:18 -0800102import android.util.ArraySet;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800103import android.util.Slog;
Steven Timotiusaf03df62017-07-18 16:56:43 -0700104import android.util.proto.ProtoOutputStream;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200105import android.view.DisplayInfo;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800106import android.view.IApplicationToken;
Robert Carr788f5742018-07-30 17:46:45 -0700107import android.view.InputApplicationHandle;
Evan Rosky966759f2019-01-15 10:33:58 -0800108import android.view.RemoteAnimationAdapter;
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100109import android.view.RemoteAnimationDefinition;
Robert Carr6914f082017-03-20 19:04:30 -0700110import android.view.SurfaceControl;
Tony Mak64b8d562017-12-28 17:44:02 +0000111import android.view.SurfaceControl.Transaction;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800112import android.view.WindowManager;
Jorim Jaggi87fdbcb2017-08-17 13:41:11 +0200113import android.view.WindowManager.LayoutParams;
Tony Mak64b8d562017-12-28 17:44:02 +0000114import android.view.animation.Animation;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800115
Tony Mak64b8d562017-12-28 17:44:02 +0000116import com.android.internal.R;
Riddle Hsua118b3a2018-10-11 22:05:06 +0800117import com.android.internal.annotations.VisibleForTesting;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800118import com.android.internal.util.ToBooleanFunction;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800119import com.android.server.AttributeCache;
chaviwdcf76ec2019-01-11 16:48:46 -0800120import com.android.server.LocalServices;
Christine Franks0ada2772019-02-25 13:54:57 -0800121import com.android.server.display.color.ColorDisplayService;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800122import com.android.server.policy.WindowManagerPolicy;
Adrian Roose99bc052017-11-20 17:55:31 +0100123import com.android.server.policy.WindowManagerPolicy.StartingSurface;
Evan Rosky2289ba12018-11-19 18:28:18 -0800124import com.android.server.wm.RemoteAnimationController.RemoteAnimationRecord;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800125import com.android.server.wm.WindowManagerService.H;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800126
127import java.io.PrintWriter;
chaviwdcf76ec2019-01-11 16:48:46 -0800128import java.lang.ref.WeakReference;
Jorim Jaggi0429f352015-12-22 16:29:16 +0100129import java.util.ArrayDeque;
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800130import java.util.ArrayList;
lumark588a3e82018-07-20 18:53:54 +0800131import java.util.function.Consumer;
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800132
133class AppTokenList extends ArrayList<AppWindowToken> {
134}
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800135
136/**
137 * Version of WindowToken that is specifically for a particular application (or
138 * really activity) that is displaying windows.
139 */
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800140class AppWindowToken extends WindowToken implements WindowManagerService.AppFreezeListener,
141 ConfigurationContainerListener {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800142 private static final String TAG = TAG_WITH_CLASS_NAME ? "AppWindowToken" : TAG_WM;
143
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100144 /**
145 * Value to increment the z-layer when boosting a layer during animations. BOOST in l33tsp34k.
146 */
Jorim Jaggi9cd99132019-04-24 17:41:35 +0200147 @VisibleForTesting static final int Z_BOOST_BASE = 800570000;
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100148
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800149 // Non-null only for application tokens.
150 final IApplicationToken appToken;
Winson Chung48b25652018-10-22 14:04:30 -0700151 final ComponentName mActivityComponent;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800152 final boolean mVoiceInteraction;
Dianne Hackborne30e02f2014-05-27 18:24:45 -0700153
Wale Ogunwale51362492016-09-08 17:49:17 -0700154 /** @see WindowContainer#fillsParent() */
155 private boolean mFillsParent;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800156 boolean mShowForAllUsers;
157 int mTargetSdk;
Craig Mautnera2c77052012-03-26 12:14:43 -0700158
Bryce Lee6d410262017-02-28 15:30:17 -0800159 // Flag set while reparenting to prevent actions normally triggered by an individual parent
160 // change.
161 private boolean mReparenting;
162
Wale Ogunwalee287e192017-04-21 09:30:12 -0700163 // True if we are current in the process of removing this app token from the display
164 private boolean mRemovingFromDisplay = false;
165
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800166 // The input dispatching timeout for this application token in nanoseconds.
Wale Ogunwale72919d22016-12-08 18:58:50 -0800167 long mInputDispatchingTimeoutNanos;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800168
169 // These are used for determining when all windows associated with
170 // an activity have been drawn, so they can be made visible together
171 // at the same time.
Craig Mautner764983d2012-03-22 11:37:36 -0700172 // initialize so that it doesn't match mTransactionSequence which is an int.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700173 private long mLastTransactionSequence = Long.MIN_VALUE;
174 private int mNumInterestingWindows;
175 private int mNumDrawnWindows;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800176 boolean inPendingTransaction;
177 boolean allDrawn;
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000178 private boolean mLastAllDrawn;
Tiger Huangc9d0d002019-05-29 22:55:29 +0800179 private boolean mUseTransferredAnimation;
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000180
Craig Mautner7636dfb2012-11-16 15:24:11 -0800181 // Set to true when this app creates a surface while in the middle of an animation. In that
182 // case do not clear allDrawn until the animation completes.
183 boolean deferClearAllDrawn;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800184
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800185 // Is this window's surface needed? This is almost like hidden, except
186 // it will sometimes be true a little earlier: when the token has
187 // been shown, but is still waiting for its app transition to execute
188 // before making its windows shown.
189 boolean hiddenRequested;
190
191 // Have we told the window clients to hide themselves?
Wale Ogunwale89973222017-04-23 18:39:45 -0700192 private boolean mClientHidden;
193
194 // If true we will defer setting mClientHidden to true and reporting to the client that it is
195 // hidden.
196 boolean mDeferHidingClient;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800197
198 // Last visibility state we reported to the app token.
199 boolean reportedVisible;
200
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700201 // Last drawn state we reported to the app token.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700202 private boolean reportedDrawn;
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700203
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800204 // Set to true when the token has been removed from the window mgr.
205 boolean removed;
206
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800207 // Information about an application starting window if displayed.
chaviwa8f07a72019-05-01 16:25:39 -0700208 StartingData mStartingData;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800209 WindowState startingWindow;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800210 StartingSurface startingSurface;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800211 boolean startingDisplayed;
212 boolean startingMoved;
Jorim Jaggi60f9c972018-02-01 19:21:07 +0100213
Wale Ogunwale6c459212017-05-17 08:56:03 -0700214 // True if the hidden state of this token was forced to false due to a transferred starting
215 // window.
216 private boolean mHiddenSetFromTransferredStartingWindow;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800217 boolean firstWindowDrawn;
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700218 private final WindowState.UpdateReportedVisibilityResults mReportedVisibilityResults =
219 new WindowState.UpdateReportedVisibilityResults();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800220
221 // Input application handle used by the input dispatcher.
Jeff Brown9302c872011-07-13 22:51:29 -0700222 final InputApplicationHandle mInputApplicationHandle;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800223
Wale Ogunwale571771c2016-08-26 13:18:50 -0700224 // TODO: Have a WindowContainer state for tracking exiting/deferred removal.
Craig Mautner799bc1d2015-01-14 10:33:48 -0800225 boolean mIsExiting;
Craig Mautner9ef471f2014-02-07 13:11:47 -0800226
Craig Mautnerbb742462014-07-07 15:28:55 -0700227 boolean mLaunchTaskBehind;
Craig Mautner8746a472014-07-24 15:12:54 -0700228 boolean mEnteringAnimation;
Craig Mautnerbb742462014-07-07 15:28:55 -0700229
Wale Ogunwale72919d22016-12-08 18:58:50 -0800230 private boolean mAlwaysFocusable;
Wale Ogunwale6cae7652015-12-26 07:36:26 -0800231
Robert Carre12aece2016-02-02 22:43:27 -0800232 boolean mAppStopped;
Robert Carrfd10cd12016-06-29 16:41:50 -0700233 int mRotationAnimationHint;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700234 private int mPendingRelaunchCount;
Robert Carre12aece2016-02-02 22:43:27 -0800235
Jorim Jaggife762342016-10-13 14:33:27 +0200236 private boolean mLastContainsShowWhenLockedWindow;
237 private boolean mLastContainsDismissKeyguardWindow;
238
Jorim Jaggi0429f352015-12-22 16:29:16 +0100239 ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
Jorim Jaggi26c8c422016-05-09 19:57:25 -0700240 ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
Jorim Jaggi0429f352015-12-22 16:29:16 +0100241
Riddle Hsub398da32019-01-21 21:48:16 +0800242 /**
243 * The scale to fit at least one side of the activity to its parent. If the activity uses
244 * 1920x1080, and the actually size on the screen is 960x540, then the scale is 0.5.
245 */
246 private float mSizeCompatScale = 1f;
247 /**
248 * The bounds in global coordinates for activity in size compatibility mode.
249 * @see ActivityRecord#inSizeCompatMode
250 */
251 private Rect mSizeCompatBounds;
252
Wale Ogunwale6c459212017-05-17 08:56:03 -0700253 private boolean mDisablePreviewScreenshots;
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +0100254
Wale Ogunwale034a8ec2017-09-02 17:14:40 -0700255 private Task mLastParent;
Robert Carred3e83b2017-04-21 13:26:55 -0700256
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800257 // TODO: Remove after unification
258 ActivityRecord mActivityRecord;
259
chaviwd3bf08d2017-08-01 17:24:59 -0700260 /**
Riddle Hsu4bb06be2019-07-02 01:03:07 +0800261 * @see #currentLaunchCanTurnScreenOn()
chaviwd3bf08d2017-08-01 17:24:59 -0700262 */
Riddle Hsu4bb06be2019-07-02 01:03:07 +0800263 private boolean mCurrentLaunchCanTurnScreenOn = true;
chaviwd3bf08d2017-08-01 17:24:59 -0700264
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200265 /**
266 * If we are running an animation, this determines the transition type. Must be one of
267 * AppTransition.TRANSIT_* constants.
268 */
269 private int mTransit;
270
271 /**
272 * If we are running an animation, this determines the flags during this animation. Must be a
273 * bitwise combination of AppTransition.TRANSIT_FLAG_* constants.
274 */
275 private int mTransitFlags;
276
277 /** Whether our surface was set to be showing in the last call to {@link #prepareSurfaces} */
Jorim Jaggifd1891462017-12-29 15:41:36 +0100278 private boolean mLastSurfaceShowing = true;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200279
Evan Rosky2289ba12018-11-19 18:28:18 -0800280 /**
281 * This gets used during some open/close transitions as well as during a change transition
282 * where it represents the starting-state snapshot.
283 */
Jorim Jaggi988f6682017-11-17 17:46:43 +0100284 private AppWindowThumbnail mThumbnail;
Evan Rosky2289ba12018-11-19 18:28:18 -0800285 private final Rect mTransitStartRect = new Rect();
286
287 /**
288 * This leash is used to "freeze" the app surface in place after the state change, but before
289 * the animation is ready to start.
290 */
291 private SurfaceControl mTransitChangeLeash = null;
Jorim Jaggi988f6682017-11-17 17:46:43 +0100292
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000293 /** Have we been asked to have this token keep the screen frozen? */
294 private boolean mFreezingScreen;
295
296 /** Whether this token should be boosted at the top of all app window tokens. */
Jorim Jaggi9cd99132019-04-24 17:41:35 +0200297 @VisibleForTesting boolean mNeedsZBoost;
Adrian Roos4d18a2e2017-12-19 19:08:05 +0100298 private Letterbox mLetterbox;
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000299
chaviw23ee71c2017-12-18 11:29:41 -0800300 private final Point mTmpPoint = new Point();
chaviw23012112017-12-20 15:29:04 -0800301 private final Rect mTmpRect = new Rect();
Evan Rosky2289ba12018-11-19 18:28:18 -0800302 private final Rect mTmpPrevBounds = new Rect();
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100303 private RemoteAnimationDefinition mRemoteAnimationDefinition;
Jorim Jaggi6de61012018-03-19 14:53:23 +0100304 private AnimatingAppWindowTokenRegistry mAnimatingAppWindowTokenRegistry;
chaviw23ee71c2017-12-18 11:29:41 -0800305
chaviw4ad54912018-05-30 11:05:44 -0700306 /**
307 * A flag to determine if this AWT is in the process of closing or entering PIP. This is needed
308 * to help AWT know that the app is in the process of closing but hasn't yet started closing on
309 * the WM side.
310 */
311 private boolean mWillCloseOrEnterPip;
312
Vishnu Naira2977262018-07-26 13:31:26 -0700313 /** Layer used to constrain the animation to a token's stack bounds. */
314 SurfaceControl mAnimationBoundsLayer;
315
316 /** Whether this token needs to create mAnimationBoundsLayer for cropping animations. */
317 boolean mNeedsAnimationBoundsLayer;
318
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800319 private static final int STARTING_WINDOW_TYPE_NONE = 0;
320 private static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
321 private static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
322
chaviwdcf76ec2019-01-11 16:48:46 -0800323 private AppSaturationInfo mLastAppSaturationInfo;
324
325 private final ColorDisplayService.ColorTransformController mColorTransformController =
326 (matrix, translation) -> mWmService.mH.post(() -> {
327 synchronized (mWmService.mGlobalLock) {
328 if (mLastAppSaturationInfo == null) {
329 mLastAppSaturationInfo = new AppSaturationInfo();
330 }
331
332 mLastAppSaturationInfo.setSaturation(matrix, translation);
333 updateColorTransform();
334 }
335 });
336
Winson Chung48b25652018-10-22 14:04:30 -0700337 AppWindowToken(WindowManagerService service, IApplicationToken token,
338 ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
339 long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers,
Jorim Jaggi91d382a2019-03-27 17:00:48 +0100340 int targetSdk, int orientation, int rotationAnimationHint,
Winson Chung48b25652018-10-22 14:04:30 -0700341 boolean launchTaskBehind, boolean alwaysFocusable,
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800342 ActivityRecord activityRecord) {
Winson Chung48b25652018-10-22 14:04:30 -0700343 this(service, token, activityComponent, voiceInteraction, dc, fullscreen);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800344 // TODO: remove after unification
345 mActivityRecord = activityRecord;
346 mActivityRecord.registerConfigurationChangeListener(this);
Wale Ogunwale72919d22016-12-08 18:58:50 -0800347 mInputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800348 mShowForAllUsers = showForAllUsers;
349 mTargetSdk = targetSdk;
350 mOrientation = orientation;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800351 mLaunchTaskBehind = launchTaskBehind;
352 mAlwaysFocusable = alwaysFocusable;
353 mRotationAnimationHint = rotationAnimationHint;
354
355 // Application tokens start out hidden.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200356 setHidden(true);
Wale Ogunwale72919d22016-12-08 18:58:50 -0800357 hiddenRequested = true;
chaviwdcf76ec2019-01-11 16:48:46 -0800358
359 ColorDisplayService.ColorDisplayServiceInternal cds = LocalServices.getService(
360 ColorDisplayService.ColorDisplayServiceInternal.class);
361 cds.attachColorTransformController(activityRecord.packageName, activityRecord.mUserId,
362 new WeakReference<>(mColorTransformController));
Wale Ogunwale72919d22016-12-08 18:58:50 -0800363 }
364
Winson Chung48b25652018-10-22 14:04:30 -0700365 AppWindowToken(WindowManagerService service, IApplicationToken token,
366 ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
367 boolean fillsParent) {
Wale Ogunwale5cd907d2017-01-26 14:14:08 -0800368 super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true, dc,
369 false /* ownerCanManageAppTokens */);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700370 appToken = token;
Winson Chung48b25652018-10-22 14:04:30 -0700371 mActivityComponent = activityComponent;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800372 mVoiceInteraction = voiceInteraction;
Wale Ogunwale17f175c2017-02-07 16:54:10 -0800373 mFillsParent = fillsParent;
Robert Carr0bcbe642018-10-11 19:07:43 -0700374 mInputApplicationHandle = new InputApplicationHandle(appToken.asBinder());
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800375 }
376
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800377 void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
378 firstWindowDrawn = true;
379
380 // We now have a good window to show, remove dead placeholders
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700381 removeDeadWindows();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800382
Jorim Jaggi02886a82016-12-06 09:10:06 -0800383 if (startingWindow != null) {
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800384 if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Slog.v(TAG, "Finish starting "
385 + win.mToken + ": first real window is shown, no animation");
386 // If this initial window is animating, stop it -- we will do an animation to reveal
387 // it from behind the starting window, so there is no need for it to also be doing its
388 // own stuff.
Jorim Jaggia5e10572017-11-15 14:36:26 +0100389 win.cancelAnimation();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800390 }
chaviwa8f07a72019-05-01 16:25:39 -0700391 removeStartingWindow();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800392 updateReportedVisibilityLocked();
393 }
394
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800395 void updateReportedVisibilityLocked() {
396 if (appToken == null) {
397 return;
398 }
399
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700400 if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700401 final int count = mChildren.size();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800402
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700403 mReportedVisibilityResults.reset();
404
405 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700406 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700407 win.updateReportedVisibility(mReportedVisibilityResults);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800408 }
409
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700410 int numInteresting = mReportedVisibilityResults.numInteresting;
411 int numVisible = mReportedVisibilityResults.numVisible;
412 int numDrawn = mReportedVisibilityResults.numDrawn;
413 boolean nowGone = mReportedVisibilityResults.nowGone;
414
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700415 boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200416 boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting && !isHidden();
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700417 if (!nowGone) {
418 // If the app is not yet gone, then it can only become visible/drawn.
419 if (!nowDrawn) {
420 nowDrawn = reportedDrawn;
421 }
422 if (!nowVisible) {
423 nowVisible = reportedVisible;
424 }
425 }
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800426 if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800427 + numInteresting + " visible=" + numVisible);
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700428 if (nowDrawn != reportedDrawn) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800429 if (mActivityRecord != null) {
430 mActivityRecord.onWindowsDrawn(nowDrawn, SystemClock.uptimeMillis());
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700431 }
432 reportedDrawn = nowDrawn;
433 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800434 if (nowVisible != reportedVisible) {
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700435 if (DEBUG_VISIBILITY) Slog.v(TAG,
436 "Visibility changed in " + this + ": vis=" + nowVisible);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800437 reportedVisible = nowVisible;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800438 if (mActivityRecord != null) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800439 if (nowVisible) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800440 onWindowsVisible();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800441 } else {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800442 onWindowsGone();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800443 }
444 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800445 }
446 }
447
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800448 private void onWindowsGone() {
449 if (mActivityRecord == null) {
450 return;
451 }
452 if (DEBUG_VISIBILITY) {
453 Slog.v(TAG_WM, "Reporting gone in " + mActivityRecord.appToken);
454 }
455 mActivityRecord.onWindowsGone();
456 }
457
458 private void onWindowsVisible() {
459 if (mActivityRecord == null) {
460 return;
461 }
462 if (DEBUG_VISIBILITY) {
463 Slog.v(TAG_WM, "Reporting visible in " + mActivityRecord.appToken);
464 }
465 mActivityRecord.onWindowsVisible();
466 }
467
Wale Ogunwale89973222017-04-23 18:39:45 -0700468 boolean isClientHidden() {
469 return mClientHidden;
470 }
471
472 void setClientHidden(boolean hideClient) {
473 if (mClientHidden == hideClient || (hideClient && mDeferHidingClient)) {
474 return;
475 }
Jorim Jaggi067b5bf2018-02-23 17:42:39 +0100476 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "setClientHidden: " + this
477 + " clientHidden=" + hideClient + " Callers=" + Debug.getCallers(5));
Wale Ogunwale89973222017-04-23 18:39:45 -0700478 mClientHidden = hideClient;
479 sendAppVisibilityToClients();
480 }
481
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800482 void setVisibility(boolean visible, boolean deferHidingClient) {
483 final AppTransition appTransition = getDisplayContent().mAppTransition;
484
485 // Don't set visibility to false if we were already not visible. This prevents WM from
486 // adding the app to the closing app list which doesn't make sense for something that is
487 // already not visible. However, set visibility to true even if we are already visible.
488 // This makes sure the app is added to the opening apps list so that the right
489 // transition can be selected.
490 // TODO: Probably a good idea to separate the concept of opening/closing apps from the
491 // concept of setting visibility...
492 if (!visible && hiddenRequested) {
493
494 if (!deferHidingClient && mDeferHidingClient) {
495 // We previously deferred telling the client to hide itself when visibility was
496 // initially set to false. Now we would like it to hide, so go ahead and set it.
497 mDeferHidingClient = deferHidingClient;
498 setClientHidden(true);
499 }
500 return;
501 }
502
503 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) {
504 Slog.v(TAG_WM, "setAppVisibility("
505 + appToken + ", visible=" + visible + "): " + appTransition
506 + " hidden=" + isHidden() + " hiddenRequested="
507 + hiddenRequested + " Callers=" + Debug.getCallers(6));
508 }
509
510 final DisplayContent displayContent = getDisplayContent();
511 displayContent.mOpeningApps.remove(this);
512 displayContent.mClosingApps.remove(this);
Evan Roskyb1e75f72019-04-26 20:23:26 -0700513 if (isInChangeTransition()) {
514 clearChangeLeash(getPendingTransaction(), true /* cancel */);
515 }
516 displayContent.mChangingApps.remove(this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800517 waitingToShow = false;
518 hiddenRequested = !visible;
519 mDeferHidingClient = deferHidingClient;
520
521 if (!visible) {
522 // If the app is dead while it was visible, we kept its dead window on screen.
523 // Now that the app is going invisible, we can remove it. It will be restarted
524 // if made visible again.
525 removeDeadWindows();
526 } else {
527 if (!appTransition.isTransitionSet()
528 && appTransition.isReady()) {
529 // Add the app mOpeningApps if transition is unset but ready. This means
530 // we're doing a screen freeze, and the unfreeze will wait for all opening
531 // apps to be ready.
532 displayContent.mOpeningApps.add(this);
533 }
534 startingMoved = false;
535 // If the token is currently hidden (should be the common case), or has been
536 // stopped, then we need to set up to wait for its windows to be ready.
537 if (isHidden() || mAppStopped) {
538 clearAllDrawn();
539
540 // If the app was already visible, don't reset the waitingToShow state.
541 if (isHidden()) {
542 waitingToShow = true;
543 }
544 }
545
546 // In the case where we are making an app visible but holding off for a transition,
547 // we still need to tell the client to make its windows visible so they get drawn.
548 // Otherwise, we will wait on performing the transition until all windows have been
549 // drawn, they never will be, and we are sad.
550 setClientHidden(false);
551
552 requestUpdateWallpaperIfNeeded();
553
554 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "No longer Stopped: " + this);
555 mAppStopped = false;
556
557 transferStartingWindowFromHiddenAboveTokenIfNeeded();
558 }
559
560 // If we are preparing an app transition, then delay changing
561 // the visibility of this token until we execute that transition.
562 if (okToAnimate() && appTransition.isTransitionSet()) {
563 inPendingTransaction = true;
564 if (visible) {
565 displayContent.mOpeningApps.add(this);
566 mEnteringAnimation = true;
567 } else {
568 displayContent.mClosingApps.add(this);
569 mEnteringAnimation = false;
570 }
571 if (appTransition.getAppTransition()
572 == WindowManager.TRANSIT_TASK_OPEN_BEHIND) {
573 // We're launchingBehind, add the launching activity to mOpeningApps.
574 final WindowState win = getDisplayContent().findFocusedWindow();
575 if (win != null) {
576 final AppWindowToken focusedToken = win.mAppToken;
577 if (focusedToken != null) {
578 if (DEBUG_APP_TRANSITIONS) {
579 Slog.d(TAG_WM, "TRANSIT_TASK_OPEN_BEHIND, "
580 + " adding " + focusedToken + " to mOpeningApps");
581 }
582 // Force animation to be loaded.
583 focusedToken.setHidden(true);
584 displayContent.mOpeningApps.add(focusedToken);
585 }
586 }
587 }
Garfield Tanb6776602019-02-20 14:44:26 -0800588 // Changes in opening apps and closing apps may cause orientation change.
589 reportDescendantOrientationChangeIfNeeded();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800590 return;
591 }
592
593 commitVisibility(null, visible, TRANSIT_UNSET, true, mVoiceInteraction);
594 updateReportedVisibilityLocked();
595 }
596
597 boolean commitVisibility(WindowManager.LayoutParams lp,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700598 boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
599
600 boolean delayed = false;
601 inPendingTransaction = false;
Wale Ogunwale9e4721f2017-05-23 19:37:30 -0700602 // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually
603 // been set by the app now.
604 mHiddenSetFromTransferredStartingWindow = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700605
606 // Allow for state changes and animation to be applied if:
607 // * token is transitioning visibility state
608 // * or the token was marked as hidden and is exiting before we had a chance to play the
609 // transition animation
610 // * or this is an opening app and windows are being replaced.
611 boolean visibilityChanged = false;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200612 if (isHidden() == visible || (isHidden() && mIsExiting) || (visible && waitingForReplacement())) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800613 final AccessibilityController accessibilityController =
614 mWmService.mAccessibilityController;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700615 boolean changed = false;
616 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM,
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200617 "Changing app " + this + " hidden=" + isHidden() + " performLayout=" + performLayout);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700618
619 boolean runningAppAnimation = false;
620
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100621 if (transit != WindowManager.TRANSIT_UNSET) {
Tiger Huangc9d0d002019-05-29 22:55:29 +0800622 if (mUseTransferredAnimation) {
623 runningAppAnimation = isReallyAnimating();
624 } else if (applyAnimationLocked(lp, transit, visible, isVoiceInteraction)) {
625 runningAppAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700626 }
Tiger Huangc9d0d002019-05-29 22:55:29 +0800627 delayed = runningAppAnimation;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700628 final WindowState window = findMainWindow();
Rhed Jao02655dc2018-10-30 20:44:52 +0800629 if (window != null && accessibilityController != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700630 accessibilityController.onAppWindowTransitionLocked(window, transit);
631 }
632 changed = true;
633 }
634
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700635 final int windowsCount = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700636 for (int i = 0; i < windowsCount; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700637 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700638 changed |= win.onAppVisibilityChanged(visible, runningAppAnimation);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700639 }
640
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200641 setHidden(!visible);
642 hiddenRequested = !visible;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700643 visibilityChanged = true;
644 if (!visible) {
645 stopFreezingScreen(true, true);
646 } else {
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700647 // If we are being set visible, and the starting window is not yet displayed,
648 // then make sure it doesn't get displayed.
649 if (startingWindow != null && !startingWindow.isDrawnLw()) {
chaviw15ad49f2019-04-24 15:05:39 -0700650 startingWindow.clearPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY);
651 startingWindow.mLegacyPolicyVisibilityAfterAnim = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700652 }
Jorim Jaggi38d44ec2017-06-14 16:04:59 -0700653
654 // We are becoming visible, so better freeze the screen with the windows that are
655 // getting visible so we also wait for them.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800656 forAllWindows(mWmService::makeWindowFreezingScreenIfNeededLocked, true);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700657 }
658
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800659 if (DEBUG_APP_TRANSITIONS) {
660 Slog.v(TAG_WM, "commitVisibility: " + this
661 + ": hidden=" + isHidden() + " hiddenRequested=" + hiddenRequested);
662 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700663
664 if (changed) {
Arthur Hung95b38a92018-07-20 18:56:12 +0800665 getDisplayContent().getInputMonitor().setUpdateInputWindowsNeededLw();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700666 if (performLayout) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800667 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700668 false /*updateInputWindows*/);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800669 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700670 }
Arthur Hung95b38a92018-07-20 18:56:12 +0800671 getDisplayContent().getInputMonitor().updateInputWindowsLw(false /*force*/);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700672 }
673 }
Tiger Huangc9d0d002019-05-29 22:55:29 +0800674 mUseTransferredAnimation = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700675
lumarkd14173e2019-03-27 19:14:33 +0800676 if (isReallyAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700677 delayed = true;
Jorim Jaggiab9fcb22018-03-15 23:46:12 +0100678 } else {
679
680 // We aren't animating anything, but exiting windows rely on the animation finished
681 // callback being called in case the AppWindowToken was pretending to be animating,
682 // which we might have done because we were in closing/opening apps list.
683 onAnimationFinished();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700684 }
685
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700686 for (int i = mChildren.size() - 1; i >= 0 && !delayed; i--) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100687 if ((mChildren.get(i)).isSelfOrChildAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700688 delayed = true;
689 }
690 }
691
692 if (visibilityChanged) {
693 if (visible && !delayed) {
694 // The token was made immediately visible, there will be no entrance animation.
695 // We need to inform the client the enter animation was finished.
696 mEnteringAnimation = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800697 mWmService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(
698 token);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700699 }
Robert Carr61b81112017-07-17 18:08:15 -0700700
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800701 // If we're becoming visible, immediately change client visibility as well. there seem
702 // to be some edge cases where we change our visibility but client visibility never gets
703 // updated.
Jorim Jaggi110839b2018-01-22 12:49:04 +0100704 // If we're becoming invisible, update the client visibility if we are not running an
705 // animation. Otherwise, we'll update client visibility in onAnimationFinished.
Jorim Jaggi3cad57f2018-02-20 18:32:01 +0100706 if (visible || !isReallyAnimating()) {
Jorim Jaggi110839b2018-01-22 12:49:04 +0100707 setClientHidden(!visible);
Jorim Jaggi4876b4a2018-01-11 15:43:49 +0100708 }
709
lumark588a3e82018-07-20 18:53:54 +0800710 if (!getDisplayContent().mClosingApps.contains(this)
711 && !getDisplayContent().mOpeningApps.contains(this)) {
chaviwa953fcf2018-03-01 12:00:39 -0800712 // The token is not closing nor opening, so even if there is an animation set, that
713 // doesn't mean that it goes through the normal app transition cycle so we have
714 // to inform the docked controller about visibility change.
715 // TODO(multi-display): notify docked divider on all displays where visibility was
716 // affected.
lumark588a3e82018-07-20 18:53:54 +0800717 getDisplayContent().getDockedDividerController().notifyAppVisibilityChanged();
chaviwa953fcf2018-03-01 12:00:39 -0800718
719 // Take the screenshot before possibly hiding the WSA, otherwise the screenshot
720 // will not be taken.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800721 mWmService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible);
chaviwa953fcf2018-03-01 12:00:39 -0800722 }
723
Robert Carre7cc44d2017-03-20 19:04:30 -0700724 // If we are hidden but there is no delay needed we immediately
725 // apply the Surface transaction so that the ActivityManager
Robert Carr61b81112017-07-17 18:08:15 -0700726 // can have some guarantee on the Surface state following
727 // setting the visibility. This captures cases like dismissing
728 // the docked or pinned stack where there is no app transition.
729 //
730 // In the case of a "Null" animation, there will be
731 // no animation but there will still be a transition set.
732 // We still need to delay hiding the surface such that it
733 // can be synchronized with showing the next surface in the transition.
lumark588a3e82018-07-20 18:53:54 +0800734 if (isHidden() && !delayed && !getDisplayContent().mAppTransition.isTransitionSet()) {
Robert Carr6914f082017-03-20 19:04:30 -0700735 SurfaceControl.openTransaction();
736 for (int i = mChildren.size() - 1; i >= 0; i--) {
737 mChildren.get(i).mWinAnimator.hide("immediately hidden");
738 }
739 SurfaceControl.closeTransaction();
740 }
Garfield Tanb6776602019-02-20 14:44:26 -0800741
742 // Visibility changes may cause orientation request change.
743 reportDescendantOrientationChangeIfNeeded();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700744 }
745
746 return delayed;
747 }
748
Garfield Tanb6776602019-02-20 14:44:26 -0800749 private void reportDescendantOrientationChangeIfNeeded() {
750 // Orientation request is exposed only when we're visible. Therefore visibility change
751 // will change requested orientation. Notify upward the hierarchy ladder to adjust
752 // configuration. This is important to cases where activities with incompatible
753 // orientations launch, or user goes back from an activity of bi-orientation to an
754 // activity with specified orientation.
755 if (mActivityRecord.getRequestedConfigurationOrientation() == getConfiguration().orientation
756 || getOrientationIgnoreVisibility() == SCREEN_ORIENTATION_UNSET) {
757 return;
758 }
759
760 final IBinder freezeToken =
761 mActivityRecord.mayFreezeScreenLocked(mActivityRecord.app)
762 ? mActivityRecord.appToken : null;
763 onDescendantOrientationChanged(freezeToken, mActivityRecord);
764 }
765
Jorim Jaggi87fdbcb2017-08-17 13:41:11 +0200766 /**
767 * @return The to top most child window for which {@link LayoutParams#isFullscreen()} returns
768 * true.
769 */
770 WindowState getTopFullscreenWindow() {
771 for (int i = mChildren.size() - 1; i >= 0; i--) {
772 final WindowState win = mChildren.get(i);
773 if (win != null && win.mAttrs.isFullscreen()) {
774 return win;
775 }
776 }
777 return null;
778 }
779
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800780 WindowState findMainWindow() {
Matthew Ng53e66b22018-01-12 17:13:13 -0800781 return findMainWindow(true);
782 }
783
784 /**
785 * Finds the main window that either has type base application or application starting if
786 * requested.
787 *
788 * @param includeStartingApp Allow to search application-starting windows to also be returned.
789 * @return The main window of type base application or application starting if requested.
790 */
791 WindowState findMainWindow(boolean includeStartingApp) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700792 WindowState candidate = null;
Matthew Ng53e66b22018-01-12 17:13:13 -0800793 for (int j = mChildren.size() - 1; j >= 0; --j) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700794 final WindowState win = mChildren.get(j);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700795 final int type = win.mAttrs.type;
796 // No need to loop through child window as base application and starting types can't be
797 // child windows.
Matthew Ng53e66b22018-01-12 17:13:13 -0800798 if (type == TYPE_BASE_APPLICATION
799 || (includeStartingApp && type == TYPE_APPLICATION_STARTING)) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700800 // In cases where there are multiple windows, we prefer the non-exiting window. This
Sungsoo Lim0d3d1f82015-12-02 14:47:59 +0900801 // happens for example when replacing windows during an activity relaunch. When
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700802 // constructing the animation, we want the new window, not the exiting one.
Wale Ogunwalec48a3542016-02-19 15:18:45 -0800803 if (win.mAnimatingExit) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700804 candidate = win;
805 } else {
806 return win;
807 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800808 }
809 }
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700810 return candidate;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800811 }
812
Wale Ogunwale6cae7652015-12-26 07:36:26 -0800813 boolean windowsAreFocusable() {
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800814 if (mTargetSdk < Build.VERSION_CODES.Q) {
815 final int pid = mActivityRecord != null
816 ? (mActivityRecord.app != null ? mActivityRecord.app.getPid() : 0) : 0;
817 final AppWindowToken topFocusedAppOfMyProcess =
818 mWmService.mRoot.mTopFocusedAppByProcess.get(pid);
819 if (topFocusedAppOfMyProcess != null && topFocusedAppOfMyProcess != this) {
820 // For the apps below Q, there can be only one app which has the focused window per
821 // process, because legacy apps may not be ready for a multi-focus system.
822 return false;
823 }
824 }
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700825 return getWindowConfiguration().canReceiveKeys() || mAlwaysFocusable;
Wale Ogunwaled045c822015-12-02 09:14:28 -0800826 }
827
Wale Ogunwale571771c2016-08-26 13:18:50 -0700828 @Override
Wale Ogunwale44f21802016-09-02 12:49:48 -0700829 boolean isVisible() {
Wale Ogunwalee471be62016-10-03 07:53:55 -0700830 // If the app token isn't hidden then it is considered visible and there is no need to check
831 // its children windows to see if they are visible.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200832 return !isHidden();
Wale Ogunwale44f21802016-09-02 12:49:48 -0700833 }
834
835 @Override
Wale Ogunwalee287e192017-04-21 09:30:12 -0700836 void removeImmediately() {
837 onRemovedFromDisplay();
Yunfan Chen3a77f282018-12-12 15:47:52 -0800838 if (mActivityRecord != null) {
839 mActivityRecord.unregisterConfigurationChangeListener(this);
840 }
Wale Ogunwalee287e192017-04-21 09:30:12 -0700841 super.removeImmediately();
842 }
843
844 @Override
Wale Ogunwale571771c2016-08-26 13:18:50 -0700845 void removeIfPossible() {
Craig Mautnere3119b72015-01-20 15:02:36 -0800846 mIsExiting = false;
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800847 removeAllWindowsIfPossible();
Bryce Lee6d410262017-02-28 15:30:17 -0800848 removeImmediately();
Craig Mautnere3119b72015-01-20 15:02:36 -0800849 }
850
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700851 @Override
852 boolean checkCompleteDeferredRemoval() {
853 if (mIsExiting) {
854 removeIfPossible();
855 }
856 return super.checkCompleteDeferredRemoval();
857 }
858
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700859 void onRemovedFromDisplay() {
Wale Ogunwalee287e192017-04-21 09:30:12 -0700860 if (mRemovingFromDisplay) {
861 return;
862 }
863 mRemovingFromDisplay = true;
864
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700865 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app token: " + this);
866
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800867 boolean delayed = commitVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700868
lumark588a3e82018-07-20 18:53:54 +0800869 getDisplayContent().mOpeningApps.remove(this);
Evan Rosky2289ba12018-11-19 18:28:18 -0800870 getDisplayContent().mChangingApps.remove(this);
lumark588a3e82018-07-20 18:53:54 +0800871 getDisplayContent().mUnknownAppVisibilityController.appRemovedOrHidden(this);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800872 mWmService.mTaskSnapshotController.onAppRemoved(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700873 waitingToShow = false;
lumark588a3e82018-07-20 18:53:54 +0800874 if (getDisplayContent().mClosingApps.contains(this)) {
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700875 delayed = true;
lumark588a3e82018-07-20 18:53:54 +0800876 } else if (getDisplayContent().mAppTransition.isTransitionSet()) {
877 getDisplayContent().mClosingApps.add(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700878 delayed = true;
879 }
880
881 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app " + this + " delayed=" + delayed
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200882 + " animation=" + getAnimation() + " animating=" + isSelfAnimating());
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700883
884 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: "
885 + this + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
886
chaviwa8f07a72019-05-01 16:25:39 -0700887 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800888 removeStartingWindow();
Jorim Jaggi19be6052017-08-03 18:33:43 +0200889 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800890
Winson Chung87e5d552017-04-05 11:49:38 -0700891 // If this window was animating, then we need to ensure that the app transition notifies
lumark588a3e82018-07-20 18:53:54 +0800892 // that animations have completed in DisplayContent.handleAnimatingStoppedAndTransition(),
893 // so add to that list now
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200894 if (isSelfAnimating()) {
lumark588a3e82018-07-20 18:53:54 +0800895 getDisplayContent().mNoAnimationNotifyOnTransitionFinished.add(token);
Winson Chung87e5d552017-04-05 11:49:38 -0700896 }
897
Wale Ogunwalee287e192017-04-21 09:30:12 -0700898 final TaskStack stack = getStack();
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700899 if (delayed && !isEmpty()) {
900 // set the token aside because it has an active animation to be finished
901 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM,
902 "removeAppToken make exiting: " + this);
Wale Ogunwalee287e192017-04-21 09:30:12 -0700903 if (stack != null) {
904 stack.mExitingAppTokens.add(this);
905 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700906 mIsExiting = true;
907 } else {
908 // Make sure there is no animation running on this token, so any windows associated
909 // with it will be removed as soon as their animations are complete
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200910 cancelAnimation();
Wale Ogunwale3106ae012017-05-16 08:56:37 -0700911 if (stack != null) {
912 stack.mExitingAppTokens.remove(this);
913 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700914 removeIfPossible();
915 }
916
917 removed = true;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700918 stopFreezingScreen(true, true);
Bryce Lee6d410262017-02-28 15:30:17 -0800919
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800920 final DisplayContent dc = getDisplayContent();
921 if (dc.mFocusedApp == this) {
922 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + this
923 + " displayId=" + dc.getDisplayId());
924 dc.setFocusedApp(null);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800925 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700926 }
Riddle Hsu192fe762019-01-15 23:41:57 +0800927 if (mLetterbox != null) {
928 mLetterbox.destroy();
929 mLetterbox = null;
930 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700931
932 if (!delayed) {
933 updateReportedVisibilityLocked();
934 }
Wale Ogunwalee287e192017-04-21 09:30:12 -0700935
936 mRemovingFromDisplay = false;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700937 }
938
Chong Zhange05bcb12016-07-26 17:47:29 -0700939 void clearAnimatingFlags() {
Chong Zhangb0d26702016-08-12 16:03:29 -0700940 boolean wallpaperMightChange = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700941 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700942 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700943 wallpaperMightChange |= win.clearAnimatingFlags();
Chong Zhange05bcb12016-07-26 17:47:29 -0700944 }
Chong Zhangb0d26702016-08-12 16:03:29 -0700945 if (wallpaperMightChange) {
946 requestUpdateWallpaperIfNeeded();
947 }
Chong Zhange05bcb12016-07-26 17:47:29 -0700948 }
949
Robert Carre12aece2016-02-02 22:43:27 -0800950 void destroySurfaces() {
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700951 destroySurfaces(false /*cleanupOnResume*/);
952 }
953
954 /**
955 * Destroy surfaces which have been marked as eligible by the animator, taking care to ensure
956 * the client has finished with them.
957 *
958 * @param cleanupOnResume whether this is done when app is resumed without fully stopped. If
959 * set to true, destroy only surfaces of removed windows, and clear relevant flags of the
960 * others so that they are ready to be reused. If set to false (common case), destroy all
961 * surfaces that's eligible, if the app is already stopped.
962 */
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700963 private void destroySurfaces(boolean cleanupOnResume) {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700964 boolean destroyedSomething = false;
Jorim Jaggia5e10572017-11-15 14:36:26 +0100965
966 // Copying to a different list as multiple children can be removed.
Jorim Jaggi59f3e922018-01-05 15:40:32 +0100967 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
Jorim Jaggia5e10572017-11-15 14:36:26 +0100968 for (int i = children.size() - 1; i >= 0; i--) {
969 final WindowState win = children.get(i);
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700970 destroyedSomething |= win.destroySurface(cleanupOnResume, mAppStopped);
Robert Carre12aece2016-02-02 22:43:27 -0800971 }
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700972 if (destroyedSomething) {
973 final DisplayContent dc = getDisplayContent();
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700974 dc.assignWindowLayers(true /*setLayoutNeeded*/);
Adrian Roos23df3a32018-03-15 15:41:13 +0100975 updateLetterboxSurface(null);
Robert Carre12aece2016-02-02 22:43:27 -0800976 }
977 }
978
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800979 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700980 * Notify that the app is now resumed, and it was not stopped before, perform a clean
981 * up of the surfaces
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800982 */
Jorim Jaggibae01b12017-04-11 16:29:10 -0700983 void notifyAppResumed(boolean wasStopped) {
Chong Zhangad24f962016-08-25 12:12:33 -0700984 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppResumed: wasStopped=" + wasStopped
Jorim Jaggibae01b12017-04-11 16:29:10 -0700985 + " " + this);
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700986 mAppStopped = false;
chaviwd3bf08d2017-08-01 17:24:59 -0700987 // Allow the window to turn the screen on once the app is resumed again.
Riddle Hsu4bb06be2019-07-02 01:03:07 +0800988 setCurrentLaunchCanTurnScreenOn(true);
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700989 if (!wasStopped) {
990 destroySurfaces(true /*cleanupOnResume*/);
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800991 }
Robert Carre12aece2016-02-02 22:43:27 -0800992 }
993
Chong Zhangbef461f2015-10-27 11:38:24 -0700994 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700995 * Notify that the app has stopped, and it is okay to destroy any surfaces which were
996 * keeping alive in case they were still being used.
997 */
998 void notifyAppStopped() {
999 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: " + this);
1000 mAppStopped = true;
1001 destroySurfaces();
1002 // Remove any starting window that was added for this app if they are still around.
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001003 removeStartingWindow();
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001004 }
1005
Chong Zhang92147042016-05-09 12:47:11 -07001006 void clearAllDrawn() {
1007 allDrawn = false;
1008 deferClearAllDrawn = false;
Chong Zhangbef461f2015-10-27 11:38:24 -07001009 }
1010
Bryce Lee6d410262017-02-28 15:30:17 -08001011 Task getTask() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001012 return (Task) getParent();
Bryce Lee6d410262017-02-28 15:30:17 -08001013 }
1014
Jorim Jaggi3878ca32017-02-02 17:13:05 -08001015 TaskStack getStack() {
1016 final Task task = getTask();
1017 if (task != null) {
1018 return task.mStack;
1019 } else {
1020 return null;
1021 }
1022 }
1023
Bryce Lee6d410262017-02-28 15:30:17 -08001024 @Override
Riddle Hsu3a4bb612019-01-31 00:02:22 +08001025 void onParentChanged() {
1026 super.onParentChanged();
Bryce Lee6d410262017-02-28 15:30:17 -08001027
Robert Carred3e83b2017-04-21 13:26:55 -07001028 final Task task = getTask();
1029
Bryce Lee6d410262017-02-28 15:30:17 -08001030 // When the associated task is {@code null}, the {@link AppWindowToken} can no longer
1031 // access visual elements like the {@link DisplayContent}. We must remove any associations
1032 // such as animations.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001033 if (!mReparenting) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001034 if (task == null) {
1035 // It is possible we have been marked as a closing app earlier. We must remove ourselves
1036 // from this list so we do not participate in any future animations.
lumark588a3e82018-07-20 18:53:54 +08001037 getDisplayContent().mClosingApps.remove(this);
Robert Carred3e83b2017-04-21 13:26:55 -07001038 } else if (mLastParent != null && mLastParent.mStack != null) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001039 task.mStack.mExitingAppTokens.remove(this);
1040 }
Bryce Lee6d410262017-02-28 15:30:17 -08001041 }
Jorim Jaggi6de61012018-03-19 14:53:23 +01001042 final TaskStack stack = getStack();
1043
1044 // If we reparent, make sure to remove ourselves from the old animation registry.
1045 if (mAnimatingAppWindowTokenRegistry != null) {
1046 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
1047 }
1048 mAnimatingAppWindowTokenRegistry = stack != null
1049 ? stack.getAnimatingAppWindowTokenRegistry()
1050 : null;
1051
Robert Carred3e83b2017-04-21 13:26:55 -07001052 mLastParent = task;
chaviwdcf76ec2019-01-11 16:48:46 -08001053
1054 updateColorTransform();
Bryce Lee6d410262017-02-28 15:30:17 -08001055 }
1056
Wale Ogunwalefa854eb2016-09-20 13:43:52 -07001057 void postWindowRemoveStartingWindowCleanup(WindowState win) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001058 // TODO: Something smells about the code below...Is there a better way?
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001059 if (startingWindow == win) {
1060 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Notify removed startingWindow " + win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001061 removeStartingWindow();
Wale Ogunwale6c459212017-05-17 08:56:03 -07001062 } else if (mChildren.size() == 0) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001063 // If this is the last window and we had requested a starting transition window,
1064 // well there is no point now.
Jorim Jaggi02886a82016-12-06 09:10:06 -08001065 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Nulling last startingData");
chaviwa8f07a72019-05-01 16:25:39 -07001066 mStartingData = null;
Wale Ogunwale6c459212017-05-17 08:56:03 -07001067 if (mHiddenSetFromTransferredStartingWindow) {
1068 // We set the hidden state to false for the token from a transferred starting window.
1069 // We now reset it back to true since the starting window was the last window in the
1070 // token.
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001071 setHidden(true);
Wale Ogunwale6c459212017-05-17 08:56:03 -07001072 }
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01001073 } else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001074 // If this is the last window except for a starting transition window,
1075 // we need to get rid of the starting transition.
Jorim Jaggie4b0f282017-05-17 15:10:29 +02001076 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Last window, removing starting window "
1077 + win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001078 removeStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001079 }
1080 }
1081
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001082 void removeDeadWindows() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001083 for (int winNdx = mChildren.size() - 1; winNdx >= 0; --winNdx) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001084 WindowState win = mChildren.get(winNdx);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001085 if (win.mAppDied) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001086 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.w(TAG,
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001087 "removeDeadWindows: " + win);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001088 // Set mDestroying, we don't want any animation or delayed removal here.
1089 win.mDestroying = true;
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001090 // Also removes child windows.
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001091 win.removeIfPossible();
Chong Zhang112eb8c2015-11-02 11:17:00 -08001092 }
1093 }
1094 }
1095
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001096 boolean hasWindowsAlive() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001097 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001098 // No need to loop through child windows as the answer should be the same as that of the
1099 // parent window.
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001100 if (!(mChildren.get(i)).mAppDied) {
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001101 return true;
1102 }
1103 }
1104 return false;
1105 }
1106
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001107 void setWillReplaceWindows(boolean animate) {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001108 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
1109 "Marking app token " + this + " with replacing windows.");
Robert Carra1eb4392015-12-10 12:43:51 -08001110
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001111 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001112 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001113 w.setWillReplaceWindow(animate);
Robert Carra1eb4392015-12-10 12:43:51 -08001114 }
Robert Carra1eb4392015-12-10 12:43:51 -08001115 }
1116
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001117 void setWillReplaceChildWindows() {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001118 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Marking app token " + this
Robert Carr23fa16b2016-01-13 13:19:58 -08001119 + " with replacing child windows.");
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001120 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001121 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001122 w.setWillReplaceChildWindows();
Robert Carr23fa16b2016-01-13 13:19:58 -08001123 }
1124 }
1125
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001126 void clearWillReplaceWindows() {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001127 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
1128 "Resetting app token " + this + " of replacing window marks.");
Chong Zhangf596cd52016-01-05 13:42:44 -08001129
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001130 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001131 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001132 w.clearWillReplaceWindow();
Chong Zhangf596cd52016-01-05 13:42:44 -08001133 }
1134 }
1135
Chong Zhang4d7369a2016-04-25 16:09:14 -07001136 void requestUpdateWallpaperIfNeeded() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001137 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001138 final WindowState w = mChildren.get(i);
Chong Zhang4d7369a2016-04-25 16:09:14 -07001139 w.requestUpdateWallpaperIfNeeded();
1140 }
1141 }
1142
Chong Zhangd78ddb42016-03-02 17:01:14 -08001143 boolean isRelaunching() {
1144 return mPendingRelaunchCount > 0;
1145 }
1146
Robert Carr68375192017-06-13 12:41:53 -07001147 boolean shouldFreezeBounds() {
1148 final Task task = getTask();
1149
1150 // For freeform windows, we can't freeze the bounds at the moment because this would make
1151 // the resizing unresponsive.
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001152 if (task == null || task.inFreeformWindowingMode()) {
Robert Carr68375192017-06-13 12:41:53 -07001153 return false;
1154 }
1155
1156 // We freeze the bounds while drag resizing to deal with the time between
1157 // the divider/drag handle being released, and the handling it's new
1158 // configuration. If we are relaunched outside of the drag resizing state,
1159 // we need to be careful not to do this.
1160 return getTask().isDragResizing();
1161 }
1162
Chong Zhangd78ddb42016-03-02 17:01:14 -08001163 void startRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001164 if (shouldFreezeBounds()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08001165 freezeBounds();
1166 }
Robert Carrd5c7dd62017-03-08 10:39:30 -08001167
1168 // In the process of tearing down before relaunching, the app will
1169 // try and clean up it's child surfaces. We need to prevent this from
1170 // happening, so we sever the children, transfering their ownership
1171 // from the client it-self to the parent surface (owned by us).
Robert Carr29daa922018-04-27 11:56:48 -07001172 detachChildren();
1173
1174 mPendingRelaunchCount++;
1175 }
1176
1177 void detachChildren() {
Robert Carrfd8e93b2018-05-10 13:40:25 -07001178 SurfaceControl.openTransaction();
Robert Carrd5c7dd62017-03-08 10:39:30 -08001179 for (int i = mChildren.size() - 1; i >= 0; i--) {
1180 final WindowState w = mChildren.get(i);
1181 w.mWinAnimator.detachChildren();
1182 }
Robert Carrfd8e93b2018-05-10 13:40:25 -07001183 SurfaceControl.closeTransaction();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001184 }
1185
1186 void finishRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001187 unfreezeBounds();
1188
Chong Zhangd78ddb42016-03-02 17:01:14 -08001189 if (mPendingRelaunchCount > 0) {
1190 mPendingRelaunchCount--;
Bryce Lee081554b2017-05-25 07:52:12 -07001191 } else {
1192 // Update keyguard flags upon finishing relaunch.
1193 checkKeyguardFlagsChanged();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001194 }
1195 }
1196
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001197 void clearRelaunching() {
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001198 if (mPendingRelaunchCount == 0) {
1199 return;
1200 }
Robert Carr68375192017-06-13 12:41:53 -07001201 unfreezeBounds();
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001202 mPendingRelaunchCount = 0;
1203 }
1204
Wale Ogunwale07bcab72016-10-14 15:30:09 -07001205 /**
1206 * Returns true if the new child window we are adding to this token is considered greater than
1207 * the existing child window in this token in terms of z-order.
1208 */
1209 @Override
1210 protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
1211 WindowState existingWindow) {
1212 final int type1 = newWindow.mAttrs.type;
1213 final int type2 = existingWindow.mAttrs.type;
1214
1215 // Base application windows should be z-ordered BELOW all other windows in the app token.
1216 if (type1 == TYPE_BASE_APPLICATION && type2 != TYPE_BASE_APPLICATION) {
1217 return false;
1218 } else if (type1 != TYPE_BASE_APPLICATION && type2 == TYPE_BASE_APPLICATION) {
1219 return true;
1220 }
1221
1222 // Starting windows should be z-ordered ABOVE all other windows in the app token.
1223 if (type1 == TYPE_APPLICATION_STARTING && type2 != TYPE_APPLICATION_STARTING) {
1224 return true;
1225 } else if (type1 != TYPE_APPLICATION_STARTING && type2 == TYPE_APPLICATION_STARTING) {
1226 return false;
1227 }
1228
1229 // Otherwise the new window is greater than the existing window.
1230 return true;
1231 }
1232
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001233 @Override
Robert Carra1eb4392015-12-10 12:43:51 -08001234 void addWindow(WindowState w) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001235 super.addWindow(w);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001236
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001237 boolean gotReplacementWindow = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001238 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001239 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001240 gotReplacementWindow |= candidate.setReplacementWindowIfNeeded(w);
1241 }
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001242
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001243 // if we got a replacement window, reset the timeout to give drawing more time
1244 if (gotReplacementWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001245 mWmService.scheduleWindowReplacementTimeouts(this);
Robert Carra1eb4392015-12-10 12:43:51 -08001246 }
Jorim Jaggife762342016-10-13 14:33:27 +02001247 checkKeyguardFlagsChanged();
1248 }
1249
1250 @Override
1251 void removeChild(WindowState child) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001252 if (!mChildren.contains(child)) {
1253 // This can be true when testing.
1254 return;
1255 }
Jorim Jaggife762342016-10-13 14:33:27 +02001256 super.removeChild(child);
1257 checkKeyguardFlagsChanged();
Adrian Roos23df3a32018-03-15 15:41:13 +01001258 updateLetterboxSurface(child);
Robert Carra1eb4392015-12-10 12:43:51 -08001259 }
1260
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001261 private boolean waitingForReplacement() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001262 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001263 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001264 if (candidate.waitingForReplacement()) {
Robert Carra1eb4392015-12-10 12:43:51 -08001265 return true;
1266 }
1267 }
1268 return false;
1269 }
1270
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001271 void onWindowReplacementTimeout() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001272 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001273 (mChildren.get(i)).onWindowReplacementTimeout();
Robert Carra1eb4392015-12-10 12:43:51 -08001274 }
1275 }
1276
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001277 void reparent(Task task, int position) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001278 if (DEBUG_ADD_REMOVE) {
1279 Slog.i(TAG_WM, "reparent: moving app token=" + this
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001280 + " to task=" + task.mTaskId + " at " + position);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001281 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001282 if (task == null) {
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001283 throw new IllegalArgumentException("reparent: could not find task");
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001284 }
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001285 final Task currentTask = getTask();
1286 if (task == currentTask) {
Winson Chung30480042017-01-26 10:55:34 -08001287 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001288 "window token=" + this + " already child of task=" + currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001289 }
Bryce Lee6d410262017-02-28 15:30:17 -08001290
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001291 if (currentTask.mStack != task.mStack) {
Bryce Lee6d410262017-02-28 15:30:17 -08001292 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001293 "window token=" + this + " current task=" + currentTask
Bryce Lee6d410262017-02-28 15:30:17 -08001294 + " belongs to a different stack than " + task);
1295 }
1296
Winson Chung30480042017-01-26 10:55:34 -08001297 if (DEBUG_ADD_REMOVE) Slog.i(TAG, "reParentWindowToken: removing window token=" + this
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001298 + " from task=" + currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001299 final DisplayContent prevDisplayContent = getDisplayContent();
1300
Bryce Lee6d410262017-02-28 15:30:17 -08001301 mReparenting = true;
1302
Winson Chung30480042017-01-26 10:55:34 -08001303 getParent().removeChild(this);
1304 task.addChild(this, position);
1305
Bryce Lee6d410262017-02-28 15:30:17 -08001306 mReparenting = false;
1307
Winson Chung30480042017-01-26 10:55:34 -08001308 // Relayout display(s).
1309 final DisplayContent displayContent = task.getDisplayContent();
1310 displayContent.setLayoutNeeded();
1311 if (prevDisplayContent != displayContent) {
1312 onDisplayChanged(displayContent);
1313 prevDisplayContent.setLayoutNeeded();
1314 }
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001315 getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
Winson Chung30480042017-01-26 10:55:34 -08001316 }
1317
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001318 @Override
1319 void onDisplayChanged(DisplayContent dc) {
1320 DisplayContent prevDc = mDisplayContent;
1321 super.onDisplayChanged(dc);
Evan Roskyb1e75f72019-04-26 20:23:26 -07001322 if (prevDc == null || prevDc == mDisplayContent) {
Evan Rosky25b56192019-02-06 16:10:56 -08001323 return;
1324 }
Wale Ogunwaleb8e6b632019-06-28 15:19:25 +00001325
1326 if (prevDc.mOpeningApps.remove(this)) {
1327 // Transfer opening transition to new display.
1328 mDisplayContent.mOpeningApps.add(this);
1329 mDisplayContent.prepareAppTransition(prevDc.mAppTransition.getAppTransition(), true);
1330 mDisplayContent.executeAppTransition();
1331 }
1332
1333 if (prevDc.mChangingApps.remove(this)) {
Evan Rosky25b56192019-02-06 16:10:56 -08001334 // This gets called *after* the AppWindowToken has been reparented to the new display.
1335 // That reparenting resulted in this window changing modes (eg. FREEFORM -> FULLSCREEN),
1336 // so this token is now "frozen" while waiting for the animation to start on prevDc
1337 // (which will be cancelled since the window is no-longer a child). However, since this
1338 // is no longer a child of prevDc, this won't be notified of the cancelled animation,
1339 // so we need to cancel the change transition here.
1340 clearChangeLeash(getPendingTransaction(), true /* cancel */);
1341 }
Wale Ogunwaleb8e6b632019-06-28 15:19:25 +00001342 prevDc.mClosingApps.remove(this);
1343
Evan Rosky25b56192019-02-06 16:10:56 -08001344 if (prevDc.mFocusedApp == this) {
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001345 prevDc.setFocusedApp(null);
lumarkbf844642018-11-23 17:11:36 +08001346 final TaskStack stack = dc.getTopStack();
1347 if (stack != null) {
1348 final Task task = stack.getTopChild();
1349 if (task != null && task.getTopChild() == this) {
1350 dc.setFocusedApp(this);
1351 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001352 }
1353 }
Riddle Hsu192fe762019-01-15 23:41:57 +08001354
Evan Roskyb1e75f72019-04-26 20:23:26 -07001355 if (mLetterbox != null) {
Riddle Hsu192fe762019-01-15 23:41:57 +08001356 mLetterbox.onMovedToDisplay(mDisplayContent.getDisplayId());
1357 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001358 }
1359
Jorim Jaggi0429f352015-12-22 16:29:16 +01001360 /**
1361 * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds
1362 * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even
1363 * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen
1364 * with a queue.
1365 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001366 private void freezeBounds() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001367 final Task task = getTask();
1368 mFrozenBounds.offer(new Rect(task.mPreparedFrozenBounds));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001369
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001370 if (task.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001371 // We didn't call prepareFreezingBounds on the task, so use the current value.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001372 mFrozenMergedConfig.offer(new Configuration(task.getConfiguration()));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001373 } else {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001374 mFrozenMergedConfig.offer(new Configuration(task.mPreparedFrozenMergedConfig));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001375 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001376 // Calling unset() to make it equal to Configuration.EMPTY.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001377 task.mPreparedFrozenMergedConfig.unset();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001378 }
1379
1380 /**
1381 * Unfreezes the previously frozen bounds. See {@link #freezeBounds}.
1382 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001383 private void unfreezeBounds() {
Robert Carr68375192017-06-13 12:41:53 -07001384 if (mFrozenBounds.isEmpty()) {
1385 return;
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001386 }
Robert Carr68375192017-06-13 12:41:53 -07001387 mFrozenBounds.remove();
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001388 if (!mFrozenMergedConfig.isEmpty()) {
1389 mFrozenMergedConfig.remove();
1390 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001391 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001392 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001393 win.onUnfreezeBounds();
Jorim Jaggi4846ee32016-01-07 17:39:12 +01001394 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001395 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001396 }
1397
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001398 void setAppLayoutChanges(int changes, String reason) {
1399 if (!mChildren.isEmpty()) {
1400 final DisplayContent dc = getDisplayContent();
1401 dc.pendingLayoutChanges |= changes;
1402 if (DEBUG_LAYOUT_REPEATS) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001403 mWmService.mWindowPlacerLocked.debugLayoutRepeats(reason, dc.pendingLayoutChanges);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001404 }
1405 }
1406 }
1407
1408 void removeReplacedWindowIfNeeded(WindowState replacement) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001409 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001410 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001411 if (win.removeReplacedWindowIfNeeded(replacement)) {
1412 return;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001413 }
1414 }
1415 }
1416
1417 void startFreezingScreen() {
1418 if (DEBUG_ORIENTATION) logWithStack(TAG, "Set freezing of " + appToken + ": hidden="
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001419 + isHidden() + " freezing=" + mFreezingScreen + " hiddenRequested="
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001420 + hiddenRequested);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001421 if (!hiddenRequested) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001422 if (!mFreezingScreen) {
1423 mFreezingScreen = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001424 mWmService.registerAppFreezeListener(this);
1425 mWmService.mAppsFreezingScreen++;
1426 if (mWmService.mAppsFreezingScreen == 1) {
1427 mWmService.startFreezingDisplayLocked(0, 0, getDisplayContent());
1428 mWmService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
1429 mWmService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001430 }
1431 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001432 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001433 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001434 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001435 w.onStartFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001436 }
1437 }
1438 }
1439
1440 void stopFreezingScreen(boolean unfreezeSurfaceNow, boolean force) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001441 if (!mFreezingScreen) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001442 return;
1443 }
1444 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + this + " force=" + force);
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001445 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001446 boolean unfrozeWindows = false;
1447 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001448 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001449 unfrozeWindows |= w.onStopFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001450 }
1451 if (force || unfrozeWindows) {
1452 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "No longer freezing: " + this);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001453 mFreezingScreen = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001454 mWmService.unregisterAppFreezeListener(this);
1455 mWmService.mAppsFreezingScreen--;
1456 mWmService.mLastFinishedFreezeSource = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001457 }
1458 if (unfreezeSurfaceNow) {
1459 if (unfrozeWindows) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001460 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001461 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001462 mWmService.stopFreezingDisplayLocked();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001463 }
1464 }
1465
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001466 @Override
1467 public void onAppFreezeTimeout() {
1468 Slog.w(TAG_WM, "Force clearing freeze: " + this);
1469 stopFreezingScreen(true, true);
1470 }
1471
Jorim Jaggi60f9c972018-02-01 19:21:07 +01001472 /**
1473 * Tries to transfer the starting window from a token that's above ourselves in the task but
1474 * not visible anymore. This is a common scenario apps use: Trampoline activity T start main
1475 * activity M in the same task. Now, when reopening the task, T starts on top of M but then
1476 * immediately finishes after, so we have to transfer T to M.
1477 */
1478 void transferStartingWindowFromHiddenAboveTokenIfNeeded() {
1479 final Task task = getTask();
1480 for (int i = task.mChildren.size() - 1; i >= 0; i--) {
1481 final AppWindowToken fromToken = task.mChildren.get(i);
1482 if (fromToken == this) {
1483 return;
1484 }
1485 if (fromToken.hiddenRequested && transferStartingWindow(fromToken.token)) {
1486 return;
1487 }
1488 }
1489 }
1490
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001491 boolean transferStartingWindow(IBinder transferFrom) {
Wale Ogunwale02319a62016-09-26 15:21:22 -07001492 final AppWindowToken fromToken = getDisplayContent().getAppWindowToken(transferFrom);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001493 if (fromToken == null) {
1494 return false;
1495 }
1496
1497 final WindowState tStartingWindow = fromToken.startingWindow;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08001498 if (tStartingWindow != null && fromToken.startingSurface != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001499 // In this case, the starting icon has already been displayed, so start
1500 // letting windows get shown immediately without any more transitions.
lumark588a3e82018-07-20 18:53:54 +08001501 getDisplayContent().mSkipAppTransitionAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001502
1503 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Moving existing starting " + tStartingWindow
1504 + " from " + fromToken + " to " + this);
1505
1506 final long origId = Binder.clearCallingIdentity();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001507 try {
1508 // Transfer the starting window over to the new token.
chaviwa8f07a72019-05-01 16:25:39 -07001509 mStartingData = fromToken.mStartingData;
Peter Visontay3556a3b2017-11-01 17:23:17 +00001510 startingSurface = fromToken.startingSurface;
1511 startingDisplayed = fromToken.startingDisplayed;
1512 fromToken.startingDisplayed = false;
1513 startingWindow = tStartingWindow;
1514 reportedVisible = fromToken.reportedVisible;
chaviwa8f07a72019-05-01 16:25:39 -07001515 fromToken.mStartingData = null;
Peter Visontay3556a3b2017-11-01 17:23:17 +00001516 fromToken.startingSurface = null;
1517 fromToken.startingWindow = null;
1518 fromToken.startingMoved = true;
1519 tStartingWindow.mToken = this;
1520 tStartingWindow.mAppToken = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001521
Peter Visontay3556a3b2017-11-01 17:23:17 +00001522 if (DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
1523 "Removing starting " + tStartingWindow + " from " + fromToken);
1524 fromToken.removeChild(tStartingWindow);
1525 fromToken.postWindowRemoveStartingWindowCleanup(tStartingWindow);
1526 fromToken.mHiddenSetFromTransferredStartingWindow = false;
1527 addWindow(tStartingWindow);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001528
Peter Visontay3556a3b2017-11-01 17:23:17 +00001529 // Propagate other interesting state between the tokens. If the old token is displayed,
1530 // we should immediately force the new one to be displayed. If it is animating, we need
1531 // to move that animation to the new one.
1532 if (fromToken.allDrawn) {
1533 allDrawn = true;
1534 deferClearAllDrawn = fromToken.deferClearAllDrawn;
1535 }
1536 if (fromToken.firstWindowDrawn) {
1537 firstWindowDrawn = true;
1538 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001539 if (!fromToken.isHidden()) {
1540 setHidden(false);
Peter Visontay3556a3b2017-11-01 17:23:17 +00001541 hiddenRequested = false;
1542 mHiddenSetFromTransferredStartingWindow = true;
1543 }
1544 setClientHidden(fromToken.mClientHidden);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001545
Jorim Jaggi980c9de2017-11-17 01:41:37 +01001546 transferAnimation(fromToken);
1547
1548 // When transferring an animation, we no longer need to apply an animation to the
Tiger Huangc9d0d002019-05-29 22:55:29 +08001549 // the token we transfer the animation over. Thus, set this flag to indicate we've
1550 // transferred the animation.
1551 mUseTransferredAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001552
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001553 mWmService.updateFocusedWindowLocked(
Peter Visontay3556a3b2017-11-01 17:23:17 +00001554 UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/);
1555 getDisplayContent().setLayoutNeeded();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001556 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001557 } finally {
1558 Binder.restoreCallingIdentity(origId);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001559 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001560 return true;
chaviwa8f07a72019-05-01 16:25:39 -07001561 } else if (fromToken.mStartingData != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001562 // The previous app was getting ready to show a
1563 // starting window, but hasn't yet done so. Steal it!
1564 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
1565 "Moving pending starting from " + fromToken + " to " + this);
chaviwa8f07a72019-05-01 16:25:39 -07001566 mStartingData = fromToken.mStartingData;
1567 fromToken.mStartingData = null;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001568 fromToken.startingMoved = true;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001569 scheduleAddStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001570 return true;
1571 }
1572
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001573 // TODO: Transfer thumbnail
1574
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001575 return false;
1576 }
1577
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001578 boolean isLastWindow(WindowState win) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001579 return mChildren.size() == 1 && mChildren.get(0) == win;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001580 }
1581
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001582 @Override
1583 void onAppTransitionDone() {
1584 sendingToBottom = false;
1585 }
1586
Wale Ogunwale51362492016-09-08 17:49:17 -07001587 /**
1588 * We override because this class doesn't want its children affecting its reported orientation
1589 * in anyway.
1590 */
1591 @Override
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001592 int getOrientation(int candidate) {
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001593 if (candidate == SCREEN_ORIENTATION_BEHIND) {
1594 // Allow app to specify orientation regardless of its visibility state if the current
1595 // candidate want us to use orientation behind. I.e. the visible app on-top of this one
1596 // wants us to use the orientation of the app behind it.
1597 return mOrientation;
1598 }
1599
Bryce Lee61fbcbc2017-03-10 14:14:03 -08001600 // The {@link AppWindowToken} should only specify an orientation when it is not closing or
1601 // going to the bottom. Allowing closing {@link AppWindowToken} to participate can lead to
1602 // an Activity in another task being started in the wrong orientation during the transition.
lumark588a3e82018-07-20 18:53:54 +08001603 if (!(sendingToBottom || getDisplayContent().mClosingApps.contains(this))
1604 && (isVisible() || getDisplayContent().mOpeningApps.contains(this))) {
Bryce Leea163b762017-01-24 11:05:01 -08001605 return mOrientation;
Wale Ogunwale51362492016-09-08 17:49:17 -07001606 }
Bryce Leea163b762017-01-24 11:05:01 -08001607
1608 return SCREEN_ORIENTATION_UNSET;
Wale Ogunwale51362492016-09-08 17:49:17 -07001609 }
1610
Wale Ogunwaleb198b742016-12-01 08:44:09 -08001611 /** Returns the app's preferred orientation regardless of its currently visibility state. */
1612 int getOrientationIgnoreVisibility() {
1613 return mOrientation;
1614 }
1615
Riddle Hsub398da32019-01-21 21:48:16 +08001616 /** @return {@code true} if the compatibility bounds is taking effect. */
1617 boolean inSizeCompatMode() {
1618 return mSizeCompatBounds != null;
1619 }
1620
1621 @Override
1622 float getSizeCompatScale() {
1623 return inSizeCompatMode() ? mSizeCompatScale : super.getSizeCompatScale();
1624 }
1625
1626 /**
1627 * @return Non-empty bounds if the activity has override bounds.
1628 * @see ActivityRecord#resolveOverrideConfiguration(Configuration)
1629 */
1630 Rect getResolvedOverrideBounds() {
1631 // Get bounds from resolved override configuration because it is computed with orientation.
1632 return getResolvedOverrideConfiguration().windowConfiguration.getBounds();
1633 }
1634
Craig Mautnerdbb79912012-03-01 18:59:14 -08001635 @Override
Winson Chunge55c0192017-08-24 14:50:48 -07001636 public void onConfigurationChanged(Configuration newParentConfig) {
1637 final int prevWinMode = getWindowingMode();
Evan Rosky2289ba12018-11-19 18:28:18 -08001638 mTmpPrevBounds.set(getBounds());
Winson Chunge55c0192017-08-24 14:50:48 -07001639 super.onConfigurationChanged(newParentConfig);
Riddle Hsub398da32019-01-21 21:48:16 +08001640
1641 final Task task = getTask();
1642 final Rect overrideBounds = getResolvedOverrideBounds();
1643 if (task != null && !overrideBounds.isEmpty()
1644 // If the changes come from change-listener, the incoming parent configuration is
1645 // still the old one. Make sure their orientations are the same to reduce computing
1646 // the compatibility bounds for the intermediate state.
Riddle Hsu04164182019-03-07 18:03:27 +08001647 && (task.mTaskRecord == null || task.mTaskRecord
1648 .getConfiguration().orientation == newParentConfig.orientation)) {
Riddle Hsub398da32019-01-21 21:48:16 +08001649 final Rect taskBounds = task.getBounds();
1650 // Since we only center the activity horizontally, if only the fixed height is smaller
1651 // than its container, the override bounds don't need to take effect.
1652 if ((overrideBounds.width() != taskBounds.width()
1653 || overrideBounds.height() > taskBounds.height())) {
1654 calculateCompatBoundsTransformation(newParentConfig);
1655 updateSurfacePosition();
1656 } else if (mSizeCompatBounds != null) {
1657 mSizeCompatBounds = null;
1658 mSizeCompatScale = 1f;
1659 updateSurfacePosition();
1660 }
1661 }
1662
Winson Chunge55c0192017-08-24 14:50:48 -07001663 final int winMode = getWindowingMode();
1664
1665 if (prevWinMode == winMode) {
1666 return;
1667 }
1668
1669 if (prevWinMode != WINDOWING_MODE_UNDEFINED && winMode == WINDOWING_MODE_PINNED) {
1670 // Entering PiP from fullscreen, reset the snap fraction
1671 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(this);
Winson Chung82267ce2018-04-06 16:38:26 -07001672 } else if (prevWinMode == WINDOWING_MODE_PINNED && winMode != WINDOWING_MODE_UNDEFINED
1673 && !isHidden()) {
Winson Chunge55c0192017-08-24 14:50:48 -07001674 // Leaving PiP to fullscreen, save the snap fraction based on the pre-animation bounds
1675 // for the next re-entry into PiP (assuming the activity is not hidden or destroyed)
1676 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
1677 if (pinnedStack != null) {
Winson Chung8efa1652018-06-06 09:34:23 -07001678 final Rect stackBounds;
1679 if (pinnedStack.lastAnimatingBoundsWasToFullscreen()) {
1680 // We are animating the bounds, use the pre-animation bounds to save the snap
1681 // fraction
1682 stackBounds = pinnedStack.mPreAnimationBounds;
1683 } else {
1684 // We skip the animation if the fullscreen configuration is not compatible, so
1685 // use the current bounds to calculate the saved snap fraction instead
1686 // (see PinnedActivityStack.skipResizeAnimation())
1687 stackBounds = mTmpRect;
1688 pinnedStack.getBounds(stackBounds);
1689 }
Winson Chunge55c0192017-08-24 14:50:48 -07001690 mDisplayContent.mPinnedStackControllerLocked.saveReentrySnapFraction(this,
Winson Chung8efa1652018-06-06 09:34:23 -07001691 stackBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001692 }
Evan Rosky2289ba12018-11-19 18:28:18 -08001693 } else if (shouldStartChangeTransition(prevWinMode, winMode)) {
1694 initializeChangeTransition(mTmpPrevBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001695 }
1696 }
1697
Evan Rosky2289ba12018-11-19 18:28:18 -08001698 private boolean shouldStartChangeTransition(int prevWinMode, int newWinMode) {
Evan Rosky25b56192019-02-06 16:10:56 -08001699 if (mWmService.mDisableTransitionAnimation
1700 || !isVisible()
1701 || getDisplayContent().mAppTransition.isTransitionSet()
1702 || getSurfaceControl() == null) {
Evan Rosky2289ba12018-11-19 18:28:18 -08001703 return false;
1704 }
1705 // Only do an animation into and out-of freeform mode for now. Other mode
1706 // transition animations are currently handled by system-ui.
1707 return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
1708 }
1709
1710 /**
1711 * Initializes a change transition. Because the app is visible already, there is a small period
1712 * of time where the user can see the app content/window update before the transition starts.
1713 * To prevent this, we immediately take a snapshot and place the app/snapshot into a leash which
1714 * "freezes" the location/crop until the transition starts.
1715 * <p>
1716 * Here's a walk-through of the process:
1717 * 1. Create a temporary leash ("interim-change-leash") and reparent the app to it.
1718 * 2. Set the temporary leash's position/crop to the current state.
1719 * 3. Create a snapshot and place that at the top of the leash to cover up content changes.
1720 * 4. Once the transition is ready, it will reparent the app to the animation leash.
1721 * 5. Detach the interim-change-leash.
1722 */
1723 private void initializeChangeTransition(Rect startBounds) {
1724 mDisplayContent.prepareAppTransition(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
1725 false /* alwaysKeepCurrent */, 0, false /* forceOverride */);
1726 mDisplayContent.mChangingApps.add(this);
1727 mTransitStartRect.set(startBounds);
1728
1729 final SurfaceControl.Builder builder = makeAnimationLeash()
1730 .setParent(getAnimationLeashParent())
1731 .setName(getSurfaceControl() + " - interim-change-leash");
1732 mTransitChangeLeash = builder.build();
1733 Transaction t = getPendingTransaction();
1734 t.setWindowCrop(mTransitChangeLeash, startBounds.width(), startBounds.height());
1735 t.setPosition(mTransitChangeLeash, startBounds.left, startBounds.top);
1736 t.show(mTransitChangeLeash);
1737 t.reparent(getSurfaceControl(), mTransitChangeLeash);
1738 onAnimationLeashCreated(t, mTransitChangeLeash);
1739
Evan Rosky966759f2019-01-15 10:33:58 -08001740 // Skip creating snapshot if this transition is controlled by a remote animator which
1741 // doesn't need it.
1742 ArraySet<Integer> activityTypes = new ArraySet<>();
1743 activityTypes.add(getActivityType());
1744 RemoteAnimationAdapter adapter =
1745 mDisplayContent.mAppTransitionController.getRemoteAnimationOverride(
1746 this, TRANSIT_TASK_CHANGE_WINDOWING_MODE, activityTypes);
1747 if (adapter != null && !adapter.getChangeNeedsSnapshot()) {
1748 return;
1749 }
1750
Evan Rosky08e20932019-05-14 10:54:07 -07001751 Task task = getTask();
1752 if (mThumbnail == null && task != null && !hasCommittedReparentToAnimationLeash()) {
1753 SurfaceControl.ScreenshotGraphicBuffer snapshot =
1754 mWmService.mTaskSnapshotController.createTaskSnapshot(
1755 task, 1 /* scaleFraction */);
Yunfan Chendcb1fcf2019-02-07 19:08:41 +09001756 if (snapshot != null) {
Evan Rosky08e20932019-05-14 10:54:07 -07001757 mThumbnail = new AppWindowThumbnail(t, this, snapshot.getGraphicBuffer(),
Yunfan Chendcb1fcf2019-02-07 19:08:41 +09001758 true /* relative */);
1759 }
Evan Rosky2289ba12018-11-19 18:28:18 -08001760 }
1761 }
1762
1763 boolean isInChangeTransition() {
Evan Roskyec9488c2019-03-01 19:32:12 -08001764 return mTransitChangeLeash != null || AppTransition.isChangeTransit(mTransit);
Evan Rosky2289ba12018-11-19 18:28:18 -08001765 }
1766
Evan Rosky966759f2019-01-15 10:33:58 -08001767 @VisibleForTesting
1768 AppWindowThumbnail getThumbnail() {
1769 return mThumbnail;
1770 }
1771
Riddle Hsub398da32019-01-21 21:48:16 +08001772 /**
1773 * Calculates the scale and offset to horizontal center the size compatibility bounds into the
1774 * region which is available to application.
1775 */
1776 private void calculateCompatBoundsTransformation(Configuration newParentConfig) {
1777 final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds();
Riddle Hsu74826262019-04-17 14:57:42 +08001778 final Rect parentBounds = newParentConfig.windowConfiguration.getBounds();
1779 final Rect viewportBounds = parentAppBounds != null ? parentAppBounds : parentBounds;
Riddle Hsu04164182019-03-07 18:03:27 +08001780 final Rect appBounds = getWindowConfiguration().getAppBounds();
1781 final Rect contentBounds = appBounds != null ? appBounds : getResolvedOverrideBounds();
Riddle Hsub398da32019-01-21 21:48:16 +08001782 final float contentW = contentBounds.width();
1783 final float contentH = contentBounds.height();
1784 final float viewportW = viewportBounds.width();
1785 final float viewportH = viewportBounds.height();
1786 // Only allow to scale down.
1787 mSizeCompatScale = (contentW <= viewportW && contentH <= viewportH)
1788 ? 1 : Math.min(viewportW / contentW, viewportH / contentH);
1789 final int offsetX = (int) ((viewportW - contentW * mSizeCompatScale + 1) * 0.5f)
1790 + viewportBounds.left;
1791
1792 if (mSizeCompatBounds == null) {
1793 mSizeCompatBounds = new Rect();
1794 }
1795 mSizeCompatBounds.set(contentBounds);
1796 mSizeCompatBounds.offsetTo(0, 0);
1797 mSizeCompatBounds.scale(mSizeCompatScale);
Riddle Hsu74826262019-04-17 14:57:42 +08001798 // Ensure to align the top with the parent.
1799 mSizeCompatBounds.top = parentBounds.top;
Riddle Hsu04164182019-03-07 18:03:27 +08001800 // The decor inset is included in height.
1801 mSizeCompatBounds.bottom += viewportBounds.top;
Riddle Hsub398da32019-01-21 21:48:16 +08001802 mSizeCompatBounds.left += offsetX;
1803 mSizeCompatBounds.right += offsetX;
1804 }
1805
1806 @Override
1807 public Rect getBounds() {
1808 if (mSizeCompatBounds != null) {
1809 return mSizeCompatBounds;
1810 }
1811 return super.getBounds();
1812 }
1813
1814 @Override
1815 public boolean matchParentBounds() {
1816 if (super.matchParentBounds()) {
1817 return true;
1818 }
1819 // An activity in size compatibility mode may have override bounds which equals to its
1820 // parent bounds, so the exact bounds should also be checked.
1821 final WindowContainer parent = getParent();
1822 return parent == null || parent.getBounds().equals(getResolvedOverrideBounds());
1823 }
1824
Winson Chunge55c0192017-08-24 14:50:48 -07001825 @Override
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001826 void checkAppWindowsReadyToShow() {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001827 if (allDrawn == mLastAllDrawn) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001828 return;
1829 }
1830
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001831 mLastAllDrawn = allDrawn;
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001832 if (!allDrawn) {
1833 return;
1834 }
1835
1836 // The token has now changed state to having all windows shown... what to do, what to do?
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001837 if (mFreezingScreen) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001838 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001839 stopFreezingScreen(false, true);
1840 if (DEBUG_ORIENTATION) Slog.i(TAG,
1841 "Setting mOrientationChangeComplete=true because wtoken " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001842 + " numInteresting=" + mNumInterestingWindows + " numDrawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001843 // This will set mOrientationChangeComplete and cause a pass through layout.
1844 setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001845 "checkAppWindowsReadyToShow: freezingScreen");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001846 } else {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001847 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001848
1849 // We can now show all of the drawn windows!
lumark588a3e82018-07-20 18:53:54 +08001850 if (!getDisplayContent().mOpeningApps.contains(this) && canShowWindows()) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001851 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001852 }
1853 }
1854 }
1855
Matthew Ng5d23afa2017-06-21 16:16:24 -07001856 /**
Bryce Leed390deb2017-06-22 13:14:28 -07001857 * Returns whether the drawn window states of this {@link AppWindowToken} has considered every
1858 * child {@link WindowState}. A child is considered if it has been passed into
1859 * {@link #updateDrawnWindowStates(WindowState)} after being added. This is used to determine
1860 * whether states, such as {@code allDrawn}, can be set, which relies on state variables such as
1861 * {@code mNumInterestingWindows}, which depend on all {@link WindowState}s being considered.
1862 *
1863 * @return {@code true} If all children have been considered, {@code false}.
1864 */
1865 private boolean allDrawnStatesConsidered() {
Bryce Lee6311c4b2017-07-06 14:09:29 -07001866 for (int i = mChildren.size() - 1; i >= 0; --i) {
1867 final WindowState child = mChildren.get(i);
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001868 if (child.mightAffectAllDrawn() && !child.getDrawnStateEvaluated()) {
Bryce Leed390deb2017-06-22 13:14:28 -07001869 return false;
1870 }
1871 }
1872 return true;
1873 }
1874
1875 /**
Matthew Ng5d23afa2017-06-21 16:16:24 -07001876 * Determines if the token has finished drawing. This should only be called from
1877 * {@link DisplayContent#applySurfaceChangesTransaction}
1878 */
Matthew Ng498c71d2017-04-18 13:55:45 -07001879 void updateAllDrawn() {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001880 if (!allDrawn) {
Matthew Ng498c71d2017-04-18 13:55:45 -07001881 // Number of drawn windows can be less when a window is being relaunched, wait for
Bryce Leed390deb2017-06-22 13:14:28 -07001882 // all windows to be launched and drawn for this token be considered all drawn.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001883 final int numInteresting = mNumInterestingWindows;
Bryce Leed390deb2017-06-22 13:14:28 -07001884
1885 // We must make sure that all present children have been considered (determined by
1886 // {@link #allDrawnStatesConsidered}) before evaluating whether everything has been
1887 // drawn.
1888 if (numInteresting > 0 && allDrawnStatesConsidered()
1889 && mNumDrawnWindows >= numInteresting && !isRelaunching()) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001890 if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawn: " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001891 + " interesting=" + numInteresting + " drawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001892 allDrawn = true;
1893 // Force an additional layout pass where
1894 // WindowStateAnimator#commitFinishDrawingLocked() will call performShowLocked().
Matthew Ng498c71d2017-04-18 13:55:45 -07001895 if (mDisplayContent != null) {
1896 mDisplayContent.setLayoutNeeded();
1897 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001898 mWmService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
Robert Carrecc06b32017-04-18 14:25:10 -07001899
Winson Chunge7ba6862017-05-24 12:13:33 -07001900 // Notify the pinned stack upon all windows drawn. If there was an animation in
1901 // progress then this signal will resume that animation.
Wale Ogunwale61911492017-10-11 08:50:50 -07001902 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
Winson Chunge7ba6862017-05-24 12:13:33 -07001903 if (pinnedStack != null) {
1904 pinnedStack.onAllWindowsDrawn();
Robert Carrecc06b32017-04-18 14:25:10 -07001905 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001906 }
1907 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001908 }
1909
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001910 boolean keyDispatchingTimedOut(String reason, int windowPid) {
1911 return mActivityRecord != null && mActivityRecord.keyDispatchingTimedOut(reason, windowPid);
1912 }
1913
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001914 /**
1915 * Updated this app token tracking states for interesting and drawn windows based on the window.
1916 *
1917 * @return Returns true if the input window is considered interesting and drawn while all the
1918 * windows in this app token where not considered drawn as of the last pass.
1919 */
1920 boolean updateDrawnWindowStates(WindowState w) {
Bryce Leed390deb2017-06-22 13:14:28 -07001921 w.setDrawnStateEvaluated(true /*evaluated*/);
1922
Jorim Jaggie4b0f282017-05-17 15:10:29 +02001923 if (DEBUG_STARTING_WINDOW_VERBOSE && w == startingWindow) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001924 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + w.isOnScreen()
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001925 + " allDrawn=" + allDrawn + " freezingScreen=" + mFreezingScreen);
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001926 }
1927
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001928 if (allDrawn && !mFreezingScreen) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001929 return false;
1930 }
1931
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001932 if (mLastTransactionSequence != mWmService.mTransactionSequence) {
1933 mLastTransactionSequence = mWmService.mTransactionSequence;
Matthew Ng53e66b22018-01-12 17:13:13 -08001934 mNumDrawnWindows = 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001935 startingDisplayed = false;
Matthew Ng53e66b22018-01-12 17:13:13 -08001936
1937 // There is the main base application window, even if it is exiting, wait for it
1938 mNumInterestingWindows = findMainWindow(false /* includeStartingApp */) != null ? 1 : 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001939 }
1940
1941 final WindowStateAnimator winAnimator = w.mWinAnimator;
1942
1943 boolean isInterestingAndDrawn = false;
1944
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001945 if (!allDrawn && w.mightAffectAllDrawn()) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001946 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
1947 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001948 + ", isAnimationSet=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001949 if (!w.isDrawnLw()) {
1950 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController
chaviw15ad49f2019-04-24 15:05:39 -07001951 + " pv=" + w.isVisibleByPolicy()
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001952 + " mDrawState=" + winAnimator.drawStateToString()
1953 + " ph=" + w.isParentWindowHidden() + " th=" + hiddenRequested
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001954 + " a=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001955 }
1956 }
1957
1958 if (w != startingWindow) {
1959 if (w.isInteresting()) {
Matthew Ng53e66b22018-01-12 17:13:13 -08001960 // Add non-main window as interesting since the main app has already been added
1961 if (findMainWindow(false /* includeStartingApp */) != w) {
1962 mNumInterestingWindows++;
1963 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001964 if (w.isDrawnLw()) {
1965 mNumDrawnWindows++;
1966
1967 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, "tokenMayBeDrawn: "
1968 + this + " w=" + w + " numInteresting=" + mNumInterestingWindows
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001969 + " freezingScreen=" + mFreezingScreen
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001970 + " mAppFreezing=" + w.mAppFreezing);
1971
1972 isInterestingAndDrawn = true;
1973 }
1974 }
1975 } else if (w.isDrawnLw()) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001976 if (mActivityRecord != null) {
1977 mActivityRecord.onStartingWindowDrawn(SystemClock.uptimeMillis());
Jorim Jaggi3878ca32017-02-02 17:13:05 -08001978 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001979 startingDisplayed = true;
1980 }
1981 }
1982
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001983 return isInterestingAndDrawn;
1984 }
1985
Adrian Roos23df3a32018-03-15 15:41:13 +01001986 void layoutLetterbox(WindowState winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001987 final WindowState w = findMainWindow();
Adrian Roosf93b6d22018-03-21 13:48:26 +01001988 if (w == null || winHint != null && w != winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001989 return;
1990 }
Jorim Jaggia32da382018-03-28 18:01:22 +02001991 final boolean surfaceReady = w.isDrawnLw() // Regular case
Adrian Roosf93b6d22018-03-21 13:48:26 +01001992 || w.mWinAnimator.mSurfaceDestroyDeferred // The preserved surface is still ready.
1993 || w.isDragResizeChanged(); // Waiting for relayoutWindow to call preserveSurface.
Jorim Jaggi4981f152019-03-26 18:58:45 +01001994 final boolean needsLetterbox = surfaceReady && w.isLetterboxedAppWindow() && fillsParent();
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001995 if (needsLetterbox) {
1996 if (mLetterbox == null) {
1997 mLetterbox = new Letterbox(() -> makeChildSurface(null));
Riddle Hsu192fe762019-01-15 23:41:57 +08001998 mLetterbox.attachInput(w);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001999 }
Adrian Roos7af9d972018-11-30 15:26:27 +01002000 getPosition(mTmpPoint);
Evan Rosky67c15642019-04-24 13:17:28 -07002001 // Get the bounds of the "space-to-fill". In multi-window mode, the task-level
2002 // represents this. In fullscreen-mode, the stack does (since the orientation letterbox
2003 // is also applied to the task).
2004 Rect spaceToFill = (inMultiWindowMode() || getStack() == null)
2005 ? getTask().getDisplayedBounds() : getStack().getDisplayedBounds();
Evan Rosky4fb1e912019-03-06 13:54:43 -08002006 mLetterbox.layout(spaceToFill, w.getFrameLw(), mTmpPoint);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002007 } else if (mLetterbox != null) {
Adrian Roos23df3a32018-03-15 15:41:13 +01002008 mLetterbox.hide();
2009 }
2010 }
2011
2012 void updateLetterboxSurface(WindowState winHint) {
2013 final WindowState w = findMainWindow();
2014 if (w != winHint && winHint != null && w != null) {
2015 return;
2016 }
2017 layoutLetterbox(winHint);
2018 if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) {
Tiger Huanged6794e2019-05-07 20:07:59 +08002019 mLetterbox.applySurfaceChanges(getPendingTransaction());
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002020 }
2021 }
2022
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07002023 @Override
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002024 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002025 // For legacy reasons we process the TaskStack.mExitingAppTokens first in DisplayContent
2026 // before the non-exiting app tokens. So, we skip the exiting app tokens here.
2027 // TODO: Investigate if we need to continue to do this or if we can just process them
2028 // in-order.
2029 if (mIsExiting && !waitingForReplacement()) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002030 return false;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002031 }
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002032 return forAllWindowsUnchecked(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002033 }
2034
lumark588a3e82018-07-20 18:53:54 +08002035 @Override
2036 void forAllAppWindows(Consumer<AppWindowToken> callback) {
2037 callback.accept(this);
2038 }
2039
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002040 boolean forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback,
2041 boolean traverseTopToBottom) {
2042 return super.forAllWindows(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002043 }
2044
2045 @Override
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002046 AppWindowToken asAppWindowToken() {
2047 // I am an app window token!
2048 return this;
2049 }
2050
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002051 boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
2052 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
2053 IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
2054 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
2055 // If the display is frozen, we won't do anything until the actual window is
2056 // displayed so there is no reason to put in the starting window.
2057 if (!okToDisplay()) {
2058 return false;
2059 }
2060
chaviwa8f07a72019-05-01 16:25:39 -07002061 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002062 return false;
2063 }
2064
2065 final WindowState mainWin = findMainWindow();
2066 if (mainWin != null && mainWin.mWinAnimator.getShown()) {
2067 // App already has a visible window...why would you want a starting window?
2068 return false;
2069 }
2070
2071 final ActivityManager.TaskSnapshot snapshot =
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002072 mWmService.mTaskSnapshotController.getSnapshot(
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002073 getTask().mTaskId, getTask().mUserId,
2074 false /* restoreFromDisk */, false /* reducedResolution */);
2075 final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
2076 allowTaskSnapshot, activityCreated, fromRecents, snapshot);
2077
2078 if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
2079 return createSnapshot(snapshot);
2080 }
2081
2082 // If this is a translucent window, then don't show a starting window -- the current
2083 // effect (a full-screen opaque starting window that fades away to the real contents
2084 // when it is ready) does not work for this.
2085 if (DEBUG_STARTING_WINDOW) {
2086 Slog.v(TAG, "Checking theme of starting window: 0x" + Integer.toHexString(theme));
2087 }
2088 if (theme != 0) {
2089 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
2090 com.android.internal.R.styleable.Window,
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002091 mWmService.mCurrentUserId);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002092 if (ent == null) {
2093 // Whoops! App doesn't exist. Um. Okay. We'll just pretend like we didn't
2094 // see that.
2095 return false;
2096 }
2097 final boolean windowIsTranslucent = ent.array.getBoolean(
2098 com.android.internal.R.styleable.Window_windowIsTranslucent, false);
2099 final boolean windowIsFloating = ent.array.getBoolean(
2100 com.android.internal.R.styleable.Window_windowIsFloating, false);
2101 final boolean windowShowWallpaper = ent.array.getBoolean(
2102 com.android.internal.R.styleable.Window_windowShowWallpaper, false);
2103 final boolean windowDisableStarting = ent.array.getBoolean(
2104 com.android.internal.R.styleable.Window_windowDisablePreview, false);
2105 if (DEBUG_STARTING_WINDOW) {
2106 Slog.v(TAG, "Translucent=" + windowIsTranslucent
2107 + " Floating=" + windowIsFloating
2108 + " ShowWallpaper=" + windowShowWallpaper);
2109 }
2110 if (windowIsTranslucent) {
2111 return false;
2112 }
2113 if (windowIsFloating || windowDisableStarting) {
2114 return false;
2115 }
2116 if (windowShowWallpaper) {
2117 if (getDisplayContent().mWallpaperController
2118 .getWallpaperTarget() == null) {
2119 // If this theme is requesting a wallpaper, and the wallpaper
2120 // is not currently visible, then this effectively serves as
2121 // an opaque window and our starting window transition animation
2122 // can still work. We just need to make sure the starting window
2123 // is also showing the wallpaper.
2124 windowFlags |= FLAG_SHOW_WALLPAPER;
2125 } else {
2126 return false;
2127 }
2128 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002129 }
Yunfan Chen8a8c0ed2018-12-18 16:46:32 -08002130
2131 if (transferStartingWindow(transferFrom)) {
2132 return true;
2133 }
2134
2135 // There is no existing starting window, and we don't want to create a splash screen, so
2136 // that's it!
2137 if (type != STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
2138 return false;
2139 }
2140
2141 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SplashScreenStartingData");
chaviwa8f07a72019-05-01 16:25:39 -07002142 mStartingData = new SplashScreenStartingData(mWmService, pkg,
Yunfan Chen8a8c0ed2018-12-18 16:46:32 -08002143 theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
2144 getMergedOverrideConfiguration());
2145 scheduleAddStartingWindow();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002146 return true;
2147 }
2148
2149
2150 private boolean createSnapshot(ActivityManager.TaskSnapshot snapshot) {
2151 if (snapshot == null) {
2152 return false;
2153 }
2154
2155 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SnapshotStartingData");
chaviwa8f07a72019-05-01 16:25:39 -07002156 mStartingData = new SnapshotStartingData(mWmService, snapshot);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002157 scheduleAddStartingWindow();
2158 return true;
2159 }
2160
2161 void scheduleAddStartingWindow() {
2162 // Note: we really want to do sendMessageAtFrontOfQueue() because we
2163 // want to process the message ASAP, before any other queued
2164 // messages.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002165 if (!mWmService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002166 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING");
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002167 mWmService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002168 }
2169 }
2170
2171 private final Runnable mAddStartingWindow = new Runnable() {
2172
2173 @Override
2174 public void run() {
chaviwa8f07a72019-05-01 16:25:39 -07002175 // Can be accessed without holding the global lock
2176 final StartingData startingData;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002177 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002178 // There can only be one adding request, silly caller!
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002179 mWmService.mAnimationHandler.removeCallbacks(this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002180
chaviwa8f07a72019-05-01 16:25:39 -07002181 if (mStartingData == null) {
2182 // Animation has been canceled... do nothing.
2183 if (DEBUG_STARTING_WINDOW) {
2184 Slog.v(TAG, "startingData was nulled out before handling"
2185 + " mAddStartingWindow: " + AppWindowToken.this);
2186 }
2187 return;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002188 }
chaviwa8f07a72019-05-01 16:25:39 -07002189 startingData = mStartingData;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002190 }
2191
2192 if (DEBUG_STARTING_WINDOW) {
2193 Slog.v(TAG, "Add starting " + this + ": startingData=" + startingData);
2194 }
2195
2196 WindowManagerPolicy.StartingSurface surface = null;
2197 try {
2198 surface = startingData.createStartingSurface(AppWindowToken.this);
2199 } catch (Exception e) {
2200 Slog.w(TAG, "Exception when adding starting window", e);
2201 }
2202 if (surface != null) {
2203 boolean abort = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002204 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002205 // If the window was successfully added, then
2206 // we need to remove it.
chaviwa8f07a72019-05-01 16:25:39 -07002207 if (removed || mStartingData == null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002208 if (DEBUG_STARTING_WINDOW) {
2209 Slog.v(TAG, "Aborted starting " + AppWindowToken.this
chaviwa8f07a72019-05-01 16:25:39 -07002210 + ": removed=" + removed + " startingData=" + mStartingData);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002211 }
2212 startingWindow = null;
chaviwa8f07a72019-05-01 16:25:39 -07002213 mStartingData = null;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002214 abort = true;
2215 } else {
2216 startingSurface = surface;
2217 }
2218 if (DEBUG_STARTING_WINDOW && !abort) {
chaviwa8f07a72019-05-01 16:25:39 -07002219 Slog.v(TAG,
2220 "Added starting " + AppWindowToken.this + ": startingWindow="
2221 + startingWindow + " startingView=" + startingSurface);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002222 }
2223 }
2224 if (abort) {
2225 surface.remove();
2226 }
2227 } else if (DEBUG_STARTING_WINDOW) {
2228 Slog.v(TAG, "Surface returned was null: " + AppWindowToken.this);
2229 }
2230 }
2231 };
2232
2233 private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
2234 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents,
2235 ActivityManager.TaskSnapshot snapshot) {
2236 if (getDisplayContent().mAppTransition.getAppTransition()
2237 == TRANSIT_DOCK_TASK_FROM_RECENTS) {
2238 // TODO(b/34099271): Remove this statement to add back the starting window and figure
2239 // out why it causes flickering, the starting window appears over the thumbnail while
2240 // the docked from recents transition occurs
2241 return STARTING_WINDOW_TYPE_NONE;
2242 } else if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
2243 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2244 } else if (taskSwitch && allowTaskSnapshot) {
Kevin716a9db2018-12-18 16:53:39 -08002245 if (mWmService.mLowRamTaskSnapshotsAndRecents) {
Kevin58b47f12018-12-17 14:09:01 -08002246 // For low RAM devices, we use the splash screen starting window instead of the
2247 // task snapshot starting window.
2248 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2249 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002250 return snapshot == null ? STARTING_WINDOW_TYPE_NONE
2251 : snapshotOrientationSameAsTask(snapshot) || fromRecents
2252 ? STARTING_WINDOW_TYPE_SNAPSHOT : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2253 } else {
2254 return STARTING_WINDOW_TYPE_NONE;
2255 }
2256 }
2257
2258
2259 private boolean snapshotOrientationSameAsTask(ActivityManager.TaskSnapshot snapshot) {
2260 if (snapshot == null) {
2261 return false;
2262 }
2263 return getTask().getConfiguration().orientation == snapshot.getOrientation();
2264 }
2265
2266 void removeStartingWindow() {
2267 if (startingWindow == null) {
chaviwa8f07a72019-05-01 16:25:39 -07002268 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002269 // Starting window has not been added yet, but it is scheduled to be added.
2270 // Go ahead and cancel the request.
2271 if (DEBUG_STARTING_WINDOW) {
2272 Slog.v(TAG_WM, "Clearing startingData for token=" + this);
2273 }
chaviwa8f07a72019-05-01 16:25:39 -07002274 mStartingData = null;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002275 }
2276 return;
2277 }
2278
2279 final WindowManagerPolicy.StartingSurface surface;
chaviwa8f07a72019-05-01 16:25:39 -07002280 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002281 surface = startingSurface;
chaviwa8f07a72019-05-01 16:25:39 -07002282 mStartingData = null;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002283 startingSurface = null;
2284 startingWindow = null;
2285 startingDisplayed = false;
2286 if (surface == null) {
2287 if (DEBUG_STARTING_WINDOW) {
2288 Slog.v(TAG_WM, "startingWindow was set but startingSurface==null, couldn't "
2289 + "remove");
2290 }
2291 return;
2292 }
2293 } else {
2294 if (DEBUG_STARTING_WINDOW) {
2295 Slog.v(TAG_WM, "Tried to remove starting window but startingWindow was null:"
2296 + this);
2297 }
2298 return;
2299 }
2300
2301 if (DEBUG_STARTING_WINDOW) {
2302 Slog.v(TAG_WM, "Schedule remove starting " + this
2303 + " startingWindow=" + startingWindow
2304 + " startingView=" + startingSurface
2305 + " Callers=" + Debug.getCallers(5));
2306 }
2307
2308 // Use the same thread to remove the window as we used to add it, as otherwise we end up
2309 // with things in the view hierarchy being called from different threads.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002310 mWmService.mAnimationHandler.post(() -> {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002311 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Removing startingView=" + surface);
2312 try {
2313 surface.remove();
2314 } catch (Exception e) {
2315 Slog.w(TAG_WM, "Exception when removing starting window", e);
2316 }
2317 });
2318 }
2319
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002320 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -07002321 boolean fillsParent() {
2322 return mFillsParent;
2323 }
2324
2325 void setFillsParent(boolean fillsParent) {
2326 mFillsParent = fillsParent;
2327 }
2328
Jorim Jaggife762342016-10-13 14:33:27 +02002329 boolean containsDismissKeyguardWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002330 // Window state is transient during relaunch. We are not guaranteed to be frozen during the
2331 // entirety of the relaunch.
2332 if (isRelaunching()) {
2333 return mLastContainsDismissKeyguardWindow;
2334 }
2335
Jorim Jaggife762342016-10-13 14:33:27 +02002336 for (int i = mChildren.size() - 1; i >= 0; i--) {
2337 if ((mChildren.get(i).mAttrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
2338 return true;
2339 }
2340 }
2341 return false;
2342 }
2343
2344 boolean containsShowWhenLockedWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002345 // When we are relaunching, it is possible for us to be unfrozen before our previous
2346 // windows have been added back. Using the cached value ensures that our previous
2347 // showWhenLocked preference is honored until relaunching is complete.
2348 if (isRelaunching()) {
2349 return mLastContainsShowWhenLockedWindow;
2350 }
2351
Jorim Jaggife762342016-10-13 14:33:27 +02002352 for (int i = mChildren.size() - 1; i >= 0; i--) {
2353 if ((mChildren.get(i).mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
2354 return true;
2355 }
2356 }
Bryce Lee081554b2017-05-25 07:52:12 -07002357
Jorim Jaggife762342016-10-13 14:33:27 +02002358 return false;
2359 }
2360
2361 void checkKeyguardFlagsChanged() {
2362 final boolean containsDismissKeyguard = containsDismissKeyguardWindow();
2363 final boolean containsShowWhenLocked = containsShowWhenLockedWindow();
2364 if (containsDismissKeyguard != mLastContainsDismissKeyguardWindow
2365 || containsShowWhenLocked != mLastContainsShowWhenLockedWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002366 mWmService.notifyKeyguardFlagsChanged(null /* callback */,
lumark588a3e82018-07-20 18:53:54 +08002367 getDisplayContent().getDisplayId());
Jorim Jaggife762342016-10-13 14:33:27 +02002368 }
2369 mLastContainsDismissKeyguardWindow = containsDismissKeyguard;
2370 mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
2371 }
2372
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002373 WindowState getImeTargetBelowWindow(WindowState w) {
2374 final int index = mChildren.indexOf(w);
2375 if (index > 0) {
2376 final WindowState target = mChildren.get(index - 1);
2377 if (target.canBeImeTarget()) {
2378 return target;
2379 }
2380 }
2381 return null;
2382 }
2383
2384 WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
2385 WindowState candidate = null;
2386 for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
2387 final WindowState w = mChildren.get(i);
2388 if (w.mRemoved) {
2389 continue;
2390 }
Jorim Jaggi35d328a2018-08-14 17:00:20 +02002391 if (candidate == null) {
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002392 candidate = w;
2393 }
2394 }
2395 return candidate;
2396 }
2397
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002398 /**
2399 * See {@link Activity#setDisablePreviewScreenshots}.
2400 */
2401 void setDisablePreviewScreenshots(boolean disable) {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002402 mDisablePreviewScreenshots = disable;
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002403 }
2404
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002405 /**
Riddle Hsu4bb06be2019-07-02 01:03:07 +08002406 * Sets whether the current launch can turn the screen on.
2407 * @see #currentLaunchCanTurnScreenOn()
chaviwd3bf08d2017-08-01 17:24:59 -07002408 */
Riddle Hsu4bb06be2019-07-02 01:03:07 +08002409 void setCurrentLaunchCanTurnScreenOn(boolean currentLaunchCanTurnScreenOn) {
2410 mCurrentLaunchCanTurnScreenOn = currentLaunchCanTurnScreenOn;
chaviwd3bf08d2017-08-01 17:24:59 -07002411 }
2412
2413 /**
2414 * Indicates whether the current launch can turn the screen on. This is to prevent multiple
2415 * relayouts from turning the screen back on. The screen should only turn on at most
2416 * once per activity resume.
Riddle Hsu4bb06be2019-07-02 01:03:07 +08002417 * <p>
2418 * Note this flag is only meaningful when {@link WindowManager.LayoutParams#FLAG_TURN_SCREEN_ON}
2419 * or {@link ActivityRecord#canTurnScreenOn} is set.
chaviwd3bf08d2017-08-01 17:24:59 -07002420 *
Riddle Hsu4bb06be2019-07-02 01:03:07 +08002421 * @return {@code true} if the activity is ready to turn on the screen.
chaviwd3bf08d2017-08-01 17:24:59 -07002422 */
Riddle Hsu4bb06be2019-07-02 01:03:07 +08002423 boolean currentLaunchCanTurnScreenOn() {
2424 return mCurrentLaunchCanTurnScreenOn;
chaviwd3bf08d2017-08-01 17:24:59 -07002425 }
2426
2427 /**
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002428 * Retrieves whether we'd like to generate a snapshot that's based solely on the theme. This is
2429 * the case when preview screenshots are disabled {@link #setDisablePreviewScreenshots} or when
2430 * we can't take a snapshot for other reasons, for example, if we have a secure window.
2431 *
2432 * @return True if we need to generate an app theme snapshot, false if we'd like to take a real
2433 * screenshot.
2434 */
2435 boolean shouldUseAppThemeSnapshot() {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002436 return mDisablePreviewScreenshots || forAllWindows(w -> (w.mAttrs.flags & FLAG_SECURE) != 0,
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002437 true /* topToBottom */);
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002438 }
2439
Jorim Jaggibe418292018-03-26 16:14:12 +02002440 SurfaceControl getAppAnimationLayer() {
Jorim Jaggi391790622018-04-18 15:30:44 +02002441 return getAppAnimationLayer(isActivityTypeHome() ? ANIMATION_LAYER_HOME
2442 : needsZBoost() ? ANIMATION_LAYER_BOOSTED
2443 : ANIMATION_LAYER_STANDARD);
Jorim Jaggibe418292018-03-26 16:14:12 +02002444 }
2445
chaviw23ee71c2017-12-18 11:29:41 -08002446 @Override
Jorim Jaggi596a1992017-12-29 14:48:02 +01002447 public SurfaceControl getAnimationLeashParent() {
Robert Carrb9506032018-02-13 13:54:00 -08002448 // All normal app transitions take place in an animation layer which is below the pinned
2449 // stack but may be above the parent stacks of the given animating apps.
2450 // For transitions in the pinned stack (menu activity) we just let them occur as a child
2451 // of the pinned stack.
2452 if (!inPinnedWindowingMode()) {
2453 return getAppAnimationLayer();
2454 } else {
2455 return getStack().getSurfaceControl();
2456 }
chaviw23ee71c2017-12-18 11:29:41 -08002457 }
2458
lumarkb5a78b32019-04-25 20:31:30 +08002459
2460 @VisibleForTesting
2461 boolean shouldAnimate(int transit) {
Jorim Jaggic6976f02018-04-18 16:31:07 +02002462 final boolean isSplitScreenPrimary =
2463 getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
2464 final boolean allowSplitScreenPrimaryAnimation = transit != TRANSIT_WALLPAPER_OPEN;
2465
lumarkb5a78b32019-04-25 20:31:30 +08002466 // Don't animate while the task runs recents animation but only if we are in the mode
2467 // where we cancel with deferred screenshot, which means that the controller has
2468 // transformed the task.
lumark54284462019-03-05 20:44:27 +08002469 final RecentsAnimationController controller = mWmService.getRecentsAnimationController();
lumarkb5a78b32019-04-25 20:31:30 +08002470 if (controller != null && controller.isAnimatingTask(getTask())
2471 && controller.shouldCancelWithDeferredScreenshot()) {
lumark54284462019-03-05 20:44:27 +08002472 return false;
2473 }
2474
Jorim Jaggic6976f02018-04-18 16:31:07 +02002475 // We animate always if it's not split screen primary, and only some special cases in split
2476 // screen primary because it causes issues with stack clipping when we run an un-minimize
2477 // animation at the same time.
2478 return !isSplitScreenPrimary || allowSplitScreenPrimaryAnimation;
2479 }
2480
Vishnu Naira2977262018-07-26 13:31:26 -07002481 /**
2482 * Creates a layer to apply crop to an animation.
2483 */
2484 private SurfaceControl createAnimationBoundsLayer(Transaction t) {
2485 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.i(TAG, "Creating animation bounds layer");
2486 final SurfaceControl.Builder builder = makeAnimationLeash()
2487 .setParent(getAnimationLeashParent())
Vishnu Naire86bd982018-11-28 13:23:17 -08002488 .setName(getSurfaceControl() + " - animation-bounds");
Vishnu Naira2977262018-07-26 13:31:26 -07002489 final SurfaceControl boundsLayer = builder.build();
2490 t.show(boundsLayer);
2491 return boundsLayer;
2492 }
2493
Evan Roskyed6767f2018-10-26 17:21:06 -07002494 @Override
2495 Rect getDisplayedBounds() {
2496 final Task task = getTask();
2497 if (task != null) {
2498 final Rect overrideDisplayedBounds = task.getOverrideDisplayedBounds();
2499 if (!overrideDisplayedBounds.isEmpty()) {
2500 return overrideDisplayedBounds;
2501 }
2502 }
2503 return getBounds();
2504 }
2505
Evan Rosky641daea2019-04-24 14:45:24 -07002506 @VisibleForTesting
2507 Rect getAnimationBounds(int appStackClipMode) {
2508 if (appStackClipMode == STACK_CLIP_BEFORE_ANIM && getStack() != null) {
2509 // Using the stack bounds here effectively applies the clipping before animation.
2510 return getStack().getBounds();
2511 }
2512 // Use task-bounds if available so that activity-level letterbox (maxAspectRatio) is
2513 // included in the animation.
2514 return getTask() != null ? getTask().getBounds() : getBounds();
2515 }
2516
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002517 boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter,
2518 boolean isVoiceInteraction) {
2519
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002520 if (mWmService.mDisableTransitionAnimation || !shouldAnimate(transit)) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002521 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
Jorim Jaggic6976f02018-04-18 16:31:07 +02002522 Slog.v(TAG_WM, "applyAnimation: transition animation is disabled or skipped."
2523 + " atoken=" + this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002524 }
2525 cancelAnimation();
2526 return false;
2527 }
2528
2529 // Only apply an animation if the display isn't frozen. If it is frozen, there is no reason
2530 // to animate and it can cause strange artifacts when we unfreeze the display if some
2531 // different animation is running.
2532 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#applyAnimationLocked");
2533 if (okToAnimate()) {
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002534 final AnimationAdapter adapter;
Evan Rosky2289ba12018-11-19 18:28:18 -08002535 AnimationAdapter thumbnailAdapter = null;
Evan Rosky4fb1e912019-03-06 13:54:43 -08002536
Evan Rosky641daea2019-04-24 14:45:24 -07002537 final int appStackClipMode =
2538 getDisplayContent().mAppTransition.getAppStackClipMode();
2539
2540 // Separate position and size for use in animators.
2541 mTmpRect.set(getAnimationBounds(appStackClipMode));
Evan Rosky4fb1e912019-03-06 13:54:43 -08002542 mTmpPoint.set(mTmpRect.left, mTmpRect.top);
2543 mTmpRect.offsetTo(0, 0);
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002544
Evan Roskyec9488c2019-03-01 19:32:12 -08002545 final boolean isChanging = AppTransition.isChangeTransit(transit) && enter
2546 && getDisplayContent().mChangingApps.contains(this);
Evan Rosky2289ba12018-11-19 18:28:18 -08002547
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002548 // Delaying animation start isn't compatible with remote animations at all.
lumark588a3e82018-07-20 18:53:54 +08002549 if (getDisplayContent().mAppTransition.getRemoteAnimationController() != null
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002550 && !mSurfaceAnimator.isAnimationStartDelayed()) {
Evan Rosky2289ba12018-11-19 18:28:18 -08002551 RemoteAnimationRecord adapters =
2552 getDisplayContent().mAppTransition.getRemoteAnimationController()
2553 .createRemoteAnimationRecord(this, mTmpPoint, mTmpRect,
2554 (isChanging ? mTransitStartRect : null));
2555 adapter = adapters.mAdapter;
2556 thumbnailAdapter = adapters.mThumbnailAdapter;
2557 } else if (isChanging) {
Evan Roskycf76bed2019-01-15 10:33:58 -08002558 final float durationScale = mWmService.getTransitionAnimationScaleLocked();
Evan Rosky2289ba12018-11-19 18:28:18 -08002559 mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y);
2560 adapter = new LocalAnimationAdapter(
2561 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
Evan Roskycf76bed2019-01-15 10:33:58 -08002562 getDisplayContent().getDisplayInfo(), durationScale,
Evan Rosky2289ba12018-11-19 18:28:18 -08002563 true /* isAppAnimation */, false /* isThumbnail */),
2564 mWmService.mSurfaceAnimationRunner);
Evan Rosky966759f2019-01-15 10:33:58 -08002565 if (mThumbnail != null) {
2566 thumbnailAdapter = new LocalAnimationAdapter(
2567 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
Evan Roskycf76bed2019-01-15 10:33:58 -08002568 getDisplayContent().getDisplayInfo(), durationScale,
Evan Rosky966759f2019-01-15 10:33:58 -08002569 true /* isAppAnimation */, true /* isThumbnail */),
2570 mWmService.mSurfaceAnimationRunner);
2571 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002572 mTransit = transit;
2573 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002574 } else {
Vishnu Naira2977262018-07-26 13:31:26 -07002575 mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM);
2576
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002577 final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
2578 if (a != null) {
Lucas Dupin95acf432019-04-29 17:55:38 -07002579 // Only apply corner radius to animation if we're not in multi window mode.
2580 // We don't want rounded corners when in pip or split screen.
2581 final float windowCornerRadius = !inMultiWindowMode()
2582 ? getDisplayContent().getWindowCornerRadius()
2583 : 0;
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002584 adapter = new LocalAnimationAdapter(
2585 new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
lumark588a3e82018-07-20 18:53:54 +08002586 getDisplayContent().mAppTransition.canSkipFirstFrame(),
Vishnu Naira2977262018-07-26 13:31:26 -07002587 appStackClipMode,
Lucas Dupin3e1dc202018-12-02 15:14:20 -08002588 true /* isAppAnimation */,
Lucas Dupin95acf432019-04-29 17:55:38 -07002589 windowCornerRadius),
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002590 mWmService.mSurfaceAnimationRunner);
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002591 if (a.getZAdjustment() == Animation.ZORDER_TOP) {
2592 mNeedsZBoost = true;
2593 }
2594 mTransit = transit;
lumark588a3e82018-07-20 18:53:54 +08002595 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002596 } else {
2597 adapter = null;
chaviw23ee71c2017-12-18 11:29:41 -08002598 }
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002599 }
2600 if (adapter != null) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002601 startAnimation(getPendingTransaction(), adapter, !isVisible());
Jorim Jaggi82c17862018-02-21 17:50:18 +01002602 if (adapter.getShowWallpaper()) {
2603 mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2604 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002605 if (thumbnailAdapter != null) {
2606 mThumbnail.startAnimation(
2607 getPendingTransaction(), thumbnailAdapter, !isVisible());
2608 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002609 }
2610 } else {
2611 cancelAnimation();
2612 }
2613 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2614
2615 return isReallyAnimating();
2616 }
2617
2618 private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
2619 boolean isVoiceInteraction) {
2620 final DisplayContent displayContent = getTask().getDisplayContent();
2621 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2622 final int width = displayInfo.appWidth;
2623 final int height = displayInfo.appHeight;
2624 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG_WM,
2625 "applyAnimation: atoken=" + this);
2626
2627 // Determine the visible rect to calculate the thumbnail clip
2628 final WindowState win = findMainWindow();
2629 final Rect frame = new Rect(0, 0, width, height);
2630 final Rect displayFrame = new Rect(0, 0,
2631 displayInfo.logicalWidth, displayInfo.logicalHeight);
2632 final Rect insets = new Rect();
2633 final Rect stableInsets = new Rect();
2634 Rect surfaceInsets = null;
2635 final boolean freeform = win != null && win.inFreeformWindowingMode();
2636 if (win != null) {
2637 // Containing frame will usually cover the whole screen, including dialog windows.
2638 // For freeform workspace windows it will not cover the whole screen and it also
2639 // won't exactly match the final freeform window frame (e.g. when overlapping with
2640 // the status bar). In that case we need to use the final frame.
2641 if (freeform) {
chaviw492139a2018-07-16 16:07:35 -07002642 frame.set(win.getFrameLw());
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002643 } else if (win.isLetterboxedAppWindow()) {
2644 frame.set(getTask().getBounds());
Winson Chungc1674272018-02-21 10:15:17 -08002645 } else if (win.isDockedResizing()) {
2646 // If we are animating while docked resizing, then use the stack bounds as the
2647 // animation target (which will be different than the task bounds)
2648 frame.set(getTask().getParent().getBounds());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002649 } else {
chaviw553b0212018-07-12 13:37:01 -07002650 frame.set(win.getContainingFrame());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002651 }
2652 surfaceInsets = win.getAttrs().surfaceInsets;
Adrian Roos20e07892018-02-23 19:12:01 +01002653 // XXX(b/72757033): These are insets relative to the window frame, but we're really
2654 // interested in the insets relative to the frame we chose in the if-blocks above.
chaviw9c81e632018-07-31 11:17:52 -07002655 win.getContentInsets(insets);
2656 win.getStableInsets(stableInsets);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002657 }
2658
2659 if (mLaunchTaskBehind) {
2660 // Differentiate the two animations. This one which is briefly on the screen
2661 // gets the !enter animation, and the other activity which remains on the
2662 // screen gets the enter animation. Both appear in the mOpeningApps set.
2663 enter = false;
2664 }
2665 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "Loading animation for app transition."
2666 + " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter
2667 + " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets);
2668 final Configuration displayConfig = displayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08002669 final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002670 displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
2671 surfaceInsets, stableInsets, isVoiceInteraction, freeform, getTask().mTaskId);
2672 if (a != null) {
2673 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
2674 final int containingWidth = frame.width();
2675 final int containingHeight = frame.height();
2676 a.initialize(containingWidth, containingHeight, width, height);
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002677 a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002678 }
2679 return a;
2680 }
2681
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002682 @Override
Jorim Jaggi6de61012018-03-19 14:53:23 +01002683 public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
2684 return mAnimatingAppWindowTokenRegistry != null
2685 && mAnimatingAppWindowTokenRegistry.notifyAboutToFinish(
2686 this, endDeferFinishCallback);
2687 }
2688
2689 @Override
lumarkf6f34942019-04-29 16:56:50 +08002690 public void onAnimationLeashLost(Transaction t) {
2691 super.onAnimationLeashLost(t);
Vishnu Naira2977262018-07-26 13:31:26 -07002692 if (mAnimationBoundsLayer != null) {
Robert Carr71200f22019-02-05 09:44:53 -08002693 t.remove(mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002694 mAnimationBoundsLayer = null;
2695 }
2696
Jorim Jaggi6de61012018-03-19 14:53:23 +01002697 if (mAnimatingAppWindowTokenRegistry != null) {
2698 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
2699 }
2700 }
2701
2702 @Override
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002703 protected void setLayer(Transaction t, int layer) {
2704 if (!mSurfaceAnimator.hasLeash()) {
2705 t.setLayer(mSurfaceControl, layer);
2706 }
2707 }
2708
2709 @Override
2710 protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
2711 if (!mSurfaceAnimator.hasLeash()) {
2712 t.setRelativeLayer(mSurfaceControl, relativeTo, layer);
2713 }
2714 }
2715
2716 @Override
2717 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
2718 if (!mSurfaceAnimator.hasLeash()) {
Robert Carr10584fa2019-01-14 15:55:19 -08002719 t.reparent(mSurfaceControl, newParent);
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002720 }
2721 }
2722
2723 @Override
2724 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002725 // The leash is parented to the animation layer. We need to preserve the z-order by using
2726 // the prefix order index, but we boost if necessary.
Robert Carrb9506032018-02-13 13:54:00 -08002727 int layer = 0;
2728 if (!inPinnedWindowingMode()) {
2729 layer = getPrefixOrderIndex();
2730 } else {
2731 // Pinned stacks have animations take place within themselves rather than an animation
2732 // layer so we need to preserve the order relative to the stack (e.g. the order of our
2733 // task/parent).
2734 layer = getParent().getPrefixOrderIndex();
2735 }
2736
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002737 if (mNeedsZBoost) {
2738 layer += Z_BOOST_BASE;
2739 }
Jorim Jaggi9cd99132019-04-24 17:41:35 +02002740 if (!mNeedsAnimationBoundsLayer) {
2741 leash.setLayer(layer);
2742 }
Robert Carr2f8aa392018-01-31 14:46:51 -08002743
2744 final DisplayContent dc = getDisplayContent();
Jorim Jaggibe418292018-03-26 16:14:12 +02002745 dc.assignStackOrdering();
Evan Rosky2289ba12018-11-19 18:28:18 -08002746
2747 if (leash == mTransitChangeLeash) {
2748 // This is a temporary state so skip any animation notifications
2749 return;
2750 } else if (mTransitChangeLeash != null) {
2751 // unparent mTransitChangeLeash for clean-up
Evan Rosky25b56192019-02-06 16:10:56 -08002752 clearChangeLeash(t, false /* cancel */);
Evan Rosky2289ba12018-11-19 18:28:18 -08002753 }
2754
Jorim Jaggi6de61012018-03-19 14:53:23 +01002755 if (mAnimatingAppWindowTokenRegistry != null) {
2756 mAnimatingAppWindowTokenRegistry.notifyStarting(this);
2757 }
Vishnu Naira2977262018-07-26 13:31:26 -07002758
2759 // If the animation needs to be cropped then an animation bounds layer is created as a child
2760 // of the pinned stack or animation layer. The leash is then reparented to this new layer.
2761 if (mNeedsAnimationBoundsLayer) {
Evan Rosky7735d352019-03-18 17:27:27 -07002762 mTmpRect.setEmpty();
2763 final Task task = getTask();
2764 if (getDisplayContent().mAppTransitionController.isTransitWithinTask(
2765 getTransit(), task)) {
2766 task.getBounds(mTmpRect);
2767 } else {
2768 final TaskStack stack = getStack();
2769 if (stack == null) {
2770 return;
2771 }
2772 // Set clip rect to stack bounds.
2773 stack.getBounds(mTmpRect);
Vishnu Naira2977262018-07-26 13:31:26 -07002774 }
2775 mAnimationBoundsLayer = createAnimationBoundsLayer(t);
2776
Vishnu Naira2977262018-07-26 13:31:26 -07002777 // Crop to stack bounds.
2778 t.setWindowCrop(mAnimationBoundsLayer, mTmpRect);
Jorim Jaggi9cd99132019-04-24 17:41:35 +02002779 t.setLayer(mAnimationBoundsLayer, layer);
Vishnu Naira2977262018-07-26 13:31:26 -07002780
2781 // Reparent leash to animation bounds layer.
Robert Carr10584fa2019-01-14 15:55:19 -08002782 t.reparent(leash, mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002783 }
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002784 }
2785
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002786 /**
2787 * This must be called while inside a transaction.
2788 */
2789 void showAllWindowsLocked() {
2790 forAllWindows(windowState -> {
2791 if (DEBUG_VISIBILITY) Slog.v(TAG, "performing show on: " + windowState);
2792 windowState.performShowLocked();
2793 }, false /* traverseTopToBottom */);
Jorim Jaggia5e10572017-11-15 14:36:26 +01002794 }
2795
2796 @Override
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002797 protected void onAnimationFinished() {
2798 super.onAnimationFinished();
2799
Ian8b2822e2019-05-14 11:59:02 -07002800 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#onAnimationFinished");
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002801 mTransit = TRANSIT_UNSET;
2802 mTransitFlags = 0;
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002803 mNeedsZBoost = false;
Vishnu Naira2977262018-07-26 13:31:26 -07002804 mNeedsAnimationBoundsLayer = false;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002805
2806 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER,
2807 "AppWindowToken");
2808
Jorim Jaggi988f6682017-11-17 17:46:43 +01002809 clearThumbnail();
Jorim Jaggi752cd822018-03-29 16:29:18 +02002810 setClientHidden(isHidden() && hiddenRequested);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002811
lumarkff0ab692018-11-05 20:32:30 +08002812 getDisplayContent().computeImeTargetIfNeeded(this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002813
2814 if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + this
2815 + ": reportedVisible=" + reportedVisible
2816 + " okToDisplay=" + okToDisplay()
2817 + " okToAnimate=" + okToAnimate()
2818 + " startingDisplayed=" + startingDisplayed);
2819
Evan Rosky2289ba12018-11-19 18:28:18 -08002820 // clean up thumbnail window
2821 if (mThumbnail != null) {
2822 mThumbnail.destroy();
2823 mThumbnail = null;
2824 }
2825
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002826 // WindowState.onExitAnimationDone might modify the children list, so make a copy and then
2827 // traverse the copy.
2828 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
2829 children.forEach(WindowState::onExitAnimationDone);
2830
lumark588a3e82018-07-20 18:53:54 +08002831 getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002832 scheduleAnimation();
Jorim Jaggi9b5e3312019-03-01 18:08:00 +01002833
2834 mActivityRecord.onAnimationFinished();
Ian8b2822e2019-05-14 11:59:02 -07002835 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002836 }
2837
2838 @Override
2839 boolean isAppAnimating() {
2840 return isSelfAnimating();
2841 }
2842
2843 @Override
2844 boolean isSelfAnimating() {
2845 // If we are about to start a transition, we also need to be considered animating.
2846 return isWaitingForTransitionStart() || isReallyAnimating();
2847 }
2848
2849 /**
2850 * @return True if and only if we are actually running an animation. Note that
2851 * {@link #isSelfAnimating} also returns true if we are waiting for an animation to
2852 * start.
2853 */
2854 private boolean isReallyAnimating() {
2855 return super.isSelfAnimating();
2856 }
2857
Evan Rosky25b56192019-02-06 16:10:56 -08002858 /**
2859 * @param cancel {@code true} if clearing the leash due to cancelling instead of transferring
2860 * to another leash.
2861 */
2862 private void clearChangeLeash(Transaction t, boolean cancel) {
2863 if (mTransitChangeLeash == null) {
2864 return;
2865 }
2866 if (cancel) {
2867 clearThumbnail();
2868 SurfaceControl sc = getSurfaceControl();
2869 SurfaceControl parentSc = getParentSurfaceControl();
2870 // Don't reparent if surface is getting destroyed
2871 if (parentSc != null && sc != null) {
2872 t.reparent(sc, getParentSurfaceControl());
2873 }
2874 }
2875 t.hide(mTransitChangeLeash);
Evan Rosky08e20932019-05-14 10:54:07 -07002876 t.remove(mTransitChangeLeash);
Evan Rosky25b56192019-02-06 16:10:56 -08002877 mTransitChangeLeash = null;
2878 if (cancel) {
lumarkf6f34942019-04-29 16:56:50 +08002879 onAnimationLeashLost(t);
Evan Rosky25b56192019-02-06 16:10:56 -08002880 }
2881 }
2882
Jorim Jaggi988f6682017-11-17 17:46:43 +01002883 @Override
2884 void cancelAnimation() {
Evan Rosky2289ba12018-11-19 18:28:18 -08002885 cancelAnimationOnly();
Jorim Jaggi988f6682017-11-17 17:46:43 +01002886 clearThumbnail();
Evan Rosky25b56192019-02-06 16:10:56 -08002887 clearChangeLeash(getPendingTransaction(), true /* cancel */);
Evan Rosky2289ba12018-11-19 18:28:18 -08002888 }
2889
2890 /**
2891 * This only cancels the animation. It doesn't do other teardown like cleaning-up thumbnail
2892 * or interim leashes.
2893 * <p>
2894 * Used when canceling in preparation for starting a new animation.
2895 */
2896 void cancelAnimationOnly() {
2897 super.cancelAnimation();
Jorim Jaggi988f6682017-11-17 17:46:43 +01002898 }
2899
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002900 boolean isWaitingForTransitionStart() {
lumark588a3e82018-07-20 18:53:54 +08002901 return getDisplayContent().mAppTransition.isTransitionSet()
2902 && (getDisplayContent().mOpeningApps.contains(this)
Evan Rosky2289ba12018-11-19 18:28:18 -08002903 || getDisplayContent().mClosingApps.contains(this)
2904 || getDisplayContent().mChangingApps.contains(this));
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002905 }
2906
2907 public int getTransit() {
2908 return mTransit;
2909 }
2910
2911 int getTransitFlags() {
2912 return mTransitFlags;
2913 }
2914
Jorim Jaggi988f6682017-11-17 17:46:43 +01002915 void attachThumbnailAnimation() {
2916 if (!isReallyAnimating()) {
2917 return;
2918 }
2919 final int taskId = getTask().mTaskId;
2920 final GraphicBuffer thumbnailHeader =
lumark588a3e82018-07-20 18:53:54 +08002921 getDisplayContent().mAppTransition.getAppTransitionThumbnailHeader(taskId);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002922 if (thumbnailHeader == null) {
2923 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG, "No thumbnail header bitmap for: " + taskId);
2924 return;
2925 }
2926 clearThumbnail();
2927 mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnailHeader);
2928 mThumbnail.startAnimation(getPendingTransaction(), loadThumbnailAnimation(thumbnailHeader));
2929 }
2930
Tony Mak64b8d562017-12-28 17:44:02 +00002931 /**
2932 * Attaches a surface with a thumbnail for the
2933 * {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation.
2934 */
2935 void attachCrossProfileAppsThumbnailAnimation() {
2936 if (!isReallyAnimating()) {
2937 return;
2938 }
2939 clearThumbnail();
2940
2941 final WindowState win = findMainWindow();
2942 if (win == null) {
2943 return;
2944 }
chaviw492139a2018-07-16 16:07:35 -07002945 final Rect frame = win.getFrameLw();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002946 final int thumbnailDrawableRes = getTask().mUserId == mWmService.mCurrentUserId
Tony Mak64b8d562017-12-28 17:44:02 +00002947 ? R.drawable.ic_account_circle
Tony Makda4af232018-04-27 11:01:10 +01002948 : R.drawable.ic_corp_badge;
Tony Mak64b8d562017-12-28 17:44:02 +00002949 final GraphicBuffer thumbnail =
lumark588a3e82018-07-20 18:53:54 +08002950 getDisplayContent().mAppTransition
Tony Mak64b8d562017-12-28 17:44:02 +00002951 .createCrossProfileAppsThumbnail(thumbnailDrawableRes, frame);
2952 if (thumbnail == null) {
2953 return;
2954 }
2955 mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnail);
2956 final Animation animation =
lumark588a3e82018-07-20 18:53:54 +08002957 getDisplayContent().mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(
chaviw492139a2018-07-16 16:07:35 -07002958 win.getFrameLw());
Tony Mak64b8d562017-12-28 17:44:02 +00002959 mThumbnail.startAnimation(getPendingTransaction(), animation, new Point(frame.left,
2960 frame.top));
2961 }
2962
Jorim Jaggi988f6682017-11-17 17:46:43 +01002963 private Animation loadThumbnailAnimation(GraphicBuffer thumbnailHeader) {
2964 final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
2965
2966 // If this is a multi-window scenario, we use the windows frame as
2967 // destination of the thumbnail header animation. If this is a full screen
2968 // window scenario, we use the whole display as the target.
2969 WindowState win = findMainWindow();
2970 Rect appRect = win != null ? win.getContentFrameLw() :
2971 new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
chaviw9c81e632018-07-31 11:17:52 -07002972 final Rect insets = win != null ? win.getContentInsets() : null;
Jorim Jaggi988f6682017-11-17 17:46:43 +01002973 final Configuration displayConfig = mDisplayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08002974 return getDisplayContent().mAppTransition.createThumbnailAspectScaleAnimationLocked(
Jorim Jaggi988f6682017-11-17 17:46:43 +01002975 appRect, insets, thumbnailHeader, getTask().mTaskId, displayConfig.uiMode,
2976 displayConfig.orientation);
2977 }
2978
2979 private void clearThumbnail() {
2980 if (mThumbnail == null) {
2981 return;
2982 }
2983 mThumbnail.destroy();
2984 mThumbnail = null;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002985 }
2986
Jorim Jaggif84e2f62018-01-16 14:17:59 +01002987 void registerRemoteAnimations(RemoteAnimationDefinition definition) {
2988 mRemoteAnimationDefinition = definition;
2989 }
2990
2991 RemoteAnimationDefinition getRemoteAnimationDefinition() {
2992 return mRemoteAnimationDefinition;
2993 }
2994
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002995 @Override
2996 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
2997 super.dump(pw, prefix, dumpAll);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002998 if (appToken != null) {
Wale Ogunwale72919d22016-12-08 18:58:50 -08002999 pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003000 }
Winson Chung48b25652018-10-22 14:04:30 -07003001 pw.println(prefix + "component=" + mActivityComponent.flattenToShortString());
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08003002 pw.print(prefix); pw.print("task="); pw.println(getTask());
Wale Ogunwale51362492016-09-08 17:49:17 -07003003 pw.print(prefix); pw.print(" mFillsParent="); pw.print(mFillsParent);
3004 pw.print(" mOrientation="); pw.println(mOrientation);
Wale Ogunwale89973222017-04-23 18:39:45 -07003005 pw.println(prefix + "hiddenRequested=" + hiddenRequested + " mClientHidden=" + mClientHidden
3006 + ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "")
3007 + " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible);
Craig Mautner59431632012-04-04 11:56:44 -07003008 if (paused) {
3009 pw.print(prefix); pw.print("paused="); pw.println(paused);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003010 }
Wale Ogunwale9017ec02016-02-25 08:55:25 -08003011 if (mAppStopped) {
3012 pw.print(prefix); pw.print("mAppStopped="); pw.println(mAppStopped);
3013 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07003014 if (mNumInterestingWindows != 0 || mNumDrawnWindows != 0
Jorim Jaggib0fc8172017-11-23 17:04:08 +00003015 || allDrawn || mLastAllDrawn) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07003016 pw.print(prefix); pw.print("mNumInterestingWindows=");
3017 pw.print(mNumInterestingWindows);
3018 pw.print(" mNumDrawnWindows="); pw.print(mNumDrawnWindows);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003019 pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
Craig Mautner6fbda632012-07-03 09:26:39 -07003020 pw.print(" allDrawn="); pw.print(allDrawn);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00003021 pw.print(" lastAllDrawn="); pw.print(mLastAllDrawn);
Craig Mautner6fbda632012-07-03 09:26:39 -07003022 pw.println(")");
3023 }
3024 if (inPendingTransaction) {
3025 pw.print(prefix); pw.print("inPendingTransaction=");
3026 pw.println(inPendingTransaction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003027 }
chaviwa8f07a72019-05-01 16:25:39 -07003028 if (mStartingData != null || removed || firstWindowDrawn || mIsExiting) {
3029 pw.print(prefix); pw.print("startingData="); pw.print(mStartingData);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003030 pw.print(" removed="); pw.print(removed);
Craig Mautner3d7ca312015-01-08 10:56:00 -08003031 pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
Craig Mautner799bc1d2015-01-14 10:33:48 -08003032 pw.print(" mIsExiting="); pw.println(mIsExiting);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003033 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08003034 if (startingWindow != null || startingSurface != null
Wale Ogunwale6c459212017-05-17 08:56:03 -07003035 || startingDisplayed || startingMoved || mHiddenSetFromTransferredStartingWindow) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003036 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08003037 pw.print(" startingSurface="); pw.print(startingSurface);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003038 pw.print(" startingDisplayed="); pw.print(startingDisplayed);
Wale Ogunwale6c459212017-05-17 08:56:03 -07003039 pw.print(" startingMoved="); pw.print(startingMoved);
3040 pw.println(" mHiddenSetFromTransferredStartingWindow="
3041 + mHiddenSetFromTransferredStartingWindow);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003042 }
Jorim Jaggi0429f352015-12-22 16:29:16 +01003043 if (!mFrozenBounds.isEmpty()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08003044 pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
Jorim Jaggi26c8c422016-05-09 19:57:25 -07003045 pw.print(prefix); pw.print("mFrozenMergedConfig="); pw.println(mFrozenMergedConfig);
Chong Zhangd78ddb42016-03-02 17:01:14 -08003046 }
3047 if (mPendingRelaunchCount != 0) {
3048 pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount);
Jorim Jaggi0429f352015-12-22 16:29:16 +01003049 }
Riddle Hsub398da32019-01-21 21:48:16 +08003050 if (mSizeCompatScale != 1f || mSizeCompatBounds != null) {
3051 pw.println(prefix + "mSizeCompatScale=" + mSizeCompatScale + " mSizeCompatBounds="
3052 + mSizeCompatBounds);
3053 }
Wale Ogunwalee287e192017-04-21 09:30:12 -07003054 if (mRemovingFromDisplay) {
3055 pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay);
3056 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003057 }
3058
3059 @Override
3060 void setHidden(boolean hidden) {
3061 super.setHidden(hidden);
Winson Chunge55c0192017-08-24 14:50:48 -07003062
3063 if (hidden) {
3064 // Once the app window is hidden, reset the last saved PiP snap fraction
3065 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(this);
3066 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003067 scheduleAnimation();
3068 }
3069
3070 @Override
3071 void prepareSurfaces() {
3072 // isSelfAnimating also returns true when we are about to start a transition, so we need
3073 // to check super here.
3074 final boolean reallyAnimating = super.isSelfAnimating();
3075 final boolean show = !isHidden() || reallyAnimating;
Robert Carrd8e4fb72019-01-31 11:14:30 -08003076
3077 if (mSurfaceControl != null) {
3078 if (show && !mLastSurfaceShowing) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003079 getPendingTransaction().show(mSurfaceControl);
Robert Carrd8e4fb72019-01-31 11:14:30 -08003080 } else if (!show && mLastSurfaceShowing) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003081 getPendingTransaction().hide(mSurfaceControl);
Robert Carrd8e4fb72019-01-31 11:14:30 -08003082 }
Jorim Jaggi4d1835d2017-08-31 17:28:27 +02003083 }
Jorim Jaggi988f6682017-11-17 17:46:43 +01003084 if (mThumbnail != null) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003085 mThumbnail.setShowing(getPendingTransaction(), show);
Jorim Jaggi988f6682017-11-17 17:46:43 +01003086 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003087 mLastSurfaceShowing = show;
3088 super.prepareSurfaces();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003089 }
3090
Jorim Jaggi77d0f36c2018-03-16 17:49:49 +01003091 /**
3092 * @return Whether our {@link #getSurfaceControl} is currently showing.
3093 */
3094 boolean isSurfaceShowing() {
3095 return mLastSurfaceShowing;
3096 }
3097
Jorim Jaggib0fc8172017-11-23 17:04:08 +00003098 boolean isFreezingScreen() {
3099 return mFreezingScreen;
3100 }
3101
3102 @Override
3103 boolean needsZBoost() {
3104 return mNeedsZBoost || super.needsZBoost();
3105 }
3106
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07003107 @CallSuper
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003108 @Override
Nataniel Borges023ecb52019-01-16 14:15:43 -08003109 public void writeToProto(ProtoOutputStream proto, long fieldId,
3110 @WindowTraceLogLevel int logLevel) {
3111 // Critical log level logs only visible elements to mitigate performance overheard
3112 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
3113 return;
3114 }
3115
Steven Timotiusaf03df62017-07-18 16:56:43 -07003116 final long token = proto.start(fieldId);
3117 writeNameToProto(proto, NAME);
Nataniel Borges023ecb52019-01-16 14:15:43 -08003118 super.writeToProto(proto, WINDOW_TOKEN, logLevel);
Vishnu Nair04ab4392018-01-10 11:00:06 -08003119 proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing);
3120 proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart());
3121 proto.write(IS_REALLY_ANIMATING, isReallyAnimating());
3122 if (mThumbnail != null){
3123 mThumbnail.writeToProto(proto, THUMBNAIL);
3124 }
3125 proto.write(FILLS_PARENT, mFillsParent);
3126 proto.write(APP_STOPPED, mAppStopped);
3127 proto.write(HIDDEN_REQUESTED, hiddenRequested);
3128 proto.write(CLIENT_HIDDEN, mClientHidden);
3129 proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient);
3130 proto.write(REPORTED_DRAWN, reportedDrawn);
3131 proto.write(REPORTED_VISIBLE, reportedVisible);
3132 proto.write(NUM_INTERESTING_WINDOWS, mNumInterestingWindows);
3133 proto.write(NUM_DRAWN_WINDOWS, mNumDrawnWindows);
3134 proto.write(ALL_DRAWN, allDrawn);
3135 proto.write(LAST_ALL_DRAWN, mLastAllDrawn);
3136 proto.write(REMOVED, removed);
Nataniel Borges023ecb52019-01-16 14:15:43 -08003137 if (startingWindow != null) {
Vishnu Nair04ab4392018-01-10 11:00:06 -08003138 startingWindow.writeIdentifierToProto(proto, STARTING_WINDOW);
3139 }
3140 proto.write(STARTING_DISPLAYED, startingDisplayed);
3141 proto.write(STARTING_MOVED, startingMoved);
3142 proto.write(HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW,
3143 mHiddenSetFromTransferredStartingWindow);
3144 for (Rect bounds : mFrozenBounds) {
3145 bounds.writeToProto(proto, FROZEN_BOUNDS);
3146 }
Steven Timotiusaf03df62017-07-18 16:56:43 -07003147 proto.end(token);
3148 }
3149
3150 void writeNameToProto(ProtoOutputStream proto, long fieldId) {
3151 if (appToken == null) {
3152 return;
3153 }
3154 try {
3155 proto.write(fieldId, appToken.getName());
3156 } catch (RemoteException e) {
3157 // This shouldn't happen, but in this case fall back to outputting nothing
3158 Slog.e(TAG, e.toString());
3159 }
3160 }
3161
3162 @Override
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003163 public String toString() {
3164 if (stringName == null) {
3165 StringBuilder sb = new StringBuilder();
3166 sb.append("AppWindowToken{");
3167 sb.append(Integer.toHexString(System.identityHashCode(this)));
3168 sb.append(" token="); sb.append(token); sb.append('}');
3169 stringName = sb.toString();
3170 }
Wale Ogunwaleba51ca22016-09-23 06:06:54 -07003171 return stringName + ((mIsExiting) ? " mIsExiting=" : "");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003172 }
Adrian Roos20e07892018-02-23 19:12:01 +01003173
3174 Rect getLetterboxInsets() {
3175 if (mLetterbox != null) {
3176 return mLetterbox.getInsets();
3177 } else {
3178 return new Rect();
3179 }
3180 }
Adrian Roos23df3a32018-03-15 15:41:13 +01003181
Riddle Hsu69de5fb2019-02-23 01:19:50 +08003182 /** Gets the inner bounds of letterbox. The bounds will be empty if there is no letterbox. */
3183 void getLetterboxInnerBounds(Rect outBounds) {
3184 if (mLetterbox != null) {
3185 outBounds.set(mLetterbox.getInnerFrame());
3186 } else {
3187 outBounds.setEmpty();
3188 }
3189 }
3190
Adrian Roos23df3a32018-03-15 15:41:13 +01003191 /**
Riddle Hsu69de5fb2019-02-23 01:19:50 +08003192 * @return {@code true} if there is a letterbox and any part of that letterbox overlaps with
Adrian Roos23df3a32018-03-15 15:41:13 +01003193 * the given {@code rect}.
3194 */
3195 boolean isLetterboxOverlappingWith(Rect rect) {
3196 return mLetterbox != null && mLetterbox.isOverlappingWith(rect);
3197 }
chaviw4ad54912018-05-30 11:05:44 -07003198
3199 /**
3200 * Sets if this AWT is in the process of closing or entering PIP.
3201 * {@link #mWillCloseOrEnterPip}}
3202 */
3203 void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
3204 mWillCloseOrEnterPip = willCloseOrEnterPip;
3205 }
3206
3207 /**
3208 * Returns whether this AWT is considered closing. Conditions are either
3209 * 1. Is this app animating and was requested to be hidden
3210 * 2. App is delayed closing since it might enter PIP.
3211 */
3212 boolean isClosingOrEnteringPip() {
3213 return (isAnimating() && hiddenRequested) || mWillCloseOrEnterPip;
3214 }
Jorim Jaggiaf0d6d22018-06-08 15:25:35 +02003215
3216 /**
3217 * @return Whether we are allowed to show non-starting windows at the moment. We disallow
3218 * showing windows during transitions in case we have windows that have wide-color-gamut
3219 * color mode set to avoid jank in the middle of the transition.
3220 */
3221 boolean canShowWindows() {
3222 return allDrawn && !(isReallyAnimating() && hasNonDefaultColorWindow());
3223 }
3224
3225 /**
3226 * @return true if we have a window that has a non-default color mode set; false otherwise.
3227 */
3228 private boolean hasNonDefaultColorWindow() {
3229 return forAllWindows(ws -> ws.mAttrs.getColorMode() != COLOR_MODE_DEFAULT,
3230 true /* topToBottom */);
3231 }
lumark588a3e82018-07-20 18:53:54 +08003232
chaviwdcf76ec2019-01-11 16:48:46 -08003233 private void updateColorTransform() {
3234 if (mSurfaceControl != null && mLastAppSaturationInfo != null) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003235 getPendingTransaction().setColorTransform(mSurfaceControl,
3236 mLastAppSaturationInfo.mMatrix, mLastAppSaturationInfo.mTranslation);
chaviwdcf76ec2019-01-11 16:48:46 -08003237 mWmService.scheduleAnimationLocked();
3238 }
3239 }
3240
3241 private static class AppSaturationInfo {
3242 float[] mMatrix = new float[9];
3243 float[] mTranslation = new float[3];
3244
3245 void setSaturation(@Size(9) float[] matrix, @Size(3) float[] translation) {
3246 System.arraycopy(matrix, 0, mMatrix, 0, mMatrix.length);
3247 System.arraycopy(translation, 0, mTranslation, 0, mTranslation.length);
3248 }
3249 }
Jeff Browne9bdb312012-04-05 15:30:10 -07003250}