blob: a8709979d730787ce510ab91b2405b7d5ef644df [file] [log] [blame]
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.wm;
18
Evan Rosky2289ba12018-11-19 18:28:18 -080019import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
Winson Chunge55c0192017-08-24 14:50:48 -070020import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
Jorim Jaggic6976f02018-04-18 16:31:07 +020021import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
Winson Chunge55c0192017-08-24 14:50:48 -070022import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
Jorim Jaggiaf0d6d22018-06-08 15:25:35 +020023import static android.content.pm.ActivityInfo.COLOR_MODE_DEFAULT;
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -070024import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
Wale Ogunwale51362492016-09-08 17:49:17 -070025import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
Jorim Jaggif5f9e122017-10-24 18:21:09 +020026import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
Jorim Jaggife762342016-10-13 14:33:27 +020027import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
Jorim Jaggid635a4a2017-05-03 15:21:26 +020028import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080029import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
Jorim Jaggife762342016-10-13 14:33:27 +020030import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
Wale Ogunwaled1c37912016-08-16 03:19:39 -070031import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080032import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -070033import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080034import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
Evan Rosky2289ba12018-11-19 18:28:18 -080035import static android.view.WindowManager.TRANSIT_TASK_CHANGE_WINDOWING_MODE;
Louis Chang37317152019-05-09 09:53:58 +080036import static android.view.WindowManager.TRANSIT_TASK_OPEN_BEHIND;
chaviw9c81e632018-07-31 11:17:52 -070037import static android.view.WindowManager.TRANSIT_UNSET;
Jorim Jaggic6976f02018-04-18 16:31:07 +020038import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
chaviw9c81e632018-07-31 11:17:52 -070039
Adrian Roose99bc052017-11-20 17:55:31 +010040import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
41import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070042import static com.android.server.wm.AppWindowTokenProto.ALL_DRAWN;
43import static com.android.server.wm.AppWindowTokenProto.APP_STOPPED;
44import static com.android.server.wm.AppWindowTokenProto.CLIENT_HIDDEN;
45import static com.android.server.wm.AppWindowTokenProto.DEFER_HIDING_CLIENT;
46import static com.android.server.wm.AppWindowTokenProto.FILLS_PARENT;
47import static com.android.server.wm.AppWindowTokenProto.FROZEN_BOUNDS;
48import static com.android.server.wm.AppWindowTokenProto.HIDDEN_REQUESTED;
49import static com.android.server.wm.AppWindowTokenProto.HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW;
50import static com.android.server.wm.AppWindowTokenProto.IS_REALLY_ANIMATING;
51import static com.android.server.wm.AppWindowTokenProto.IS_WAITING_FOR_TRANSITION_START;
52import static com.android.server.wm.AppWindowTokenProto.LAST_ALL_DRAWN;
53import static com.android.server.wm.AppWindowTokenProto.LAST_SURFACE_SHOWING;
54import static com.android.server.wm.AppWindowTokenProto.NAME;
55import static com.android.server.wm.AppWindowTokenProto.NUM_DRAWN_WINDOWS;
56import static com.android.server.wm.AppWindowTokenProto.NUM_INTERESTING_WINDOWS;
57import static com.android.server.wm.AppWindowTokenProto.REMOVED;
58import static com.android.server.wm.AppWindowTokenProto.REPORTED_DRAWN;
59import static com.android.server.wm.AppWindowTokenProto.REPORTED_VISIBLE;
60import static com.android.server.wm.AppWindowTokenProto.STARTING_DISPLAYED;
61import static com.android.server.wm.AppWindowTokenProto.STARTING_MOVED;
62import static com.android.server.wm.AppWindowTokenProto.STARTING_WINDOW;
63import static com.android.server.wm.AppWindowTokenProto.THUMBNAIL;
64import static com.android.server.wm.AppWindowTokenProto.WINDOW_TOKEN;
chaviw9c81e632018-07-31 11:17:52 -070065import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
66import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
67import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
68import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
69import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
70import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
71import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
72import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
73import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
74import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
75import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
76import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
77import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
78import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN;
79import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
80import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
81import static com.android.server.wm.WindowManagerService.logWithStack;
chaviw15ad49f2019-04-24 15:05:39 -070082import static com.android.server.wm.WindowState.LEGACY_POLICY_VISIBILITY;
Vishnu Naira2977262018-07-26 13:31:26 -070083import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
Evan Rosky641daea2019-04-24 14:45:24 -070084import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080085
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070086import android.annotation.CallSuper;
chaviwdcf76ec2019-01-11 16:48:46 -080087import android.annotation.Size;
Jorim Jaggid635a4a2017-05-03 15:21:26 +020088import android.app.Activity;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080089import android.app.ActivityManager;
Winson Chung48b25652018-10-22 14:04:30 -070090import android.content.ComponentName;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080091import android.content.res.CompatibilityInfo;
Jorim Jaggi26c8c422016-05-09 19:57:25 -070092import android.content.res.Configuration;
Jorim Jaggi988f6682017-11-17 17:46:43 +010093import android.graphics.GraphicBuffer;
Jorim Jaggif5f9e122017-10-24 18:21:09 +020094import android.graphics.Point;
Jorim Jaggi0429f352015-12-22 16:29:16 +010095import android.graphics.Rect;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -070096import android.os.Binder;
Tiger Huang51c5a1d2018-12-11 20:24:51 +080097import android.os.Build;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -080098import android.os.Debug;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -070099import android.os.IBinder;
Steven Timotiusaf03df62017-07-18 16:56:43 -0700100import android.os.RemoteException;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800101import android.os.SystemClock;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200102import android.os.Trace;
Evan Rosky2289ba12018-11-19 18:28:18 -0800103import android.util.ArraySet;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800104import android.util.Slog;
Steven Timotiusaf03df62017-07-18 16:56:43 -0700105import android.util.proto.ProtoOutputStream;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200106import android.view.DisplayInfo;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800107import android.view.IApplicationToken;
Robert Carr788f5742018-07-30 17:46:45 -0700108import android.view.InputApplicationHandle;
Evan Rosky966759f2019-01-15 10:33:58 -0800109import android.view.RemoteAnimationAdapter;
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100110import android.view.RemoteAnimationDefinition;
Robert Carr6914f082017-03-20 19:04:30 -0700111import android.view.SurfaceControl;
Tony Mak64b8d562017-12-28 17:44:02 +0000112import android.view.SurfaceControl.Transaction;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800113import android.view.WindowManager;
Jorim Jaggi87fdbcb2017-08-17 13:41:11 +0200114import android.view.WindowManager.LayoutParams;
Tony Mak64b8d562017-12-28 17:44:02 +0000115import android.view.animation.Animation;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800116
Tony Mak64b8d562017-12-28 17:44:02 +0000117import com.android.internal.R;
Riddle Hsua118b3a2018-10-11 22:05:06 +0800118import com.android.internal.annotations.VisibleForTesting;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800119import com.android.internal.util.ToBooleanFunction;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800120import com.android.server.AttributeCache;
chaviwdcf76ec2019-01-11 16:48:46 -0800121import com.android.server.LocalServices;
Christine Franks0ada2772019-02-25 13:54:57 -0800122import com.android.server.display.color.ColorDisplayService;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800123import com.android.server.policy.WindowManagerPolicy;
Adrian Roose99bc052017-11-20 17:55:31 +0100124import com.android.server.policy.WindowManagerPolicy.StartingSurface;
Evan Rosky2289ba12018-11-19 18:28:18 -0800125import com.android.server.wm.RemoteAnimationController.RemoteAnimationRecord;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800126import com.android.server.wm.WindowManagerService.H;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800127
128import java.io.PrintWriter;
chaviwdcf76ec2019-01-11 16:48:46 -0800129import java.lang.ref.WeakReference;
Jorim Jaggi0429f352015-12-22 16:29:16 +0100130import java.util.ArrayDeque;
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800131import java.util.ArrayList;
lumark588a3e82018-07-20 18:53:54 +0800132import java.util.function.Consumer;
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800133
134class AppTokenList extends ArrayList<AppWindowToken> {
135}
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800136
137/**
138 * Version of WindowToken that is specifically for a particular application (or
139 * really activity) that is displaying windows.
140 */
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800141class AppWindowToken extends WindowToken implements WindowManagerService.AppFreezeListener,
142 ConfigurationContainerListener {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800143 private static final String TAG = TAG_WITH_CLASS_NAME ? "AppWindowToken" : TAG_WM;
144
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100145 /**
146 * Value to increment the z-layer when boosting a layer during animations. BOOST in l33tsp34k.
147 */
Jorim Jaggi9cd99132019-04-24 17:41:35 +0200148 @VisibleForTesting static final int Z_BOOST_BASE = 800570000;
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100149
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800150 // Non-null only for application tokens.
151 final IApplicationToken appToken;
Winson Chung48b25652018-10-22 14:04:30 -0700152 final ComponentName mActivityComponent;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800153 final boolean mVoiceInteraction;
Dianne Hackborne30e02f2014-05-27 18:24:45 -0700154
Wale Ogunwale51362492016-09-08 17:49:17 -0700155 /** @see WindowContainer#fillsParent() */
156 private boolean mFillsParent;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800157 boolean mShowForAllUsers;
158 int mTargetSdk;
Craig Mautnera2c77052012-03-26 12:14:43 -0700159
Bryce Lee6d410262017-02-28 15:30:17 -0800160 // Flag set while reparenting to prevent actions normally triggered by an individual parent
161 // change.
162 private boolean mReparenting;
163
Wale Ogunwalee287e192017-04-21 09:30:12 -0700164 // True if we are current in the process of removing this app token from the display
165 private boolean mRemovingFromDisplay = false;
166
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800167 // The input dispatching timeout for this application token in nanoseconds.
Wale Ogunwale72919d22016-12-08 18:58:50 -0800168 long mInputDispatchingTimeoutNanos;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800169
170 // These are used for determining when all windows associated with
171 // an activity have been drawn, so they can be made visible together
172 // at the same time.
Craig Mautner764983d2012-03-22 11:37:36 -0700173 // initialize so that it doesn't match mTransactionSequence which is an int.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700174 private long mLastTransactionSequence = Long.MIN_VALUE;
175 private int mNumInterestingWindows;
176 private int mNumDrawnWindows;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800177 boolean inPendingTransaction;
178 boolean allDrawn;
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000179 private boolean mLastAllDrawn;
Tiger Huangc9d0d002019-05-29 22:55:29 +0800180 private boolean mUseTransferredAnimation;
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000181
Craig Mautner7636dfb2012-11-16 15:24:11 -0800182 // Set to true when this app creates a surface while in the middle of an animation. In that
183 // case do not clear allDrawn until the animation completes.
184 boolean deferClearAllDrawn;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800185
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800186 // Is this window's surface needed? This is almost like hidden, except
187 // it will sometimes be true a little earlier: when the token has
188 // been shown, but is still waiting for its app transition to execute
189 // before making its windows shown.
190 boolean hiddenRequested;
191
192 // Have we told the window clients to hide themselves?
Wale Ogunwale89973222017-04-23 18:39:45 -0700193 private boolean mClientHidden;
194
195 // If true we will defer setting mClientHidden to true and reporting to the client that it is
196 // hidden.
197 boolean mDeferHidingClient;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800198
199 // Last visibility state we reported to the app token.
200 boolean reportedVisible;
201
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700202 // Last drawn state we reported to the app token.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700203 private boolean reportedDrawn;
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700204
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800205 // Set to true when the token has been removed from the window mgr.
206 boolean removed;
207
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800208 // Information about an application starting window if displayed.
chaviwa8f07a72019-05-01 16:25:39 -0700209 StartingData mStartingData;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800210 WindowState startingWindow;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800211 StartingSurface startingSurface;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800212 boolean startingDisplayed;
213 boolean startingMoved;
Jorim Jaggi60f9c972018-02-01 19:21:07 +0100214
Wale Ogunwale6c459212017-05-17 08:56:03 -0700215 // True if the hidden state of this token was forced to false due to a transferred starting
216 // window.
217 private boolean mHiddenSetFromTransferredStartingWindow;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800218 boolean firstWindowDrawn;
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700219 private final WindowState.UpdateReportedVisibilityResults mReportedVisibilityResults =
220 new WindowState.UpdateReportedVisibilityResults();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800221
222 // Input application handle used by the input dispatcher.
Jeff Brown9302c872011-07-13 22:51:29 -0700223 final InputApplicationHandle mInputApplicationHandle;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800224
Wale Ogunwale571771c2016-08-26 13:18:50 -0700225 // TODO: Have a WindowContainer state for tracking exiting/deferred removal.
Craig Mautner799bc1d2015-01-14 10:33:48 -0800226 boolean mIsExiting;
Craig Mautner9ef471f2014-02-07 13:11:47 -0800227
Craig Mautnerbb742462014-07-07 15:28:55 -0700228 boolean mLaunchTaskBehind;
Craig Mautner8746a472014-07-24 15:12:54 -0700229 boolean mEnteringAnimation;
Craig Mautnerbb742462014-07-07 15:28:55 -0700230
Wale Ogunwale72919d22016-12-08 18:58:50 -0800231 private boolean mAlwaysFocusable;
Wale Ogunwale6cae7652015-12-26 07:36:26 -0800232
Robert Carre12aece2016-02-02 22:43:27 -0800233 boolean mAppStopped;
Robert Carrfd10cd12016-06-29 16:41:50 -0700234 int mRotationAnimationHint;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700235 private int mPendingRelaunchCount;
Robert Carre12aece2016-02-02 22:43:27 -0800236
Jorim Jaggife762342016-10-13 14:33:27 +0200237 private boolean mLastContainsShowWhenLockedWindow;
238 private boolean mLastContainsDismissKeyguardWindow;
239
Jorim Jaggi0429f352015-12-22 16:29:16 +0100240 ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
Jorim Jaggi26c8c422016-05-09 19:57:25 -0700241 ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
Jorim Jaggi0429f352015-12-22 16:29:16 +0100242
Riddle Hsub398da32019-01-21 21:48:16 +0800243 /**
244 * The scale to fit at least one side of the activity to its parent. If the activity uses
245 * 1920x1080, and the actually size on the screen is 960x540, then the scale is 0.5.
246 */
247 private float mSizeCompatScale = 1f;
248 /**
249 * The bounds in global coordinates for activity in size compatibility mode.
250 * @see ActivityRecord#inSizeCompatMode
251 */
252 private Rect mSizeCompatBounds;
253
Wale Ogunwale6c459212017-05-17 08:56:03 -0700254 private boolean mDisablePreviewScreenshots;
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +0100255
Wale Ogunwale034a8ec2017-09-02 17:14:40 -0700256 private Task mLastParent;
Robert Carred3e83b2017-04-21 13:26:55 -0700257
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800258 // TODO: Remove after unification
259 ActivityRecord mActivityRecord;
260
chaviwd3bf08d2017-08-01 17:24:59 -0700261 /**
262 * See {@link #canTurnScreenOn()}
263 */
264 private boolean mCanTurnScreenOn = true;
265
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200266 /**
267 * If we are running an animation, this determines the transition type. Must be one of
268 * AppTransition.TRANSIT_* constants.
269 */
270 private int mTransit;
271
272 /**
273 * If we are running an animation, this determines the flags during this animation. Must be a
274 * bitwise combination of AppTransition.TRANSIT_FLAG_* constants.
275 */
276 private int mTransitFlags;
277
278 /** Whether our surface was set to be showing in the last call to {@link #prepareSurfaces} */
Jorim Jaggifd1891462017-12-29 15:41:36 +0100279 private boolean mLastSurfaceShowing = true;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200280
Evan Rosky2289ba12018-11-19 18:28:18 -0800281 /**
282 * This gets used during some open/close transitions as well as during a change transition
283 * where it represents the starting-state snapshot.
284 */
Jorim Jaggi988f6682017-11-17 17:46:43 +0100285 private AppWindowThumbnail mThumbnail;
Evan Rosky2289ba12018-11-19 18:28:18 -0800286 private final Rect mTransitStartRect = new Rect();
287
288 /**
289 * This leash is used to "freeze" the app surface in place after the state change, but before
290 * the animation is ready to start.
291 */
292 private SurfaceControl mTransitChangeLeash = null;
Jorim Jaggi988f6682017-11-17 17:46:43 +0100293
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000294 /** Have we been asked to have this token keep the screen frozen? */
295 private boolean mFreezingScreen;
296
297 /** Whether this token should be boosted at the top of all app window tokens. */
Jorim Jaggi9cd99132019-04-24 17:41:35 +0200298 @VisibleForTesting boolean mNeedsZBoost;
Adrian Roos4d18a2e2017-12-19 19:08:05 +0100299 private Letterbox mLetterbox;
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000300
chaviw23ee71c2017-12-18 11:29:41 -0800301 private final Point mTmpPoint = new Point();
chaviw23012112017-12-20 15:29:04 -0800302 private final Rect mTmpRect = new Rect();
Evan Rosky2289ba12018-11-19 18:28:18 -0800303 private final Rect mTmpPrevBounds = new Rect();
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100304 private RemoteAnimationDefinition mRemoteAnimationDefinition;
Jorim Jaggi6de61012018-03-19 14:53:23 +0100305 private AnimatingAppWindowTokenRegistry mAnimatingAppWindowTokenRegistry;
chaviw23ee71c2017-12-18 11:29:41 -0800306
chaviw4ad54912018-05-30 11:05:44 -0700307 /**
308 * A flag to determine if this AWT is in the process of closing or entering PIP. This is needed
309 * to help AWT know that the app is in the process of closing but hasn't yet started closing on
310 * the WM side.
311 */
312 private boolean mWillCloseOrEnterPip;
313
Vishnu Naira2977262018-07-26 13:31:26 -0700314 /** Layer used to constrain the animation to a token's stack bounds. */
315 SurfaceControl mAnimationBoundsLayer;
316
317 /** Whether this token needs to create mAnimationBoundsLayer for cropping animations. */
318 boolean mNeedsAnimationBoundsLayer;
319
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800320 private static final int STARTING_WINDOW_TYPE_NONE = 0;
321 private static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
322 private static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
323
chaviwdcf76ec2019-01-11 16:48:46 -0800324 private AppSaturationInfo mLastAppSaturationInfo;
325
326 private final ColorDisplayService.ColorTransformController mColorTransformController =
327 (matrix, translation) -> mWmService.mH.post(() -> {
328 synchronized (mWmService.mGlobalLock) {
329 if (mLastAppSaturationInfo == null) {
330 mLastAppSaturationInfo = new AppSaturationInfo();
331 }
332
333 mLastAppSaturationInfo.setSaturation(matrix, translation);
334 updateColorTransform();
335 }
336 });
337
Winson Chung48b25652018-10-22 14:04:30 -0700338 AppWindowToken(WindowManagerService service, IApplicationToken token,
339 ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
340 long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers,
Jorim Jaggi91d382a2019-03-27 17:00:48 +0100341 int targetSdk, int orientation, int rotationAnimationHint,
Winson Chung48b25652018-10-22 14:04:30 -0700342 boolean launchTaskBehind, boolean alwaysFocusable,
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800343 ActivityRecord activityRecord) {
Winson Chung48b25652018-10-22 14:04:30 -0700344 this(service, token, activityComponent, voiceInteraction, dc, fullscreen);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800345 // TODO: remove after unification
346 mActivityRecord = activityRecord;
347 mActivityRecord.registerConfigurationChangeListener(this);
Wale Ogunwale72919d22016-12-08 18:58:50 -0800348 mInputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800349 mShowForAllUsers = showForAllUsers;
350 mTargetSdk = targetSdk;
351 mOrientation = orientation;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800352 mLaunchTaskBehind = launchTaskBehind;
353 mAlwaysFocusable = alwaysFocusable;
354 mRotationAnimationHint = rotationAnimationHint;
355
356 // Application tokens start out hidden.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200357 setHidden(true);
Wale Ogunwale72919d22016-12-08 18:58:50 -0800358 hiddenRequested = true;
chaviwdcf76ec2019-01-11 16:48:46 -0800359
360 ColorDisplayService.ColorDisplayServiceInternal cds = LocalServices.getService(
361 ColorDisplayService.ColorDisplayServiceInternal.class);
362 cds.attachColorTransformController(activityRecord.packageName, activityRecord.mUserId,
363 new WeakReference<>(mColorTransformController));
Wale Ogunwale72919d22016-12-08 18:58:50 -0800364 }
365
Winson Chung48b25652018-10-22 14:04:30 -0700366 AppWindowToken(WindowManagerService service, IApplicationToken token,
367 ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
368 boolean fillsParent) {
Wale Ogunwale5cd907d2017-01-26 14:14:08 -0800369 super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true, dc,
370 false /* ownerCanManageAppTokens */);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700371 appToken = token;
Winson Chung48b25652018-10-22 14:04:30 -0700372 mActivityComponent = activityComponent;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800373 mVoiceInteraction = voiceInteraction;
Wale Ogunwale17f175c2017-02-07 16:54:10 -0800374 mFillsParent = fillsParent;
Robert Carr0bcbe642018-10-11 19:07:43 -0700375 mInputApplicationHandle = new InputApplicationHandle(appToken.asBinder());
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800376 }
377
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800378 void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
379 firstWindowDrawn = true;
380
381 // We now have a good window to show, remove dead placeholders
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700382 removeDeadWindows();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800383
Jorim Jaggi02886a82016-12-06 09:10:06 -0800384 if (startingWindow != null) {
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800385 if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Slog.v(TAG, "Finish starting "
386 + win.mToken + ": first real window is shown, no animation");
387 // If this initial window is animating, stop it -- we will do an animation to reveal
388 // it from behind the starting window, so there is no need for it to also be doing its
389 // own stuff.
Jorim Jaggia5e10572017-11-15 14:36:26 +0100390 win.cancelAnimation();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800391 }
chaviwa8f07a72019-05-01 16:25:39 -0700392 removeStartingWindow();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800393 updateReportedVisibilityLocked();
394 }
395
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800396 void updateReportedVisibilityLocked() {
397 if (appToken == null) {
398 return;
399 }
400
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700401 if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700402 final int count = mChildren.size();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800403
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700404 mReportedVisibilityResults.reset();
405
406 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700407 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700408 win.updateReportedVisibility(mReportedVisibilityResults);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800409 }
410
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700411 int numInteresting = mReportedVisibilityResults.numInteresting;
412 int numVisible = mReportedVisibilityResults.numVisible;
413 int numDrawn = mReportedVisibilityResults.numDrawn;
414 boolean nowGone = mReportedVisibilityResults.nowGone;
415
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700416 boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200417 boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting && !isHidden();
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700418 if (!nowGone) {
419 // If the app is not yet gone, then it can only become visible/drawn.
420 if (!nowDrawn) {
421 nowDrawn = reportedDrawn;
422 }
423 if (!nowVisible) {
424 nowVisible = reportedVisible;
425 }
426 }
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800427 if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800428 + numInteresting + " visible=" + numVisible);
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700429 if (nowDrawn != reportedDrawn) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800430 if (mActivityRecord != null) {
431 mActivityRecord.onWindowsDrawn(nowDrawn, SystemClock.uptimeMillis());
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700432 }
433 reportedDrawn = nowDrawn;
434 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800435 if (nowVisible != reportedVisible) {
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700436 if (DEBUG_VISIBILITY) Slog.v(TAG,
437 "Visibility changed in " + this + ": vis=" + nowVisible);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800438 reportedVisible = nowVisible;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800439 if (mActivityRecord != null) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800440 if (nowVisible) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800441 onWindowsVisible();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800442 } else {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800443 onWindowsGone();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800444 }
445 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800446 }
447 }
448
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800449 private void onWindowsGone() {
450 if (mActivityRecord == null) {
451 return;
452 }
453 if (DEBUG_VISIBILITY) {
454 Slog.v(TAG_WM, "Reporting gone in " + mActivityRecord.appToken);
455 }
456 mActivityRecord.onWindowsGone();
457 }
458
459 private void onWindowsVisible() {
460 if (mActivityRecord == null) {
461 return;
462 }
463 if (DEBUG_VISIBILITY) {
464 Slog.v(TAG_WM, "Reporting visible in " + mActivityRecord.appToken);
465 }
466 mActivityRecord.onWindowsVisible();
467 }
468
Wale Ogunwale89973222017-04-23 18:39:45 -0700469 boolean isClientHidden() {
470 return mClientHidden;
471 }
472
473 void setClientHidden(boolean hideClient) {
474 if (mClientHidden == hideClient || (hideClient && mDeferHidingClient)) {
475 return;
476 }
Jorim Jaggi067b5bf2018-02-23 17:42:39 +0100477 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "setClientHidden: " + this
478 + " clientHidden=" + hideClient + " Callers=" + Debug.getCallers(5));
Wale Ogunwale89973222017-04-23 18:39:45 -0700479 mClientHidden = hideClient;
480 sendAppVisibilityToClients();
481 }
482
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800483 void setVisibility(boolean visible, boolean deferHidingClient) {
484 final AppTransition appTransition = getDisplayContent().mAppTransition;
485
486 // Don't set visibility to false if we were already not visible. This prevents WM from
487 // adding the app to the closing app list which doesn't make sense for something that is
488 // already not visible. However, set visibility to true even if we are already visible.
489 // This makes sure the app is added to the opening apps list so that the right
490 // transition can be selected.
491 // TODO: Probably a good idea to separate the concept of opening/closing apps from the
492 // concept of setting visibility...
493 if (!visible && hiddenRequested) {
494
495 if (!deferHidingClient && mDeferHidingClient) {
496 // We previously deferred telling the client to hide itself when visibility was
497 // initially set to false. Now we would like it to hide, so go ahead and set it.
498 mDeferHidingClient = deferHidingClient;
499 setClientHidden(true);
500 }
501 return;
502 }
503
504 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) {
505 Slog.v(TAG_WM, "setAppVisibility("
506 + appToken + ", visible=" + visible + "): " + appTransition
507 + " hidden=" + isHidden() + " hiddenRequested="
508 + hiddenRequested + " Callers=" + Debug.getCallers(6));
509 }
510
511 final DisplayContent displayContent = getDisplayContent();
512 displayContent.mOpeningApps.remove(this);
513 displayContent.mClosingApps.remove(this);
Evan Roskyb1e75f72019-04-26 20:23:26 -0700514 if (isInChangeTransition()) {
515 clearChangeLeash(getPendingTransaction(), true /* cancel */);
516 }
517 displayContent.mChangingApps.remove(this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800518 waitingToShow = false;
519 hiddenRequested = !visible;
520 mDeferHidingClient = deferHidingClient;
521
522 if (!visible) {
523 // If the app is dead while it was visible, we kept its dead window on screen.
524 // Now that the app is going invisible, we can remove it. It will be restarted
525 // if made visible again.
526 removeDeadWindows();
527 } else {
528 if (!appTransition.isTransitionSet()
529 && appTransition.isReady()) {
530 // Add the app mOpeningApps if transition is unset but ready. This means
531 // we're doing a screen freeze, and the unfreeze will wait for all opening
532 // apps to be ready.
533 displayContent.mOpeningApps.add(this);
534 }
535 startingMoved = false;
536 // If the token is currently hidden (should be the common case), or has been
537 // stopped, then we need to set up to wait for its windows to be ready.
538 if (isHidden() || mAppStopped) {
539 clearAllDrawn();
540
541 // If the app was already visible, don't reset the waitingToShow state.
542 if (isHidden()) {
543 waitingToShow = true;
544 }
545 }
546
547 // In the case where we are making an app visible but holding off for a transition,
548 // we still need to tell the client to make its windows visible so they get drawn.
549 // Otherwise, we will wait on performing the transition until all windows have been
550 // drawn, they never will be, and we are sad.
551 setClientHidden(false);
552
553 requestUpdateWallpaperIfNeeded();
554
555 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "No longer Stopped: " + this);
556 mAppStopped = false;
557
558 transferStartingWindowFromHiddenAboveTokenIfNeeded();
559 }
560
561 // If we are preparing an app transition, then delay changing
562 // the visibility of this token until we execute that transition.
563 if (okToAnimate() && appTransition.isTransitionSet()) {
564 inPendingTransaction = true;
565 if (visible) {
566 displayContent.mOpeningApps.add(this);
567 mEnteringAnimation = true;
568 } else {
569 displayContent.mClosingApps.add(this);
570 mEnteringAnimation = false;
571 }
Louis Chang37317152019-05-09 09:53:58 +0800572 if (appTransition.getAppTransition() == TRANSIT_TASK_OPEN_BEHIND) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800573 // 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.
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800583 displayContent.mOpeningApps.add(focusedToken);
584 }
585 }
586 }
Garfield Tanb6776602019-02-20 14:44:26 -0800587 // Changes in opening apps and closing apps may cause orientation change.
588 reportDescendantOrientationChangeIfNeeded();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800589 return;
590 }
591
592 commitVisibility(null, visible, TRANSIT_UNSET, true, mVoiceInteraction);
593 updateReportedVisibilityLocked();
594 }
595
596 boolean commitVisibility(WindowManager.LayoutParams lp,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700597 boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
598
599 boolean delayed = false;
600 inPendingTransaction = false;
Wale Ogunwale9e4721f2017-05-23 19:37:30 -0700601 // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually
602 // been set by the app now.
603 mHiddenSetFromTransferredStartingWindow = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700604
605 // Allow for state changes and animation to be applied if:
606 // * token is transitioning visibility state
607 // * or the token was marked as hidden and is exiting before we had a chance to play the
608 // transition animation
Louis Chang37317152019-05-09 09:53:58 +0800609 // * or this is an opening app and windows are being replaced
610 // * or the token is the opening app and visible while opening task behind existing one.
611 final DisplayContent displayContent = getDisplayContent();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700612 boolean visibilityChanged = false;
Louis Chang37317152019-05-09 09:53:58 +0800613 if (isHidden() == visible || (isHidden() && mIsExiting)
614 || (visible && waitingForReplacement())
615 || (visible && displayContent.mOpeningApps.contains(this)
616 && displayContent.mAppTransition.getAppTransition() == TRANSIT_TASK_OPEN_BEHIND)) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800617 final AccessibilityController accessibilityController =
618 mWmService.mAccessibilityController;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700619 boolean changed = false;
620 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM,
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200621 "Changing app " + this + " hidden=" + isHidden() + " performLayout=" + performLayout);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700622
623 boolean runningAppAnimation = false;
624
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100625 if (transit != WindowManager.TRANSIT_UNSET) {
Tiger Huangc9d0d002019-05-29 22:55:29 +0800626 if (mUseTransferredAnimation) {
627 runningAppAnimation = isReallyAnimating();
628 } else if (applyAnimationLocked(lp, transit, visible, isVoiceInteraction)) {
629 runningAppAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700630 }
Tiger Huangc9d0d002019-05-29 22:55:29 +0800631 delayed = runningAppAnimation;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700632 final WindowState window = findMainWindow();
Rhed Jao02655dc2018-10-30 20:44:52 +0800633 if (window != null && accessibilityController != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700634 accessibilityController.onAppWindowTransitionLocked(window, transit);
635 }
636 changed = true;
637 }
638
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700639 final int windowsCount = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700640 for (int i = 0; i < windowsCount; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700641 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700642 changed |= win.onAppVisibilityChanged(visible, runningAppAnimation);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700643 }
644
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200645 setHidden(!visible);
646 hiddenRequested = !visible;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700647 visibilityChanged = true;
648 if (!visible) {
649 stopFreezingScreen(true, true);
650 } else {
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700651 // If we are being set visible, and the starting window is not yet displayed,
652 // then make sure it doesn't get displayed.
653 if (startingWindow != null && !startingWindow.isDrawnLw()) {
chaviw15ad49f2019-04-24 15:05:39 -0700654 startingWindow.clearPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY);
655 startingWindow.mLegacyPolicyVisibilityAfterAnim = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700656 }
Jorim Jaggi38d44ec2017-06-14 16:04:59 -0700657
658 // We are becoming visible, so better freeze the screen with the windows that are
659 // getting visible so we also wait for them.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800660 forAllWindows(mWmService::makeWindowFreezingScreenIfNeededLocked, true);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700661 }
662
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800663 if (DEBUG_APP_TRANSITIONS) {
664 Slog.v(TAG_WM, "commitVisibility: " + this
665 + ": hidden=" + isHidden() + " hiddenRequested=" + hiddenRequested);
666 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700667
668 if (changed) {
Louis Chang37317152019-05-09 09:53:58 +0800669 displayContent.getInputMonitor().setUpdateInputWindowsNeededLw();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700670 if (performLayout) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800671 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700672 false /*updateInputWindows*/);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800673 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700674 }
Louis Chang37317152019-05-09 09:53:58 +0800675 displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700676 }
677 }
Tiger Huangc9d0d002019-05-29 22:55:29 +0800678 mUseTransferredAnimation = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700679
lumarkd14173e2019-03-27 19:14:33 +0800680 if (isReallyAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700681 delayed = true;
Jorim Jaggiab9fcb22018-03-15 23:46:12 +0100682 } else {
683
684 // We aren't animating anything, but exiting windows rely on the animation finished
685 // callback being called in case the AppWindowToken was pretending to be animating,
686 // which we might have done because we were in closing/opening apps list.
687 onAnimationFinished();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700688 }
689
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700690 for (int i = mChildren.size() - 1; i >= 0 && !delayed; i--) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100691 if ((mChildren.get(i)).isSelfOrChildAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700692 delayed = true;
693 }
694 }
695
696 if (visibilityChanged) {
697 if (visible && !delayed) {
698 // The token was made immediately visible, there will be no entrance animation.
699 // We need to inform the client the enter animation was finished.
700 mEnteringAnimation = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800701 mWmService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(
702 token);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700703 }
Robert Carr61b81112017-07-17 18:08:15 -0700704
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800705 // If we're becoming visible, immediately change client visibility as well. there seem
706 // to be some edge cases where we change our visibility but client visibility never gets
707 // updated.
Jorim Jaggi110839b2018-01-22 12:49:04 +0100708 // If we're becoming invisible, update the client visibility if we are not running an
709 // animation. Otherwise, we'll update client visibility in onAnimationFinished.
Jorim Jaggi3cad57f2018-02-20 18:32:01 +0100710 if (visible || !isReallyAnimating()) {
Jorim Jaggi110839b2018-01-22 12:49:04 +0100711 setClientHidden(!visible);
Jorim Jaggi4876b4a2018-01-11 15:43:49 +0100712 }
713
Louis Chang37317152019-05-09 09:53:58 +0800714 if (!displayContent.mClosingApps.contains(this)
715 && !displayContent.mOpeningApps.contains(this)) {
chaviwa953fcf2018-03-01 12:00:39 -0800716 // The token is not closing nor opening, so even if there is an animation set, that
717 // doesn't mean that it goes through the normal app transition cycle so we have
718 // to inform the docked controller about visibility change.
719 // TODO(multi-display): notify docked divider on all displays where visibility was
720 // affected.
Louis Chang37317152019-05-09 09:53:58 +0800721 displayContent.getDockedDividerController().notifyAppVisibilityChanged();
chaviwa953fcf2018-03-01 12:00:39 -0800722
723 // Take the screenshot before possibly hiding the WSA, otherwise the screenshot
724 // will not be taken.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800725 mWmService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible);
chaviwa953fcf2018-03-01 12:00:39 -0800726 }
727
Robert Carre7cc44d2017-03-20 19:04:30 -0700728 // If we are hidden but there is no delay needed we immediately
729 // apply the Surface transaction so that the ActivityManager
Robert Carr61b81112017-07-17 18:08:15 -0700730 // can have some guarantee on the Surface state following
731 // setting the visibility. This captures cases like dismissing
732 // the docked or pinned stack where there is no app transition.
733 //
734 // In the case of a "Null" animation, there will be
735 // no animation but there will still be a transition set.
736 // We still need to delay hiding the surface such that it
737 // can be synchronized with showing the next surface in the transition.
Louis Chang37317152019-05-09 09:53:58 +0800738 if (isHidden() && !delayed && !displayContent.mAppTransition.isTransitionSet()) {
Robert Carr6914f082017-03-20 19:04:30 -0700739 SurfaceControl.openTransaction();
740 for (int i = mChildren.size() - 1; i >= 0; i--) {
741 mChildren.get(i).mWinAnimator.hide("immediately hidden");
742 }
743 SurfaceControl.closeTransaction();
744 }
Garfield Tanb6776602019-02-20 14:44:26 -0800745
746 // Visibility changes may cause orientation request change.
747 reportDescendantOrientationChangeIfNeeded();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700748 }
749
750 return delayed;
751 }
752
Garfield Tanb6776602019-02-20 14:44:26 -0800753 private void reportDescendantOrientationChangeIfNeeded() {
754 // Orientation request is exposed only when we're visible. Therefore visibility change
755 // will change requested orientation. Notify upward the hierarchy ladder to adjust
756 // configuration. This is important to cases where activities with incompatible
757 // orientations launch, or user goes back from an activity of bi-orientation to an
758 // activity with specified orientation.
759 if (mActivityRecord.getRequestedConfigurationOrientation() == getConfiguration().orientation
760 || getOrientationIgnoreVisibility() == SCREEN_ORIENTATION_UNSET) {
761 return;
762 }
763
764 final IBinder freezeToken =
765 mActivityRecord.mayFreezeScreenLocked(mActivityRecord.app)
766 ? mActivityRecord.appToken : null;
767 onDescendantOrientationChanged(freezeToken, mActivityRecord);
768 }
769
Jorim Jaggi87fdbcb2017-08-17 13:41:11 +0200770 /**
771 * @return The to top most child window for which {@link LayoutParams#isFullscreen()} returns
772 * true.
773 */
774 WindowState getTopFullscreenWindow() {
775 for (int i = mChildren.size() - 1; i >= 0; i--) {
776 final WindowState win = mChildren.get(i);
777 if (win != null && win.mAttrs.isFullscreen()) {
778 return win;
779 }
780 }
781 return null;
782 }
783
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800784 WindowState findMainWindow() {
Matthew Ng53e66b22018-01-12 17:13:13 -0800785 return findMainWindow(true);
786 }
787
788 /**
789 * Finds the main window that either has type base application or application starting if
790 * requested.
791 *
792 * @param includeStartingApp Allow to search application-starting windows to also be returned.
793 * @return The main window of type base application or application starting if requested.
794 */
795 WindowState findMainWindow(boolean includeStartingApp) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700796 WindowState candidate = null;
Matthew Ng53e66b22018-01-12 17:13:13 -0800797 for (int j = mChildren.size() - 1; j >= 0; --j) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700798 final WindowState win = mChildren.get(j);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700799 final int type = win.mAttrs.type;
800 // No need to loop through child window as base application and starting types can't be
801 // child windows.
Matthew Ng53e66b22018-01-12 17:13:13 -0800802 if (type == TYPE_BASE_APPLICATION
803 || (includeStartingApp && type == TYPE_APPLICATION_STARTING)) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700804 // In cases where there are multiple windows, we prefer the non-exiting window. This
Sungsoo Lim0d3d1f82015-12-02 14:47:59 +0900805 // happens for example when replacing windows during an activity relaunch. When
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700806 // constructing the animation, we want the new window, not the exiting one.
Wale Ogunwalec48a3542016-02-19 15:18:45 -0800807 if (win.mAnimatingExit) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700808 candidate = win;
809 } else {
810 return win;
811 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800812 }
813 }
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700814 return candidate;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800815 }
816
Wale Ogunwale6cae7652015-12-26 07:36:26 -0800817 boolean windowsAreFocusable() {
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800818 if (mTargetSdk < Build.VERSION_CODES.Q) {
819 final int pid = mActivityRecord != null
820 ? (mActivityRecord.app != null ? mActivityRecord.app.getPid() : 0) : 0;
821 final AppWindowToken topFocusedAppOfMyProcess =
822 mWmService.mRoot.mTopFocusedAppByProcess.get(pid);
823 if (topFocusedAppOfMyProcess != null && topFocusedAppOfMyProcess != this) {
824 // For the apps below Q, there can be only one app which has the focused window per
825 // process, because legacy apps may not be ready for a multi-focus system.
826 return false;
827 }
828 }
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700829 return getWindowConfiguration().canReceiveKeys() || mAlwaysFocusable;
Wale Ogunwaled045c822015-12-02 09:14:28 -0800830 }
831
Wale Ogunwale571771c2016-08-26 13:18:50 -0700832 @Override
Wale Ogunwale44f21802016-09-02 12:49:48 -0700833 boolean isVisible() {
Wale Ogunwalee471be62016-10-03 07:53:55 -0700834 // If the app token isn't hidden then it is considered visible and there is no need to check
835 // its children windows to see if they are visible.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200836 return !isHidden();
Wale Ogunwale44f21802016-09-02 12:49:48 -0700837 }
838
839 @Override
Wale Ogunwalee287e192017-04-21 09:30:12 -0700840 void removeImmediately() {
841 onRemovedFromDisplay();
Yunfan Chen3a77f282018-12-12 15:47:52 -0800842 if (mActivityRecord != null) {
843 mActivityRecord.unregisterConfigurationChangeListener(this);
844 }
Wale Ogunwalee287e192017-04-21 09:30:12 -0700845 super.removeImmediately();
846 }
847
848 @Override
Wale Ogunwale571771c2016-08-26 13:18:50 -0700849 void removeIfPossible() {
Craig Mautnere3119b72015-01-20 15:02:36 -0800850 mIsExiting = false;
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800851 removeAllWindowsIfPossible();
Bryce Lee6d410262017-02-28 15:30:17 -0800852 removeImmediately();
Craig Mautnere3119b72015-01-20 15:02:36 -0800853 }
854
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700855 @Override
856 boolean checkCompleteDeferredRemoval() {
857 if (mIsExiting) {
858 removeIfPossible();
859 }
860 return super.checkCompleteDeferredRemoval();
861 }
862
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700863 void onRemovedFromDisplay() {
Wale Ogunwalee287e192017-04-21 09:30:12 -0700864 if (mRemovingFromDisplay) {
865 return;
866 }
867 mRemovingFromDisplay = true;
868
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700869 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app token: " + this);
870
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800871 boolean delayed = commitVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700872
lumark588a3e82018-07-20 18:53:54 +0800873 getDisplayContent().mOpeningApps.remove(this);
Evan Rosky2289ba12018-11-19 18:28:18 -0800874 getDisplayContent().mChangingApps.remove(this);
lumark588a3e82018-07-20 18:53:54 +0800875 getDisplayContent().mUnknownAppVisibilityController.appRemovedOrHidden(this);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800876 mWmService.mTaskSnapshotController.onAppRemoved(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700877 waitingToShow = false;
lumark588a3e82018-07-20 18:53:54 +0800878 if (getDisplayContent().mClosingApps.contains(this)) {
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700879 delayed = true;
lumark588a3e82018-07-20 18:53:54 +0800880 } else if (getDisplayContent().mAppTransition.isTransitionSet()) {
881 getDisplayContent().mClosingApps.add(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700882 delayed = true;
883 }
884
885 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app " + this + " delayed=" + delayed
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200886 + " animation=" + getAnimation() + " animating=" + isSelfAnimating());
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700887
888 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: "
889 + this + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
890
chaviwa8f07a72019-05-01 16:25:39 -0700891 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800892 removeStartingWindow();
Jorim Jaggi19be6052017-08-03 18:33:43 +0200893 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800894
Winson Chung87e5d552017-04-05 11:49:38 -0700895 // If this window was animating, then we need to ensure that the app transition notifies
lumark588a3e82018-07-20 18:53:54 +0800896 // that animations have completed in DisplayContent.handleAnimatingStoppedAndTransition(),
897 // so add to that list now
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200898 if (isSelfAnimating()) {
lumark588a3e82018-07-20 18:53:54 +0800899 getDisplayContent().mNoAnimationNotifyOnTransitionFinished.add(token);
Winson Chung87e5d552017-04-05 11:49:38 -0700900 }
901
Wale Ogunwalee287e192017-04-21 09:30:12 -0700902 final TaskStack stack = getStack();
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700903 if (delayed && !isEmpty()) {
904 // set the token aside because it has an active animation to be finished
905 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM,
906 "removeAppToken make exiting: " + this);
Wale Ogunwalee287e192017-04-21 09:30:12 -0700907 if (stack != null) {
908 stack.mExitingAppTokens.add(this);
909 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700910 mIsExiting = true;
911 } else {
912 // Make sure there is no animation running on this token, so any windows associated
913 // with it will be removed as soon as their animations are complete
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200914 cancelAnimation();
Wale Ogunwale3106ae012017-05-16 08:56:37 -0700915 if (stack != null) {
916 stack.mExitingAppTokens.remove(this);
917 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700918 removeIfPossible();
919 }
920
921 removed = true;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700922 stopFreezingScreen(true, true);
Bryce Lee6d410262017-02-28 15:30:17 -0800923
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800924 final DisplayContent dc = getDisplayContent();
925 if (dc.mFocusedApp == this) {
926 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + this
927 + " displayId=" + dc.getDisplayId());
928 dc.setFocusedApp(null);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800929 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700930 }
Riddle Hsu192fe762019-01-15 23:41:57 +0800931 if (mLetterbox != null) {
932 mLetterbox.destroy();
933 mLetterbox = null;
934 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700935
936 if (!delayed) {
937 updateReportedVisibilityLocked();
938 }
Wale Ogunwalee287e192017-04-21 09:30:12 -0700939
940 mRemovingFromDisplay = false;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700941 }
942
Chong Zhange05bcb12016-07-26 17:47:29 -0700943 void clearAnimatingFlags() {
Chong Zhangb0d26702016-08-12 16:03:29 -0700944 boolean wallpaperMightChange = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700945 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700946 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700947 wallpaperMightChange |= win.clearAnimatingFlags();
Chong Zhange05bcb12016-07-26 17:47:29 -0700948 }
Chong Zhangb0d26702016-08-12 16:03:29 -0700949 if (wallpaperMightChange) {
950 requestUpdateWallpaperIfNeeded();
951 }
Chong Zhange05bcb12016-07-26 17:47:29 -0700952 }
953
Robert Carre12aece2016-02-02 22:43:27 -0800954 void destroySurfaces() {
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700955 destroySurfaces(false /*cleanupOnResume*/);
956 }
957
958 /**
959 * Destroy surfaces which have been marked as eligible by the animator, taking care to ensure
960 * the client has finished with them.
961 *
962 * @param cleanupOnResume whether this is done when app is resumed without fully stopped. If
963 * set to true, destroy only surfaces of removed windows, and clear relevant flags of the
964 * others so that they are ready to be reused. If set to false (common case), destroy all
965 * surfaces that's eligible, if the app is already stopped.
966 */
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700967 private void destroySurfaces(boolean cleanupOnResume) {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700968 boolean destroyedSomething = false;
Jorim Jaggia5e10572017-11-15 14:36:26 +0100969
970 // Copying to a different list as multiple children can be removed.
Jorim Jaggi59f3e922018-01-05 15:40:32 +0100971 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
Jorim Jaggia5e10572017-11-15 14:36:26 +0100972 for (int i = children.size() - 1; i >= 0; i--) {
973 final WindowState win = children.get(i);
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700974 destroyedSomething |= win.destroySurface(cleanupOnResume, mAppStopped);
Robert Carre12aece2016-02-02 22:43:27 -0800975 }
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700976 if (destroyedSomething) {
977 final DisplayContent dc = getDisplayContent();
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700978 dc.assignWindowLayers(true /*setLayoutNeeded*/);
Adrian Roos23df3a32018-03-15 15:41:13 +0100979 updateLetterboxSurface(null);
Robert Carre12aece2016-02-02 22:43:27 -0800980 }
981 }
982
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800983 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700984 * Notify that the app is now resumed, and it was not stopped before, perform a clean
985 * up of the surfaces
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800986 */
Jorim Jaggibae01b12017-04-11 16:29:10 -0700987 void notifyAppResumed(boolean wasStopped) {
Chong Zhangad24f962016-08-25 12:12:33 -0700988 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppResumed: wasStopped=" + wasStopped
Jorim Jaggibae01b12017-04-11 16:29:10 -0700989 + " " + this);
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700990 mAppStopped = false;
chaviwd3bf08d2017-08-01 17:24:59 -0700991 // Allow the window to turn the screen on once the app is resumed again.
992 setCanTurnScreenOn(true);
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700993 if (!wasStopped) {
994 destroySurfaces(true /*cleanupOnResume*/);
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800995 }
Robert Carre12aece2016-02-02 22:43:27 -0800996 }
997
Chong Zhangbef461f2015-10-27 11:38:24 -0700998 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700999 * Notify that the app has stopped, and it is okay to destroy any surfaces which were
1000 * keeping alive in case they were still being used.
1001 */
1002 void notifyAppStopped() {
1003 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: " + this);
1004 mAppStopped = true;
1005 destroySurfaces();
1006 // Remove any starting window that was added for this app if they are still around.
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001007 removeStartingWindow();
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001008 }
1009
Chong Zhang92147042016-05-09 12:47:11 -07001010 void clearAllDrawn() {
1011 allDrawn = false;
1012 deferClearAllDrawn = false;
Chong Zhangbef461f2015-10-27 11:38:24 -07001013 }
1014
Bryce Lee6d410262017-02-28 15:30:17 -08001015 Task getTask() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001016 return (Task) getParent();
Bryce Lee6d410262017-02-28 15:30:17 -08001017 }
1018
Jorim Jaggi3878ca32017-02-02 17:13:05 -08001019 TaskStack getStack() {
1020 final Task task = getTask();
1021 if (task != null) {
1022 return task.mStack;
1023 } else {
1024 return null;
1025 }
1026 }
1027
Bryce Lee6d410262017-02-28 15:30:17 -08001028 @Override
Riddle Hsu3a4bb612019-01-31 00:02:22 +08001029 void onParentChanged() {
1030 super.onParentChanged();
Bryce Lee6d410262017-02-28 15:30:17 -08001031
Robert Carred3e83b2017-04-21 13:26:55 -07001032 final Task task = getTask();
1033
Bryce Lee6d410262017-02-28 15:30:17 -08001034 // When the associated task is {@code null}, the {@link AppWindowToken} can no longer
1035 // access visual elements like the {@link DisplayContent}. We must remove any associations
1036 // such as animations.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001037 if (!mReparenting) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001038 if (task == null) {
1039 // It is possible we have been marked as a closing app earlier. We must remove ourselves
1040 // from this list so we do not participate in any future animations.
lumark588a3e82018-07-20 18:53:54 +08001041 getDisplayContent().mClosingApps.remove(this);
Robert Carred3e83b2017-04-21 13:26:55 -07001042 } else if (mLastParent != null && mLastParent.mStack != null) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001043 task.mStack.mExitingAppTokens.remove(this);
1044 }
Bryce Lee6d410262017-02-28 15:30:17 -08001045 }
Jorim Jaggi6de61012018-03-19 14:53:23 +01001046 final TaskStack stack = getStack();
1047
1048 // If we reparent, make sure to remove ourselves from the old animation registry.
1049 if (mAnimatingAppWindowTokenRegistry != null) {
1050 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
1051 }
1052 mAnimatingAppWindowTokenRegistry = stack != null
1053 ? stack.getAnimatingAppWindowTokenRegistry()
1054 : null;
1055
Robert Carred3e83b2017-04-21 13:26:55 -07001056 mLastParent = task;
chaviwdcf76ec2019-01-11 16:48:46 -08001057
1058 updateColorTransform();
Bryce Lee6d410262017-02-28 15:30:17 -08001059 }
1060
Wale Ogunwalefa854eb2016-09-20 13:43:52 -07001061 void postWindowRemoveStartingWindowCleanup(WindowState win) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001062 // TODO: Something smells about the code below...Is there a better way?
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001063 if (startingWindow == win) {
1064 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Notify removed startingWindow " + win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001065 removeStartingWindow();
Wale Ogunwale6c459212017-05-17 08:56:03 -07001066 } else if (mChildren.size() == 0) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001067 // If this is the last window and we had requested a starting transition window,
1068 // well there is no point now.
Jorim Jaggi02886a82016-12-06 09:10:06 -08001069 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Nulling last startingData");
chaviwa8f07a72019-05-01 16:25:39 -07001070 mStartingData = null;
Wale Ogunwale6c459212017-05-17 08:56:03 -07001071 if (mHiddenSetFromTransferredStartingWindow) {
1072 // We set the hidden state to false for the token from a transferred starting window.
1073 // We now reset it back to true since the starting window was the last window in the
1074 // token.
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001075 setHidden(true);
Wale Ogunwale6c459212017-05-17 08:56:03 -07001076 }
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01001077 } else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001078 // If this is the last window except for a starting transition window,
1079 // we need to get rid of the starting transition.
Jorim Jaggie4b0f282017-05-17 15:10:29 +02001080 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Last window, removing starting window "
1081 + win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001082 removeStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001083 }
1084 }
1085
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001086 void removeDeadWindows() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001087 for (int winNdx = mChildren.size() - 1; winNdx >= 0; --winNdx) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001088 WindowState win = mChildren.get(winNdx);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001089 if (win.mAppDied) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001090 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.w(TAG,
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001091 "removeDeadWindows: " + win);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001092 // Set mDestroying, we don't want any animation or delayed removal here.
1093 win.mDestroying = true;
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001094 // Also removes child windows.
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001095 win.removeIfPossible();
Chong Zhang112eb8c2015-11-02 11:17:00 -08001096 }
1097 }
1098 }
1099
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001100 boolean hasWindowsAlive() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001101 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001102 // No need to loop through child windows as the answer should be the same as that of the
1103 // parent window.
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001104 if (!(mChildren.get(i)).mAppDied) {
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001105 return true;
1106 }
1107 }
1108 return false;
1109 }
1110
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001111 void setWillReplaceWindows(boolean animate) {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001112 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
1113 "Marking app token " + this + " with replacing windows.");
Robert Carra1eb4392015-12-10 12:43:51 -08001114
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001115 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001116 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001117 w.setWillReplaceWindow(animate);
Robert Carra1eb4392015-12-10 12:43:51 -08001118 }
Robert Carra1eb4392015-12-10 12:43:51 -08001119 }
1120
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001121 void setWillReplaceChildWindows() {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001122 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Marking app token " + this
Robert Carr23fa16b2016-01-13 13:19:58 -08001123 + " with replacing child windows.");
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001124 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001125 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001126 w.setWillReplaceChildWindows();
Robert Carr23fa16b2016-01-13 13:19:58 -08001127 }
1128 }
1129
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001130 void clearWillReplaceWindows() {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001131 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
1132 "Resetting app token " + this + " of replacing window marks.");
Chong Zhangf596cd52016-01-05 13:42:44 -08001133
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001134 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001135 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001136 w.clearWillReplaceWindow();
Chong Zhangf596cd52016-01-05 13:42:44 -08001137 }
1138 }
1139
Chong Zhang4d7369a2016-04-25 16:09:14 -07001140 void requestUpdateWallpaperIfNeeded() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001141 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001142 final WindowState w = mChildren.get(i);
Chong Zhang4d7369a2016-04-25 16:09:14 -07001143 w.requestUpdateWallpaperIfNeeded();
1144 }
1145 }
1146
Chong Zhangd78ddb42016-03-02 17:01:14 -08001147 boolean isRelaunching() {
1148 return mPendingRelaunchCount > 0;
1149 }
1150
Robert Carr68375192017-06-13 12:41:53 -07001151 boolean shouldFreezeBounds() {
1152 final Task task = getTask();
1153
1154 // For freeform windows, we can't freeze the bounds at the moment because this would make
1155 // the resizing unresponsive.
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001156 if (task == null || task.inFreeformWindowingMode()) {
Robert Carr68375192017-06-13 12:41:53 -07001157 return false;
1158 }
1159
1160 // We freeze the bounds while drag resizing to deal with the time between
1161 // the divider/drag handle being released, and the handling it's new
1162 // configuration. If we are relaunched outside of the drag resizing state,
1163 // we need to be careful not to do this.
1164 return getTask().isDragResizing();
1165 }
1166
Chong Zhangd78ddb42016-03-02 17:01:14 -08001167 void startRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001168 if (shouldFreezeBounds()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08001169 freezeBounds();
1170 }
Robert Carrd5c7dd62017-03-08 10:39:30 -08001171
1172 // In the process of tearing down before relaunching, the app will
1173 // try and clean up it's child surfaces. We need to prevent this from
1174 // happening, so we sever the children, transfering their ownership
1175 // from the client it-self to the parent surface (owned by us).
Robert Carr29daa922018-04-27 11:56:48 -07001176 detachChildren();
1177
1178 mPendingRelaunchCount++;
1179 }
1180
1181 void detachChildren() {
Robert Carrfd8e93b2018-05-10 13:40:25 -07001182 SurfaceControl.openTransaction();
Robert Carrd5c7dd62017-03-08 10:39:30 -08001183 for (int i = mChildren.size() - 1; i >= 0; i--) {
1184 final WindowState w = mChildren.get(i);
1185 w.mWinAnimator.detachChildren();
1186 }
Robert Carrfd8e93b2018-05-10 13:40:25 -07001187 SurfaceControl.closeTransaction();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001188 }
1189
1190 void finishRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001191 unfreezeBounds();
1192
Chong Zhangd78ddb42016-03-02 17:01:14 -08001193 if (mPendingRelaunchCount > 0) {
1194 mPendingRelaunchCount--;
Bryce Lee081554b2017-05-25 07:52:12 -07001195 } else {
1196 // Update keyguard flags upon finishing relaunch.
1197 checkKeyguardFlagsChanged();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001198 }
1199 }
1200
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001201 void clearRelaunching() {
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001202 if (mPendingRelaunchCount == 0) {
1203 return;
1204 }
Robert Carr68375192017-06-13 12:41:53 -07001205 unfreezeBounds();
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001206 mPendingRelaunchCount = 0;
1207 }
1208
Wale Ogunwale07bcab72016-10-14 15:30:09 -07001209 /**
1210 * Returns true if the new child window we are adding to this token is considered greater than
1211 * the existing child window in this token in terms of z-order.
1212 */
1213 @Override
1214 protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
1215 WindowState existingWindow) {
1216 final int type1 = newWindow.mAttrs.type;
1217 final int type2 = existingWindow.mAttrs.type;
1218
1219 // Base application windows should be z-ordered BELOW all other windows in the app token.
1220 if (type1 == TYPE_BASE_APPLICATION && type2 != TYPE_BASE_APPLICATION) {
1221 return false;
1222 } else if (type1 != TYPE_BASE_APPLICATION && type2 == TYPE_BASE_APPLICATION) {
1223 return true;
1224 }
1225
1226 // Starting windows should be z-ordered ABOVE all other windows in the app token.
1227 if (type1 == TYPE_APPLICATION_STARTING && type2 != TYPE_APPLICATION_STARTING) {
1228 return true;
1229 } else if (type1 != TYPE_APPLICATION_STARTING && type2 == TYPE_APPLICATION_STARTING) {
1230 return false;
1231 }
1232
1233 // Otherwise the new window is greater than the existing window.
1234 return true;
1235 }
1236
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001237 @Override
Robert Carra1eb4392015-12-10 12:43:51 -08001238 void addWindow(WindowState w) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001239 super.addWindow(w);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001240
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001241 boolean gotReplacementWindow = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001242 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001243 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001244 gotReplacementWindow |= candidate.setReplacementWindowIfNeeded(w);
1245 }
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001246
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001247 // if we got a replacement window, reset the timeout to give drawing more time
1248 if (gotReplacementWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001249 mWmService.scheduleWindowReplacementTimeouts(this);
Robert Carra1eb4392015-12-10 12:43:51 -08001250 }
Jorim Jaggife762342016-10-13 14:33:27 +02001251 checkKeyguardFlagsChanged();
1252 }
1253
1254 @Override
1255 void removeChild(WindowState child) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001256 if (!mChildren.contains(child)) {
1257 // This can be true when testing.
1258 return;
1259 }
Jorim Jaggife762342016-10-13 14:33:27 +02001260 super.removeChild(child);
1261 checkKeyguardFlagsChanged();
Adrian Roos23df3a32018-03-15 15:41:13 +01001262 updateLetterboxSurface(child);
Robert Carra1eb4392015-12-10 12:43:51 -08001263 }
1264
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001265 private boolean waitingForReplacement() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001266 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001267 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001268 if (candidate.waitingForReplacement()) {
Robert Carra1eb4392015-12-10 12:43:51 -08001269 return true;
1270 }
1271 }
1272 return false;
1273 }
1274
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001275 void onWindowReplacementTimeout() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001276 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001277 (mChildren.get(i)).onWindowReplacementTimeout();
Robert Carra1eb4392015-12-10 12:43:51 -08001278 }
1279 }
1280
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001281 void reparent(Task task, int position) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001282 if (DEBUG_ADD_REMOVE) {
1283 Slog.i(TAG_WM, "reparent: moving app token=" + this
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001284 + " to task=" + task.mTaskId + " at " + position);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001285 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001286 if (task == null) {
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001287 throw new IllegalArgumentException("reparent: could not find task");
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001288 }
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001289 final Task currentTask = getTask();
1290 if (task == currentTask) {
Winson Chung30480042017-01-26 10:55:34 -08001291 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001292 "window token=" + this + " already child of task=" + currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001293 }
Bryce Lee6d410262017-02-28 15:30:17 -08001294
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001295 if (currentTask.mStack != task.mStack) {
Bryce Lee6d410262017-02-28 15:30:17 -08001296 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001297 "window token=" + this + " current task=" + currentTask
Bryce Lee6d410262017-02-28 15:30:17 -08001298 + " belongs to a different stack than " + task);
1299 }
1300
Winson Chung30480042017-01-26 10:55:34 -08001301 if (DEBUG_ADD_REMOVE) Slog.i(TAG, "reParentWindowToken: removing window token=" + this
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001302 + " from task=" + currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001303 final DisplayContent prevDisplayContent = getDisplayContent();
1304
Bryce Lee6d410262017-02-28 15:30:17 -08001305 mReparenting = true;
1306
Winson Chung30480042017-01-26 10:55:34 -08001307 getParent().removeChild(this);
1308 task.addChild(this, position);
1309
Bryce Lee6d410262017-02-28 15:30:17 -08001310 mReparenting = false;
1311
Winson Chung30480042017-01-26 10:55:34 -08001312 // Relayout display(s).
1313 final DisplayContent displayContent = task.getDisplayContent();
1314 displayContent.setLayoutNeeded();
1315 if (prevDisplayContent != displayContent) {
1316 onDisplayChanged(displayContent);
1317 prevDisplayContent.setLayoutNeeded();
1318 }
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001319 getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
Winson Chung30480042017-01-26 10:55:34 -08001320 }
1321
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001322 @Override
1323 void onDisplayChanged(DisplayContent dc) {
1324 DisplayContent prevDc = mDisplayContent;
1325 super.onDisplayChanged(dc);
Evan Roskyb1e75f72019-04-26 20:23:26 -07001326 if (prevDc == null || prevDc == mDisplayContent) {
Evan Rosky25b56192019-02-06 16:10:56 -08001327 return;
1328 }
Wale Ogunwaleb8e6b632019-06-28 15:19:25 +00001329
1330 if (prevDc.mOpeningApps.remove(this)) {
1331 // Transfer opening transition to new display.
1332 mDisplayContent.mOpeningApps.add(this);
1333 mDisplayContent.prepareAppTransition(prevDc.mAppTransition.getAppTransition(), true);
1334 mDisplayContent.executeAppTransition();
1335 }
1336
1337 if (prevDc.mChangingApps.remove(this)) {
Evan Rosky25b56192019-02-06 16:10:56 -08001338 // This gets called *after* the AppWindowToken has been reparented to the new display.
1339 // That reparenting resulted in this window changing modes (eg. FREEFORM -> FULLSCREEN),
1340 // so this token is now "frozen" while waiting for the animation to start on prevDc
1341 // (which will be cancelled since the window is no-longer a child). However, since this
1342 // is no longer a child of prevDc, this won't be notified of the cancelled animation,
1343 // so we need to cancel the change transition here.
1344 clearChangeLeash(getPendingTransaction(), true /* cancel */);
1345 }
Wale Ogunwaleb8e6b632019-06-28 15:19:25 +00001346 prevDc.mClosingApps.remove(this);
1347
Evan Rosky25b56192019-02-06 16:10:56 -08001348 if (prevDc.mFocusedApp == this) {
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001349 prevDc.setFocusedApp(null);
lumarkbf844642018-11-23 17:11:36 +08001350 final TaskStack stack = dc.getTopStack();
1351 if (stack != null) {
1352 final Task task = stack.getTopChild();
1353 if (task != null && task.getTopChild() == this) {
1354 dc.setFocusedApp(this);
1355 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001356 }
1357 }
Riddle Hsu192fe762019-01-15 23:41:57 +08001358
Evan Roskyb1e75f72019-04-26 20:23:26 -07001359 if (mLetterbox != null) {
Riddle Hsu192fe762019-01-15 23:41:57 +08001360 mLetterbox.onMovedToDisplay(mDisplayContent.getDisplayId());
1361 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001362 }
1363
Jorim Jaggi0429f352015-12-22 16:29:16 +01001364 /**
1365 * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds
1366 * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even
1367 * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen
1368 * with a queue.
1369 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001370 private void freezeBounds() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001371 final Task task = getTask();
1372 mFrozenBounds.offer(new Rect(task.mPreparedFrozenBounds));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001373
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001374 if (task.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001375 // We didn't call prepareFreezingBounds on the task, so use the current value.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001376 mFrozenMergedConfig.offer(new Configuration(task.getConfiguration()));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001377 } else {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001378 mFrozenMergedConfig.offer(new Configuration(task.mPreparedFrozenMergedConfig));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001379 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001380 // Calling unset() to make it equal to Configuration.EMPTY.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001381 task.mPreparedFrozenMergedConfig.unset();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001382 }
1383
1384 /**
1385 * Unfreezes the previously frozen bounds. See {@link #freezeBounds}.
1386 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001387 private void unfreezeBounds() {
Robert Carr68375192017-06-13 12:41:53 -07001388 if (mFrozenBounds.isEmpty()) {
1389 return;
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001390 }
Robert Carr68375192017-06-13 12:41:53 -07001391 mFrozenBounds.remove();
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001392 if (!mFrozenMergedConfig.isEmpty()) {
1393 mFrozenMergedConfig.remove();
1394 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001395 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001396 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001397 win.onUnfreezeBounds();
Jorim Jaggi4846ee32016-01-07 17:39:12 +01001398 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001399 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001400 }
1401
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001402 void setAppLayoutChanges(int changes, String reason) {
1403 if (!mChildren.isEmpty()) {
1404 final DisplayContent dc = getDisplayContent();
1405 dc.pendingLayoutChanges |= changes;
1406 if (DEBUG_LAYOUT_REPEATS) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001407 mWmService.mWindowPlacerLocked.debugLayoutRepeats(reason, dc.pendingLayoutChanges);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001408 }
1409 }
1410 }
1411
1412 void removeReplacedWindowIfNeeded(WindowState replacement) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001413 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001414 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001415 if (win.removeReplacedWindowIfNeeded(replacement)) {
1416 return;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001417 }
1418 }
1419 }
1420
1421 void startFreezingScreen() {
1422 if (DEBUG_ORIENTATION) logWithStack(TAG, "Set freezing of " + appToken + ": hidden="
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001423 + isHidden() + " freezing=" + mFreezingScreen + " hiddenRequested="
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001424 + hiddenRequested);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001425 if (!hiddenRequested) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001426 if (!mFreezingScreen) {
1427 mFreezingScreen = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001428 mWmService.registerAppFreezeListener(this);
1429 mWmService.mAppsFreezingScreen++;
1430 if (mWmService.mAppsFreezingScreen == 1) {
1431 mWmService.startFreezingDisplayLocked(0, 0, getDisplayContent());
1432 mWmService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
1433 mWmService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001434 }
1435 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001436 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001437 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001438 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001439 w.onStartFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001440 }
1441 }
1442 }
1443
1444 void stopFreezingScreen(boolean unfreezeSurfaceNow, boolean force) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001445 if (!mFreezingScreen) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001446 return;
1447 }
1448 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + this + " force=" + force);
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001449 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001450 boolean unfrozeWindows = false;
1451 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001452 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001453 unfrozeWindows |= w.onStopFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001454 }
1455 if (force || unfrozeWindows) {
1456 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "No longer freezing: " + this);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001457 mFreezingScreen = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001458 mWmService.unregisterAppFreezeListener(this);
1459 mWmService.mAppsFreezingScreen--;
1460 mWmService.mLastFinishedFreezeSource = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001461 }
1462 if (unfreezeSurfaceNow) {
1463 if (unfrozeWindows) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001464 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001465 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001466 mWmService.stopFreezingDisplayLocked();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001467 }
1468 }
1469
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001470 @Override
1471 public void onAppFreezeTimeout() {
1472 Slog.w(TAG_WM, "Force clearing freeze: " + this);
1473 stopFreezingScreen(true, true);
1474 }
1475
Jorim Jaggi60f9c972018-02-01 19:21:07 +01001476 /**
1477 * Tries to transfer the starting window from a token that's above ourselves in the task but
1478 * not visible anymore. This is a common scenario apps use: Trampoline activity T start main
1479 * activity M in the same task. Now, when reopening the task, T starts on top of M but then
1480 * immediately finishes after, so we have to transfer T to M.
1481 */
1482 void transferStartingWindowFromHiddenAboveTokenIfNeeded() {
1483 final Task task = getTask();
1484 for (int i = task.mChildren.size() - 1; i >= 0; i--) {
1485 final AppWindowToken fromToken = task.mChildren.get(i);
1486 if (fromToken == this) {
1487 return;
1488 }
1489 if (fromToken.hiddenRequested && transferStartingWindow(fromToken.token)) {
1490 return;
1491 }
1492 }
1493 }
1494
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001495 boolean transferStartingWindow(IBinder transferFrom) {
Wale Ogunwale02319a62016-09-26 15:21:22 -07001496 final AppWindowToken fromToken = getDisplayContent().getAppWindowToken(transferFrom);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001497 if (fromToken == null) {
1498 return false;
1499 }
1500
1501 final WindowState tStartingWindow = fromToken.startingWindow;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08001502 if (tStartingWindow != null && fromToken.startingSurface != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001503 // In this case, the starting icon has already been displayed, so start
1504 // letting windows get shown immediately without any more transitions.
lumark588a3e82018-07-20 18:53:54 +08001505 getDisplayContent().mSkipAppTransitionAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001506
1507 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Moving existing starting " + tStartingWindow
1508 + " from " + fromToken + " to " + this);
1509
1510 final long origId = Binder.clearCallingIdentity();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001511 try {
1512 // Transfer the starting window over to the new token.
chaviwa8f07a72019-05-01 16:25:39 -07001513 mStartingData = fromToken.mStartingData;
Peter Visontay3556a3b2017-11-01 17:23:17 +00001514 startingSurface = fromToken.startingSurface;
1515 startingDisplayed = fromToken.startingDisplayed;
1516 fromToken.startingDisplayed = false;
1517 startingWindow = tStartingWindow;
1518 reportedVisible = fromToken.reportedVisible;
chaviwa8f07a72019-05-01 16:25:39 -07001519 fromToken.mStartingData = null;
Peter Visontay3556a3b2017-11-01 17:23:17 +00001520 fromToken.startingSurface = null;
1521 fromToken.startingWindow = null;
1522 fromToken.startingMoved = true;
1523 tStartingWindow.mToken = this;
1524 tStartingWindow.mAppToken = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001525
Peter Visontay3556a3b2017-11-01 17:23:17 +00001526 if (DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
1527 "Removing starting " + tStartingWindow + " from " + fromToken);
1528 fromToken.removeChild(tStartingWindow);
1529 fromToken.postWindowRemoveStartingWindowCleanup(tStartingWindow);
1530 fromToken.mHiddenSetFromTransferredStartingWindow = false;
1531 addWindow(tStartingWindow);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001532
Peter Visontay3556a3b2017-11-01 17:23:17 +00001533 // Propagate other interesting state between the tokens. If the old token is displayed,
1534 // we should immediately force the new one to be displayed. If it is animating, we need
1535 // to move that animation to the new one.
1536 if (fromToken.allDrawn) {
1537 allDrawn = true;
1538 deferClearAllDrawn = fromToken.deferClearAllDrawn;
1539 }
1540 if (fromToken.firstWindowDrawn) {
1541 firstWindowDrawn = true;
1542 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001543 if (!fromToken.isHidden()) {
1544 setHidden(false);
Peter Visontay3556a3b2017-11-01 17:23:17 +00001545 hiddenRequested = false;
1546 mHiddenSetFromTransferredStartingWindow = true;
1547 }
1548 setClientHidden(fromToken.mClientHidden);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001549
Jorim Jaggi980c9de2017-11-17 01:41:37 +01001550 transferAnimation(fromToken);
1551
1552 // When transferring an animation, we no longer need to apply an animation to the
Tiger Huangc9d0d002019-05-29 22:55:29 +08001553 // the token we transfer the animation over. Thus, set this flag to indicate we've
1554 // transferred the animation.
1555 mUseTransferredAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001556
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001557 mWmService.updateFocusedWindowLocked(
Peter Visontay3556a3b2017-11-01 17:23:17 +00001558 UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/);
1559 getDisplayContent().setLayoutNeeded();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001560 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001561 } finally {
1562 Binder.restoreCallingIdentity(origId);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001563 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001564 return true;
chaviwa8f07a72019-05-01 16:25:39 -07001565 } else if (fromToken.mStartingData != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001566 // The previous app was getting ready to show a
1567 // starting window, but hasn't yet done so. Steal it!
1568 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
1569 "Moving pending starting from " + fromToken + " to " + this);
chaviwa8f07a72019-05-01 16:25:39 -07001570 mStartingData = fromToken.mStartingData;
1571 fromToken.mStartingData = null;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001572 fromToken.startingMoved = true;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001573 scheduleAddStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001574 return true;
1575 }
1576
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001577 // TODO: Transfer thumbnail
1578
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001579 return false;
1580 }
1581
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001582 boolean isLastWindow(WindowState win) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001583 return mChildren.size() == 1 && mChildren.get(0) == win;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001584 }
1585
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001586 @Override
1587 void onAppTransitionDone() {
1588 sendingToBottom = false;
1589 }
1590
Wale Ogunwale51362492016-09-08 17:49:17 -07001591 /**
1592 * We override because this class doesn't want its children affecting its reported orientation
1593 * in anyway.
1594 */
1595 @Override
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001596 int getOrientation(int candidate) {
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001597 if (candidate == SCREEN_ORIENTATION_BEHIND) {
1598 // Allow app to specify orientation regardless of its visibility state if the current
1599 // candidate want us to use orientation behind. I.e. the visible app on-top of this one
1600 // wants us to use the orientation of the app behind it.
1601 return mOrientation;
1602 }
1603
Bryce Lee61fbcbc2017-03-10 14:14:03 -08001604 // The {@link AppWindowToken} should only specify an orientation when it is not closing or
1605 // going to the bottom. Allowing closing {@link AppWindowToken} to participate can lead to
1606 // an Activity in another task being started in the wrong orientation during the transition.
lumark588a3e82018-07-20 18:53:54 +08001607 if (!(sendingToBottom || getDisplayContent().mClosingApps.contains(this))
1608 && (isVisible() || getDisplayContent().mOpeningApps.contains(this))) {
Bryce Leea163b762017-01-24 11:05:01 -08001609 return mOrientation;
Wale Ogunwale51362492016-09-08 17:49:17 -07001610 }
Bryce Leea163b762017-01-24 11:05:01 -08001611
1612 return SCREEN_ORIENTATION_UNSET;
Wale Ogunwale51362492016-09-08 17:49:17 -07001613 }
1614
Wale Ogunwaleb198b742016-12-01 08:44:09 -08001615 /** Returns the app's preferred orientation regardless of its currently visibility state. */
1616 int getOrientationIgnoreVisibility() {
1617 return mOrientation;
1618 }
1619
Riddle Hsub398da32019-01-21 21:48:16 +08001620 /** @return {@code true} if the compatibility bounds is taking effect. */
1621 boolean inSizeCompatMode() {
1622 return mSizeCompatBounds != null;
1623 }
1624
1625 @Override
1626 float getSizeCompatScale() {
1627 return inSizeCompatMode() ? mSizeCompatScale : super.getSizeCompatScale();
1628 }
1629
1630 /**
1631 * @return Non-empty bounds if the activity has override bounds.
1632 * @see ActivityRecord#resolveOverrideConfiguration(Configuration)
1633 */
1634 Rect getResolvedOverrideBounds() {
1635 // Get bounds from resolved override configuration because it is computed with orientation.
1636 return getResolvedOverrideConfiguration().windowConfiguration.getBounds();
1637 }
1638
Craig Mautnerdbb79912012-03-01 18:59:14 -08001639 @Override
Winson Chunge55c0192017-08-24 14:50:48 -07001640 public void onConfigurationChanged(Configuration newParentConfig) {
1641 final int prevWinMode = getWindowingMode();
Evan Rosky2289ba12018-11-19 18:28:18 -08001642 mTmpPrevBounds.set(getBounds());
Winson Chunge55c0192017-08-24 14:50:48 -07001643 super.onConfigurationChanged(newParentConfig);
Riddle Hsub398da32019-01-21 21:48:16 +08001644
1645 final Task task = getTask();
1646 final Rect overrideBounds = getResolvedOverrideBounds();
1647 if (task != null && !overrideBounds.isEmpty()
1648 // If the changes come from change-listener, the incoming parent configuration is
1649 // still the old one. Make sure their orientations are the same to reduce computing
1650 // the compatibility bounds for the intermediate state.
Riddle Hsu04164182019-03-07 18:03:27 +08001651 && (task.mTaskRecord == null || task.mTaskRecord
1652 .getConfiguration().orientation == newParentConfig.orientation)) {
Riddle Hsub398da32019-01-21 21:48:16 +08001653 final Rect taskBounds = task.getBounds();
1654 // Since we only center the activity horizontally, if only the fixed height is smaller
1655 // than its container, the override bounds don't need to take effect.
1656 if ((overrideBounds.width() != taskBounds.width()
1657 || overrideBounds.height() > taskBounds.height())) {
1658 calculateCompatBoundsTransformation(newParentConfig);
1659 updateSurfacePosition();
1660 } else if (mSizeCompatBounds != null) {
1661 mSizeCompatBounds = null;
1662 mSizeCompatScale = 1f;
1663 updateSurfacePosition();
1664 }
1665 }
1666
Winson Chunge55c0192017-08-24 14:50:48 -07001667 final int winMode = getWindowingMode();
1668
1669 if (prevWinMode == winMode) {
1670 return;
1671 }
1672
1673 if (prevWinMode != WINDOWING_MODE_UNDEFINED && winMode == WINDOWING_MODE_PINNED) {
1674 // Entering PiP from fullscreen, reset the snap fraction
1675 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(this);
Winson Chung82267ce2018-04-06 16:38:26 -07001676 } else if (prevWinMode == WINDOWING_MODE_PINNED && winMode != WINDOWING_MODE_UNDEFINED
1677 && !isHidden()) {
Winson Chunge55c0192017-08-24 14:50:48 -07001678 // Leaving PiP to fullscreen, save the snap fraction based on the pre-animation bounds
1679 // for the next re-entry into PiP (assuming the activity is not hidden or destroyed)
1680 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
1681 if (pinnedStack != null) {
Winson Chung8efa1652018-06-06 09:34:23 -07001682 final Rect stackBounds;
1683 if (pinnedStack.lastAnimatingBoundsWasToFullscreen()) {
1684 // We are animating the bounds, use the pre-animation bounds to save the snap
1685 // fraction
1686 stackBounds = pinnedStack.mPreAnimationBounds;
1687 } else {
1688 // We skip the animation if the fullscreen configuration is not compatible, so
1689 // use the current bounds to calculate the saved snap fraction instead
1690 // (see PinnedActivityStack.skipResizeAnimation())
1691 stackBounds = mTmpRect;
1692 pinnedStack.getBounds(stackBounds);
1693 }
Winson Chunge55c0192017-08-24 14:50:48 -07001694 mDisplayContent.mPinnedStackControllerLocked.saveReentrySnapFraction(this,
Winson Chung8efa1652018-06-06 09:34:23 -07001695 stackBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001696 }
Evan Rosky2289ba12018-11-19 18:28:18 -08001697 } else if (shouldStartChangeTransition(prevWinMode, winMode)) {
1698 initializeChangeTransition(mTmpPrevBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001699 }
1700 }
1701
Evan Rosky2289ba12018-11-19 18:28:18 -08001702 private boolean shouldStartChangeTransition(int prevWinMode, int newWinMode) {
Evan Rosky25b56192019-02-06 16:10:56 -08001703 if (mWmService.mDisableTransitionAnimation
1704 || !isVisible()
1705 || getDisplayContent().mAppTransition.isTransitionSet()
1706 || getSurfaceControl() == null) {
Evan Rosky2289ba12018-11-19 18:28:18 -08001707 return false;
1708 }
1709 // Only do an animation into and out-of freeform mode for now. Other mode
1710 // transition animations are currently handled by system-ui.
1711 return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
1712 }
1713
1714 /**
1715 * Initializes a change transition. Because the app is visible already, there is a small period
1716 * of time where the user can see the app content/window update before the transition starts.
1717 * To prevent this, we immediately take a snapshot and place the app/snapshot into a leash which
1718 * "freezes" the location/crop until the transition starts.
1719 * <p>
1720 * Here's a walk-through of the process:
1721 * 1. Create a temporary leash ("interim-change-leash") and reparent the app to it.
1722 * 2. Set the temporary leash's position/crop to the current state.
1723 * 3. Create a snapshot and place that at the top of the leash to cover up content changes.
1724 * 4. Once the transition is ready, it will reparent the app to the animation leash.
1725 * 5. Detach the interim-change-leash.
1726 */
1727 private void initializeChangeTransition(Rect startBounds) {
1728 mDisplayContent.prepareAppTransition(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
1729 false /* alwaysKeepCurrent */, 0, false /* forceOverride */);
1730 mDisplayContent.mChangingApps.add(this);
1731 mTransitStartRect.set(startBounds);
1732
1733 final SurfaceControl.Builder builder = makeAnimationLeash()
1734 .setParent(getAnimationLeashParent())
1735 .setName(getSurfaceControl() + " - interim-change-leash");
1736 mTransitChangeLeash = builder.build();
1737 Transaction t = getPendingTransaction();
1738 t.setWindowCrop(mTransitChangeLeash, startBounds.width(), startBounds.height());
1739 t.setPosition(mTransitChangeLeash, startBounds.left, startBounds.top);
1740 t.show(mTransitChangeLeash);
1741 t.reparent(getSurfaceControl(), mTransitChangeLeash);
1742 onAnimationLeashCreated(t, mTransitChangeLeash);
1743
Evan Rosky966759f2019-01-15 10:33:58 -08001744 // Skip creating snapshot if this transition is controlled by a remote animator which
1745 // doesn't need it.
1746 ArraySet<Integer> activityTypes = new ArraySet<>();
1747 activityTypes.add(getActivityType());
1748 RemoteAnimationAdapter adapter =
1749 mDisplayContent.mAppTransitionController.getRemoteAnimationOverride(
1750 this, TRANSIT_TASK_CHANGE_WINDOWING_MODE, activityTypes);
1751 if (adapter != null && !adapter.getChangeNeedsSnapshot()) {
1752 return;
1753 }
1754
Evan Rosky08e20932019-05-14 10:54:07 -07001755 Task task = getTask();
1756 if (mThumbnail == null && task != null && !hasCommittedReparentToAnimationLeash()) {
1757 SurfaceControl.ScreenshotGraphicBuffer snapshot =
1758 mWmService.mTaskSnapshotController.createTaskSnapshot(
1759 task, 1 /* scaleFraction */);
Yunfan Chendcb1fcf2019-02-07 19:08:41 +09001760 if (snapshot != null) {
Evan Rosky08e20932019-05-14 10:54:07 -07001761 mThumbnail = new AppWindowThumbnail(t, this, snapshot.getGraphicBuffer(),
Yunfan Chendcb1fcf2019-02-07 19:08:41 +09001762 true /* relative */);
1763 }
Evan Rosky2289ba12018-11-19 18:28:18 -08001764 }
1765 }
1766
1767 boolean isInChangeTransition() {
Evan Roskyec9488c2019-03-01 19:32:12 -08001768 return mTransitChangeLeash != null || AppTransition.isChangeTransit(mTransit);
Evan Rosky2289ba12018-11-19 18:28:18 -08001769 }
1770
Evan Rosky966759f2019-01-15 10:33:58 -08001771 @VisibleForTesting
1772 AppWindowThumbnail getThumbnail() {
1773 return mThumbnail;
1774 }
1775
Riddle Hsub398da32019-01-21 21:48:16 +08001776 /**
1777 * Calculates the scale and offset to horizontal center the size compatibility bounds into the
1778 * region which is available to application.
1779 */
1780 private void calculateCompatBoundsTransformation(Configuration newParentConfig) {
1781 final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds();
Riddle Hsu74826262019-04-17 14:57:42 +08001782 final Rect parentBounds = newParentConfig.windowConfiguration.getBounds();
1783 final Rect viewportBounds = parentAppBounds != null ? parentAppBounds : parentBounds;
Riddle Hsu04164182019-03-07 18:03:27 +08001784 final Rect appBounds = getWindowConfiguration().getAppBounds();
1785 final Rect contentBounds = appBounds != null ? appBounds : getResolvedOverrideBounds();
Riddle Hsub398da32019-01-21 21:48:16 +08001786 final float contentW = contentBounds.width();
1787 final float contentH = contentBounds.height();
1788 final float viewportW = viewportBounds.width();
1789 final float viewportH = viewportBounds.height();
1790 // Only allow to scale down.
1791 mSizeCompatScale = (contentW <= viewportW && contentH <= viewportH)
1792 ? 1 : Math.min(viewportW / contentW, viewportH / contentH);
1793 final int offsetX = (int) ((viewportW - contentW * mSizeCompatScale + 1) * 0.5f)
1794 + viewportBounds.left;
1795
1796 if (mSizeCompatBounds == null) {
1797 mSizeCompatBounds = new Rect();
1798 }
1799 mSizeCompatBounds.set(contentBounds);
1800 mSizeCompatBounds.offsetTo(0, 0);
1801 mSizeCompatBounds.scale(mSizeCompatScale);
Riddle Hsu74826262019-04-17 14:57:42 +08001802 // Ensure to align the top with the parent.
1803 mSizeCompatBounds.top = parentBounds.top;
Riddle Hsu04164182019-03-07 18:03:27 +08001804 // The decor inset is included in height.
1805 mSizeCompatBounds.bottom += viewportBounds.top;
Riddle Hsub398da32019-01-21 21:48:16 +08001806 mSizeCompatBounds.left += offsetX;
1807 mSizeCompatBounds.right += offsetX;
1808 }
1809
1810 @Override
1811 public Rect getBounds() {
1812 if (mSizeCompatBounds != null) {
1813 return mSizeCompatBounds;
1814 }
1815 return super.getBounds();
1816 }
1817
1818 @Override
1819 public boolean matchParentBounds() {
1820 if (super.matchParentBounds()) {
1821 return true;
1822 }
1823 // An activity in size compatibility mode may have override bounds which equals to its
1824 // parent bounds, so the exact bounds should also be checked.
1825 final WindowContainer parent = getParent();
1826 return parent == null || parent.getBounds().equals(getResolvedOverrideBounds());
1827 }
1828
Winson Chunge55c0192017-08-24 14:50:48 -07001829 @Override
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001830 void checkAppWindowsReadyToShow() {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001831 if (allDrawn == mLastAllDrawn) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001832 return;
1833 }
1834
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001835 mLastAllDrawn = allDrawn;
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001836 if (!allDrawn) {
1837 return;
1838 }
1839
1840 // The token has now changed state to having all windows shown... what to do, what to do?
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001841 if (mFreezingScreen) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001842 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001843 stopFreezingScreen(false, true);
1844 if (DEBUG_ORIENTATION) Slog.i(TAG,
1845 "Setting mOrientationChangeComplete=true because wtoken " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001846 + " numInteresting=" + mNumInterestingWindows + " numDrawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001847 // This will set mOrientationChangeComplete and cause a pass through layout.
1848 setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001849 "checkAppWindowsReadyToShow: freezingScreen");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001850 } else {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001851 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001852
1853 // We can now show all of the drawn windows!
lumark588a3e82018-07-20 18:53:54 +08001854 if (!getDisplayContent().mOpeningApps.contains(this) && canShowWindows()) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001855 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001856 }
1857 }
1858 }
1859
Matthew Ng5d23afa2017-06-21 16:16:24 -07001860 /**
Bryce Leed390deb2017-06-22 13:14:28 -07001861 * Returns whether the drawn window states of this {@link AppWindowToken} has considered every
1862 * child {@link WindowState}. A child is considered if it has been passed into
1863 * {@link #updateDrawnWindowStates(WindowState)} after being added. This is used to determine
1864 * whether states, such as {@code allDrawn}, can be set, which relies on state variables such as
1865 * {@code mNumInterestingWindows}, which depend on all {@link WindowState}s being considered.
1866 *
1867 * @return {@code true} If all children have been considered, {@code false}.
1868 */
1869 private boolean allDrawnStatesConsidered() {
Bryce Lee6311c4b2017-07-06 14:09:29 -07001870 for (int i = mChildren.size() - 1; i >= 0; --i) {
1871 final WindowState child = mChildren.get(i);
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001872 if (child.mightAffectAllDrawn() && !child.getDrawnStateEvaluated()) {
Bryce Leed390deb2017-06-22 13:14:28 -07001873 return false;
1874 }
1875 }
1876 return true;
1877 }
1878
1879 /**
Matthew Ng5d23afa2017-06-21 16:16:24 -07001880 * Determines if the token has finished drawing. This should only be called from
1881 * {@link DisplayContent#applySurfaceChangesTransaction}
1882 */
Matthew Ng498c71d2017-04-18 13:55:45 -07001883 void updateAllDrawn() {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001884 if (!allDrawn) {
Matthew Ng498c71d2017-04-18 13:55:45 -07001885 // Number of drawn windows can be less when a window is being relaunched, wait for
Bryce Leed390deb2017-06-22 13:14:28 -07001886 // all windows to be launched and drawn for this token be considered all drawn.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001887 final int numInteresting = mNumInterestingWindows;
Bryce Leed390deb2017-06-22 13:14:28 -07001888
1889 // We must make sure that all present children have been considered (determined by
1890 // {@link #allDrawnStatesConsidered}) before evaluating whether everything has been
1891 // drawn.
1892 if (numInteresting > 0 && allDrawnStatesConsidered()
1893 && mNumDrawnWindows >= numInteresting && !isRelaunching()) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001894 if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawn: " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001895 + " interesting=" + numInteresting + " drawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001896 allDrawn = true;
1897 // Force an additional layout pass where
1898 // WindowStateAnimator#commitFinishDrawingLocked() will call performShowLocked().
Matthew Ng498c71d2017-04-18 13:55:45 -07001899 if (mDisplayContent != null) {
1900 mDisplayContent.setLayoutNeeded();
1901 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001902 mWmService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
Robert Carrecc06b32017-04-18 14:25:10 -07001903
Winson Chunge7ba6862017-05-24 12:13:33 -07001904 // Notify the pinned stack upon all windows drawn. If there was an animation in
1905 // progress then this signal will resume that animation.
Wale Ogunwale61911492017-10-11 08:50:50 -07001906 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
Winson Chunge7ba6862017-05-24 12:13:33 -07001907 if (pinnedStack != null) {
1908 pinnedStack.onAllWindowsDrawn();
Robert Carrecc06b32017-04-18 14:25:10 -07001909 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001910 }
1911 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001912 }
1913
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001914 boolean keyDispatchingTimedOut(String reason, int windowPid) {
1915 return mActivityRecord != null && mActivityRecord.keyDispatchingTimedOut(reason, windowPid);
1916 }
1917
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001918 /**
1919 * Updated this app token tracking states for interesting and drawn windows based on the window.
1920 *
1921 * @return Returns true if the input window is considered interesting and drawn while all the
1922 * windows in this app token where not considered drawn as of the last pass.
1923 */
1924 boolean updateDrawnWindowStates(WindowState w) {
Bryce Leed390deb2017-06-22 13:14:28 -07001925 w.setDrawnStateEvaluated(true /*evaluated*/);
1926
Jorim Jaggie4b0f282017-05-17 15:10:29 +02001927 if (DEBUG_STARTING_WINDOW_VERBOSE && w == startingWindow) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001928 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + w.isOnScreen()
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001929 + " allDrawn=" + allDrawn + " freezingScreen=" + mFreezingScreen);
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001930 }
1931
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001932 if (allDrawn && !mFreezingScreen) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001933 return false;
1934 }
1935
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001936 if (mLastTransactionSequence != mWmService.mTransactionSequence) {
1937 mLastTransactionSequence = mWmService.mTransactionSequence;
Matthew Ng53e66b22018-01-12 17:13:13 -08001938 mNumDrawnWindows = 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001939 startingDisplayed = false;
Matthew Ng53e66b22018-01-12 17:13:13 -08001940
1941 // There is the main base application window, even if it is exiting, wait for it
1942 mNumInterestingWindows = findMainWindow(false /* includeStartingApp */) != null ? 1 : 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001943 }
1944
1945 final WindowStateAnimator winAnimator = w.mWinAnimator;
1946
1947 boolean isInterestingAndDrawn = false;
1948
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001949 if (!allDrawn && w.mightAffectAllDrawn()) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001950 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
1951 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001952 + ", isAnimationSet=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001953 if (!w.isDrawnLw()) {
1954 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController
chaviw15ad49f2019-04-24 15:05:39 -07001955 + " pv=" + w.isVisibleByPolicy()
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001956 + " mDrawState=" + winAnimator.drawStateToString()
1957 + " ph=" + w.isParentWindowHidden() + " th=" + hiddenRequested
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001958 + " a=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001959 }
1960 }
1961
1962 if (w != startingWindow) {
1963 if (w.isInteresting()) {
Matthew Ng53e66b22018-01-12 17:13:13 -08001964 // Add non-main window as interesting since the main app has already been added
1965 if (findMainWindow(false /* includeStartingApp */) != w) {
1966 mNumInterestingWindows++;
1967 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001968 if (w.isDrawnLw()) {
1969 mNumDrawnWindows++;
1970
1971 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, "tokenMayBeDrawn: "
1972 + this + " w=" + w + " numInteresting=" + mNumInterestingWindows
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001973 + " freezingScreen=" + mFreezingScreen
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001974 + " mAppFreezing=" + w.mAppFreezing);
1975
1976 isInterestingAndDrawn = true;
1977 }
1978 }
1979 } else if (w.isDrawnLw()) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001980 if (mActivityRecord != null) {
1981 mActivityRecord.onStartingWindowDrawn(SystemClock.uptimeMillis());
Jorim Jaggi3878ca32017-02-02 17:13:05 -08001982 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001983 startingDisplayed = true;
1984 }
1985 }
1986
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001987 return isInterestingAndDrawn;
1988 }
1989
Adrian Roos23df3a32018-03-15 15:41:13 +01001990 void layoutLetterbox(WindowState winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001991 final WindowState w = findMainWindow();
Adrian Roosf93b6d22018-03-21 13:48:26 +01001992 if (w == null || winHint != null && w != winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001993 return;
1994 }
Jorim Jaggia32da382018-03-28 18:01:22 +02001995 final boolean surfaceReady = w.isDrawnLw() // Regular case
Adrian Roosf93b6d22018-03-21 13:48:26 +01001996 || w.mWinAnimator.mSurfaceDestroyDeferred // The preserved surface is still ready.
1997 || w.isDragResizeChanged(); // Waiting for relayoutWindow to call preserveSurface.
Jorim Jaggi4981f152019-03-26 18:58:45 +01001998 final boolean needsLetterbox = surfaceReady && w.isLetterboxedAppWindow() && fillsParent();
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001999 if (needsLetterbox) {
2000 if (mLetterbox == null) {
2001 mLetterbox = new Letterbox(() -> makeChildSurface(null));
Riddle Hsu192fe762019-01-15 23:41:57 +08002002 mLetterbox.attachInput(w);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002003 }
Adrian Roos7af9d972018-11-30 15:26:27 +01002004 getPosition(mTmpPoint);
Evan Rosky67c15642019-04-24 13:17:28 -07002005 // Get the bounds of the "space-to-fill". In multi-window mode, the task-level
2006 // represents this. In fullscreen-mode, the stack does (since the orientation letterbox
2007 // is also applied to the task).
2008 Rect spaceToFill = (inMultiWindowMode() || getStack() == null)
2009 ? getTask().getDisplayedBounds() : getStack().getDisplayedBounds();
Evan Rosky4fb1e912019-03-06 13:54:43 -08002010 mLetterbox.layout(spaceToFill, w.getFrameLw(), mTmpPoint);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002011 } else if (mLetterbox != null) {
Adrian Roos23df3a32018-03-15 15:41:13 +01002012 mLetterbox.hide();
2013 }
2014 }
2015
2016 void updateLetterboxSurface(WindowState winHint) {
2017 final WindowState w = findMainWindow();
2018 if (w != winHint && winHint != null && w != null) {
2019 return;
2020 }
2021 layoutLetterbox(winHint);
2022 if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) {
Tiger Huanged6794e2019-05-07 20:07:59 +08002023 mLetterbox.applySurfaceChanges(getPendingTransaction());
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002024 }
2025 }
2026
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07002027 @Override
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002028 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002029 // For legacy reasons we process the TaskStack.mExitingAppTokens first in DisplayContent
2030 // before the non-exiting app tokens. So, we skip the exiting app tokens here.
2031 // TODO: Investigate if we need to continue to do this or if we can just process them
2032 // in-order.
2033 if (mIsExiting && !waitingForReplacement()) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002034 return false;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002035 }
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002036 return forAllWindowsUnchecked(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002037 }
2038
lumark588a3e82018-07-20 18:53:54 +08002039 @Override
2040 void forAllAppWindows(Consumer<AppWindowToken> callback) {
2041 callback.accept(this);
2042 }
2043
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002044 boolean forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback,
2045 boolean traverseTopToBottom) {
2046 return super.forAllWindows(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002047 }
2048
2049 @Override
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002050 AppWindowToken asAppWindowToken() {
2051 // I am an app window token!
2052 return this;
2053 }
2054
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002055 boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
2056 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
2057 IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
2058 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
2059 // If the display is frozen, we won't do anything until the actual window is
2060 // displayed so there is no reason to put in the starting window.
2061 if (!okToDisplay()) {
2062 return false;
2063 }
2064
chaviwa8f07a72019-05-01 16:25:39 -07002065 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002066 return false;
2067 }
2068
2069 final WindowState mainWin = findMainWindow();
2070 if (mainWin != null && mainWin.mWinAnimator.getShown()) {
2071 // App already has a visible window...why would you want a starting window?
2072 return false;
2073 }
2074
2075 final ActivityManager.TaskSnapshot snapshot =
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002076 mWmService.mTaskSnapshotController.getSnapshot(
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002077 getTask().mTaskId, getTask().mUserId,
2078 false /* restoreFromDisk */, false /* reducedResolution */);
2079 final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
2080 allowTaskSnapshot, activityCreated, fromRecents, snapshot);
2081
2082 if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
2083 return createSnapshot(snapshot);
2084 }
2085
2086 // If this is a translucent window, then don't show a starting window -- the current
2087 // effect (a full-screen opaque starting window that fades away to the real contents
2088 // when it is ready) does not work for this.
2089 if (DEBUG_STARTING_WINDOW) {
2090 Slog.v(TAG, "Checking theme of starting window: 0x" + Integer.toHexString(theme));
2091 }
2092 if (theme != 0) {
2093 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
2094 com.android.internal.R.styleable.Window,
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002095 mWmService.mCurrentUserId);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002096 if (ent == null) {
2097 // Whoops! App doesn't exist. Um. Okay. We'll just pretend like we didn't
2098 // see that.
2099 return false;
2100 }
2101 final boolean windowIsTranslucent = ent.array.getBoolean(
2102 com.android.internal.R.styleable.Window_windowIsTranslucent, false);
2103 final boolean windowIsFloating = ent.array.getBoolean(
2104 com.android.internal.R.styleable.Window_windowIsFloating, false);
2105 final boolean windowShowWallpaper = ent.array.getBoolean(
2106 com.android.internal.R.styleable.Window_windowShowWallpaper, false);
2107 final boolean windowDisableStarting = ent.array.getBoolean(
2108 com.android.internal.R.styleable.Window_windowDisablePreview, false);
2109 if (DEBUG_STARTING_WINDOW) {
2110 Slog.v(TAG, "Translucent=" + windowIsTranslucent
2111 + " Floating=" + windowIsFloating
2112 + " ShowWallpaper=" + windowShowWallpaper);
2113 }
2114 if (windowIsTranslucent) {
2115 return false;
2116 }
2117 if (windowIsFloating || windowDisableStarting) {
2118 return false;
2119 }
2120 if (windowShowWallpaper) {
2121 if (getDisplayContent().mWallpaperController
2122 .getWallpaperTarget() == null) {
2123 // If this theme is requesting a wallpaper, and the wallpaper
2124 // is not currently visible, then this effectively serves as
2125 // an opaque window and our starting window transition animation
2126 // can still work. We just need to make sure the starting window
2127 // is also showing the wallpaper.
2128 windowFlags |= FLAG_SHOW_WALLPAPER;
2129 } else {
2130 return false;
2131 }
2132 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002133 }
Yunfan Chen8a8c0ed2018-12-18 16:46:32 -08002134
2135 if (transferStartingWindow(transferFrom)) {
2136 return true;
2137 }
2138
2139 // There is no existing starting window, and we don't want to create a splash screen, so
2140 // that's it!
2141 if (type != STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
2142 return false;
2143 }
2144
2145 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SplashScreenStartingData");
chaviwa8f07a72019-05-01 16:25:39 -07002146 mStartingData = new SplashScreenStartingData(mWmService, pkg,
Yunfan Chen8a8c0ed2018-12-18 16:46:32 -08002147 theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
2148 getMergedOverrideConfiguration());
2149 scheduleAddStartingWindow();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002150 return true;
2151 }
2152
2153
2154 private boolean createSnapshot(ActivityManager.TaskSnapshot snapshot) {
2155 if (snapshot == null) {
2156 return false;
2157 }
2158
2159 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SnapshotStartingData");
chaviwa8f07a72019-05-01 16:25:39 -07002160 mStartingData = new SnapshotStartingData(mWmService, snapshot);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002161 scheduleAddStartingWindow();
2162 return true;
2163 }
2164
2165 void scheduleAddStartingWindow() {
2166 // Note: we really want to do sendMessageAtFrontOfQueue() because we
2167 // want to process the message ASAP, before any other queued
2168 // messages.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002169 if (!mWmService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002170 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING");
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002171 mWmService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002172 }
2173 }
2174
2175 private final Runnable mAddStartingWindow = new Runnable() {
2176
2177 @Override
2178 public void run() {
chaviwa8f07a72019-05-01 16:25:39 -07002179 // Can be accessed without holding the global lock
2180 final StartingData startingData;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002181 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002182 // There can only be one adding request, silly caller!
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002183 mWmService.mAnimationHandler.removeCallbacks(this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002184
chaviwa8f07a72019-05-01 16:25:39 -07002185 if (mStartingData == null) {
2186 // Animation has been canceled... do nothing.
2187 if (DEBUG_STARTING_WINDOW) {
2188 Slog.v(TAG, "startingData was nulled out before handling"
2189 + " mAddStartingWindow: " + AppWindowToken.this);
2190 }
2191 return;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002192 }
chaviwa8f07a72019-05-01 16:25:39 -07002193 startingData = mStartingData;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002194 }
2195
2196 if (DEBUG_STARTING_WINDOW) {
2197 Slog.v(TAG, "Add starting " + this + ": startingData=" + startingData);
2198 }
2199
2200 WindowManagerPolicy.StartingSurface surface = null;
2201 try {
2202 surface = startingData.createStartingSurface(AppWindowToken.this);
2203 } catch (Exception e) {
2204 Slog.w(TAG, "Exception when adding starting window", e);
2205 }
2206 if (surface != null) {
2207 boolean abort = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002208 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002209 // If the window was successfully added, then
2210 // we need to remove it.
chaviwa8f07a72019-05-01 16:25:39 -07002211 if (removed || mStartingData == null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002212 if (DEBUG_STARTING_WINDOW) {
2213 Slog.v(TAG, "Aborted starting " + AppWindowToken.this
chaviwa8f07a72019-05-01 16:25:39 -07002214 + ": removed=" + removed + " startingData=" + mStartingData);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002215 }
2216 startingWindow = null;
chaviwa8f07a72019-05-01 16:25:39 -07002217 mStartingData = null;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002218 abort = true;
2219 } else {
2220 startingSurface = surface;
2221 }
2222 if (DEBUG_STARTING_WINDOW && !abort) {
chaviwa8f07a72019-05-01 16:25:39 -07002223 Slog.v(TAG,
2224 "Added starting " + AppWindowToken.this + ": startingWindow="
2225 + startingWindow + " startingView=" + startingSurface);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002226 }
2227 }
2228 if (abort) {
2229 surface.remove();
2230 }
2231 } else if (DEBUG_STARTING_WINDOW) {
2232 Slog.v(TAG, "Surface returned was null: " + AppWindowToken.this);
2233 }
2234 }
2235 };
2236
2237 private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
2238 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents,
2239 ActivityManager.TaskSnapshot snapshot) {
2240 if (getDisplayContent().mAppTransition.getAppTransition()
2241 == TRANSIT_DOCK_TASK_FROM_RECENTS) {
2242 // TODO(b/34099271): Remove this statement to add back the starting window and figure
2243 // out why it causes flickering, the starting window appears over the thumbnail while
2244 // the docked from recents transition occurs
2245 return STARTING_WINDOW_TYPE_NONE;
2246 } else if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
2247 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2248 } else if (taskSwitch && allowTaskSnapshot) {
Kevin716a9db2018-12-18 16:53:39 -08002249 if (mWmService.mLowRamTaskSnapshotsAndRecents) {
Kevin58b47f12018-12-17 14:09:01 -08002250 // For low RAM devices, we use the splash screen starting window instead of the
2251 // task snapshot starting window.
2252 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2253 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002254 return snapshot == null ? STARTING_WINDOW_TYPE_NONE
2255 : snapshotOrientationSameAsTask(snapshot) || fromRecents
2256 ? STARTING_WINDOW_TYPE_SNAPSHOT : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2257 } else {
2258 return STARTING_WINDOW_TYPE_NONE;
2259 }
2260 }
2261
2262
2263 private boolean snapshotOrientationSameAsTask(ActivityManager.TaskSnapshot snapshot) {
2264 if (snapshot == null) {
2265 return false;
2266 }
2267 return getTask().getConfiguration().orientation == snapshot.getOrientation();
2268 }
2269
2270 void removeStartingWindow() {
2271 if (startingWindow == null) {
chaviwa8f07a72019-05-01 16:25:39 -07002272 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002273 // Starting window has not been added yet, but it is scheduled to be added.
2274 // Go ahead and cancel the request.
2275 if (DEBUG_STARTING_WINDOW) {
2276 Slog.v(TAG_WM, "Clearing startingData for token=" + this);
2277 }
chaviwa8f07a72019-05-01 16:25:39 -07002278 mStartingData = null;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002279 }
2280 return;
2281 }
2282
2283 final WindowManagerPolicy.StartingSurface surface;
chaviwa8f07a72019-05-01 16:25:39 -07002284 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002285 surface = startingSurface;
chaviwa8f07a72019-05-01 16:25:39 -07002286 mStartingData = null;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002287 startingSurface = null;
2288 startingWindow = null;
2289 startingDisplayed = false;
2290 if (surface == null) {
2291 if (DEBUG_STARTING_WINDOW) {
2292 Slog.v(TAG_WM, "startingWindow was set but startingSurface==null, couldn't "
2293 + "remove");
2294 }
2295 return;
2296 }
2297 } else {
2298 if (DEBUG_STARTING_WINDOW) {
2299 Slog.v(TAG_WM, "Tried to remove starting window but startingWindow was null:"
2300 + this);
2301 }
2302 return;
2303 }
2304
2305 if (DEBUG_STARTING_WINDOW) {
2306 Slog.v(TAG_WM, "Schedule remove starting " + this
2307 + " startingWindow=" + startingWindow
2308 + " startingView=" + startingSurface
2309 + " Callers=" + Debug.getCallers(5));
2310 }
2311
2312 // Use the same thread to remove the window as we used to add it, as otherwise we end up
2313 // with things in the view hierarchy being called from different threads.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002314 mWmService.mAnimationHandler.post(() -> {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002315 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Removing startingView=" + surface);
2316 try {
2317 surface.remove();
2318 } catch (Exception e) {
2319 Slog.w(TAG_WM, "Exception when removing starting window", e);
2320 }
2321 });
2322 }
2323
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002324 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -07002325 boolean fillsParent() {
2326 return mFillsParent;
2327 }
2328
2329 void setFillsParent(boolean fillsParent) {
2330 mFillsParent = fillsParent;
2331 }
2332
Jorim Jaggife762342016-10-13 14:33:27 +02002333 boolean containsDismissKeyguardWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002334 // Window state is transient during relaunch. We are not guaranteed to be frozen during the
2335 // entirety of the relaunch.
2336 if (isRelaunching()) {
2337 return mLastContainsDismissKeyguardWindow;
2338 }
2339
Jorim Jaggife762342016-10-13 14:33:27 +02002340 for (int i = mChildren.size() - 1; i >= 0; i--) {
2341 if ((mChildren.get(i).mAttrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
2342 return true;
2343 }
2344 }
2345 return false;
2346 }
2347
2348 boolean containsShowWhenLockedWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002349 // When we are relaunching, it is possible for us to be unfrozen before our previous
2350 // windows have been added back. Using the cached value ensures that our previous
2351 // showWhenLocked preference is honored until relaunching is complete.
2352 if (isRelaunching()) {
2353 return mLastContainsShowWhenLockedWindow;
2354 }
2355
Jorim Jaggife762342016-10-13 14:33:27 +02002356 for (int i = mChildren.size() - 1; i >= 0; i--) {
2357 if ((mChildren.get(i).mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
2358 return true;
2359 }
2360 }
Bryce Lee081554b2017-05-25 07:52:12 -07002361
Jorim Jaggife762342016-10-13 14:33:27 +02002362 return false;
2363 }
2364
2365 void checkKeyguardFlagsChanged() {
2366 final boolean containsDismissKeyguard = containsDismissKeyguardWindow();
2367 final boolean containsShowWhenLocked = containsShowWhenLockedWindow();
2368 if (containsDismissKeyguard != mLastContainsDismissKeyguardWindow
2369 || containsShowWhenLocked != mLastContainsShowWhenLockedWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002370 mWmService.notifyKeyguardFlagsChanged(null /* callback */,
lumark588a3e82018-07-20 18:53:54 +08002371 getDisplayContent().getDisplayId());
Jorim Jaggife762342016-10-13 14:33:27 +02002372 }
2373 mLastContainsDismissKeyguardWindow = containsDismissKeyguard;
2374 mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
2375 }
2376
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002377 WindowState getImeTargetBelowWindow(WindowState w) {
2378 final int index = mChildren.indexOf(w);
2379 if (index > 0) {
2380 final WindowState target = mChildren.get(index - 1);
2381 if (target.canBeImeTarget()) {
2382 return target;
2383 }
2384 }
2385 return null;
2386 }
2387
2388 WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
2389 WindowState candidate = null;
2390 for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
2391 final WindowState w = mChildren.get(i);
2392 if (w.mRemoved) {
2393 continue;
2394 }
Jorim Jaggi35d328a2018-08-14 17:00:20 +02002395 if (candidate == null) {
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002396 candidate = w;
2397 }
2398 }
2399 return candidate;
2400 }
2401
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002402 /**
2403 * See {@link Activity#setDisablePreviewScreenshots}.
2404 */
2405 void setDisablePreviewScreenshots(boolean disable) {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002406 mDisablePreviewScreenshots = disable;
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002407 }
2408
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002409 /**
chaviwd3bf08d2017-08-01 17:24:59 -07002410 * Sets whether the current launch can turn the screen on. See {@link #canTurnScreenOn()}
2411 */
2412 void setCanTurnScreenOn(boolean canTurnScreenOn) {
2413 mCanTurnScreenOn = canTurnScreenOn;
2414 }
2415
2416 /**
2417 * Indicates whether the current launch can turn the screen on. This is to prevent multiple
2418 * relayouts from turning the screen back on. The screen should only turn on at most
2419 * once per activity resume.
2420 *
2421 * @return true if the screen can be turned on.
2422 */
2423 boolean canTurnScreenOn() {
2424 return mCanTurnScreenOn;
2425 }
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}