blob: a342c5e9fa7e4985c28acc0c3a76cac2ee520aac [file] [log] [blame]
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.wm;
18
Evan Rosky2289ba12018-11-19 18:28:18 -080019import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
Winson Chunge55c0192017-08-24 14:50:48 -070020import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
Jorim Jaggic6976f02018-04-18 16:31:07 +020021import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
Winson Chunge55c0192017-08-24 14:50:48 -070022import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
Jorim Jaggiaf0d6d22018-06-08 15:25:35 +020023import static android.content.pm.ActivityInfo.COLOR_MODE_DEFAULT;
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -070024import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
Wale Ogunwale51362492016-09-08 17:49:17 -070025import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
Jorim Jaggif5f9e122017-10-24 18:21:09 +020026import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
Jorim Jaggife762342016-10-13 14:33:27 +020027import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
Jorim Jaggid635a4a2017-05-03 15:21:26 +020028import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080029import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
Jorim Jaggife762342016-10-13 14:33:27 +020030import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
Wale Ogunwaled1c37912016-08-16 03:19:39 -070031import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080032import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -070033import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080034import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
Evan Rosky2289ba12018-11-19 18:28:18 -080035import static android.view.WindowManager.TRANSIT_TASK_CHANGE_WINDOWING_MODE;
chaviw9c81e632018-07-31 11:17:52 -070036import static android.view.WindowManager.TRANSIT_UNSET;
Jorim Jaggic6976f02018-04-18 16:31:07 +020037import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
chaviw9c81e632018-07-31 11:17:52 -070038
Adrian Roose99bc052017-11-20 17:55:31 +010039import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
40import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070041import static com.android.server.wm.AppWindowTokenProto.ALL_DRAWN;
42import static com.android.server.wm.AppWindowTokenProto.APP_STOPPED;
43import static com.android.server.wm.AppWindowTokenProto.CLIENT_HIDDEN;
44import static com.android.server.wm.AppWindowTokenProto.DEFER_HIDING_CLIENT;
45import static com.android.server.wm.AppWindowTokenProto.FILLS_PARENT;
46import static com.android.server.wm.AppWindowTokenProto.FROZEN_BOUNDS;
47import static com.android.server.wm.AppWindowTokenProto.HIDDEN_REQUESTED;
48import static com.android.server.wm.AppWindowTokenProto.HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW;
49import static com.android.server.wm.AppWindowTokenProto.IS_REALLY_ANIMATING;
50import static com.android.server.wm.AppWindowTokenProto.IS_WAITING_FOR_TRANSITION_START;
51import static com.android.server.wm.AppWindowTokenProto.LAST_ALL_DRAWN;
52import static com.android.server.wm.AppWindowTokenProto.LAST_SURFACE_SHOWING;
53import static com.android.server.wm.AppWindowTokenProto.NAME;
54import static com.android.server.wm.AppWindowTokenProto.NUM_DRAWN_WINDOWS;
55import static com.android.server.wm.AppWindowTokenProto.NUM_INTERESTING_WINDOWS;
56import static com.android.server.wm.AppWindowTokenProto.REMOVED;
57import static com.android.server.wm.AppWindowTokenProto.REPORTED_DRAWN;
58import static com.android.server.wm.AppWindowTokenProto.REPORTED_VISIBLE;
59import static com.android.server.wm.AppWindowTokenProto.STARTING_DISPLAYED;
60import static com.android.server.wm.AppWindowTokenProto.STARTING_MOVED;
61import static com.android.server.wm.AppWindowTokenProto.STARTING_WINDOW;
62import static com.android.server.wm.AppWindowTokenProto.THUMBNAIL;
63import static com.android.server.wm.AppWindowTokenProto.WINDOW_TOKEN;
chaviw9c81e632018-07-31 11:17:52 -070064import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
65import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
66import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
67import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
68import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
69import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
70import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
71import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
72import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
73import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
74import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
75import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
76import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
77import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN;
78import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
79import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
80import static com.android.server.wm.WindowManagerService.logWithStack;
Vishnu Naira2977262018-07-26 13:31:26 -070081import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080082
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070083import android.annotation.CallSuper;
chaviwdcf76ec2019-01-11 16:48:46 -080084import android.annotation.Size;
Jorim Jaggid635a4a2017-05-03 15:21:26 +020085import android.app.Activity;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080086import android.app.ActivityManager;
Winson Chung48b25652018-10-22 14:04:30 -070087import android.content.ComponentName;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080088import android.content.res.CompatibilityInfo;
Jorim Jaggi26c8c422016-05-09 19:57:25 -070089import android.content.res.Configuration;
Jorim Jaggi988f6682017-11-17 17:46:43 +010090import android.graphics.GraphicBuffer;
Jorim Jaggif5f9e122017-10-24 18:21:09 +020091import android.graphics.Point;
Jorim Jaggi0429f352015-12-22 16:29:16 +010092import android.graphics.Rect;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -070093import android.os.Binder;
Tiger Huang51c5a1d2018-12-11 20:24:51 +080094import android.os.Build;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -080095import android.os.Debug;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -070096import android.os.IBinder;
Steven Timotiusaf03df62017-07-18 16:56:43 -070097import android.os.RemoteException;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080098import android.os.SystemClock;
Jorim Jaggif5f9e122017-10-24 18:21:09 +020099import android.os.Trace;
Evan Rosky2289ba12018-11-19 18:28:18 -0800100import android.util.ArraySet;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800101import android.util.Slog;
Steven Timotiusaf03df62017-07-18 16:56:43 -0700102import android.util.proto.ProtoOutputStream;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200103import android.view.DisplayInfo;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800104import android.view.IApplicationToken;
Robert Carr788f5742018-07-30 17:46:45 -0700105import android.view.InputApplicationHandle;
Evan Rosky966759f2019-01-15 10:33:58 -0800106import android.view.RemoteAnimationAdapter;
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100107import android.view.RemoteAnimationDefinition;
Robert Carr6914f082017-03-20 19:04:30 -0700108import android.view.SurfaceControl;
Tony Mak64b8d562017-12-28 17:44:02 +0000109import android.view.SurfaceControl.Transaction;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800110import android.view.WindowManager;
Jorim Jaggi87fdbcb2017-08-17 13:41:11 +0200111import android.view.WindowManager.LayoutParams;
Tony Mak64b8d562017-12-28 17:44:02 +0000112import android.view.animation.Animation;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800113
Tony Mak64b8d562017-12-28 17:44:02 +0000114import com.android.internal.R;
Riddle Hsua118b3a2018-10-11 22:05:06 +0800115import com.android.internal.annotations.VisibleForTesting;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800116import com.android.internal.util.ToBooleanFunction;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800117import com.android.server.AttributeCache;
chaviwdcf76ec2019-01-11 16:48:46 -0800118import com.android.server.LocalServices;
Christine Franks0ada2772019-02-25 13:54:57 -0800119import com.android.server.display.color.ColorDisplayService;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800120import com.android.server.policy.WindowManagerPolicy;
Adrian Roose99bc052017-11-20 17:55:31 +0100121import com.android.server.policy.WindowManagerPolicy.StartingSurface;
Evan Rosky2289ba12018-11-19 18:28:18 -0800122import com.android.server.wm.RemoteAnimationController.RemoteAnimationRecord;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800123import com.android.server.wm.WindowManagerService.H;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800124
125import java.io.PrintWriter;
chaviwdcf76ec2019-01-11 16:48:46 -0800126import java.lang.ref.WeakReference;
Jorim Jaggi0429f352015-12-22 16:29:16 +0100127import java.util.ArrayDeque;
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800128import java.util.ArrayList;
lumark588a3e82018-07-20 18:53:54 +0800129import java.util.function.Consumer;
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800130
131class AppTokenList extends ArrayList<AppWindowToken> {
132}
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800133
134/**
135 * Version of WindowToken that is specifically for a particular application (or
136 * really activity) that is displaying windows.
137 */
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800138class AppWindowToken extends WindowToken implements WindowManagerService.AppFreezeListener,
139 ConfigurationContainerListener {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800140 private static final String TAG = TAG_WITH_CLASS_NAME ? "AppWindowToken" : TAG_WM;
141
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100142 /**
143 * Value to increment the z-layer when boosting a layer during animations. BOOST in l33tsp34k.
144 */
145 private static final int Z_BOOST_BASE = 800570000;
146
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800147 // Non-null only for application tokens.
148 final IApplicationToken appToken;
Winson Chung48b25652018-10-22 14:04:30 -0700149 final ComponentName mActivityComponent;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800150 final boolean mVoiceInteraction;
Dianne Hackborne30e02f2014-05-27 18:24:45 -0700151
Wale Ogunwale51362492016-09-08 17:49:17 -0700152 /** @see WindowContainer#fillsParent() */
153 private boolean mFillsParent;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800154 boolean mShowForAllUsers;
155 int mTargetSdk;
Craig Mautnera2c77052012-03-26 12:14:43 -0700156
Bryce Lee6d410262017-02-28 15:30:17 -0800157 // Flag set while reparenting to prevent actions normally triggered by an individual parent
158 // change.
159 private boolean mReparenting;
160
Wale Ogunwalee287e192017-04-21 09:30:12 -0700161 // True if we are current in the process of removing this app token from the display
162 private boolean mRemovingFromDisplay = false;
163
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800164 // The input dispatching timeout for this application token in nanoseconds.
Wale Ogunwale72919d22016-12-08 18:58:50 -0800165 long mInputDispatchingTimeoutNanos;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800166
167 // These are used for determining when all windows associated with
168 // an activity have been drawn, so they can be made visible together
169 // at the same time.
Craig Mautner764983d2012-03-22 11:37:36 -0700170 // initialize so that it doesn't match mTransactionSequence which is an int.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700171 private long mLastTransactionSequence = Long.MIN_VALUE;
172 private int mNumInterestingWindows;
173 private int mNumDrawnWindows;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800174 boolean inPendingTransaction;
175 boolean allDrawn;
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000176 private boolean mLastAllDrawn;
177
Craig Mautner7636dfb2012-11-16 15:24:11 -0800178 // Set to true when this app creates a surface while in the middle of an animation. In that
179 // case do not clear allDrawn until the animation completes.
180 boolean deferClearAllDrawn;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800181
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800182 // Is this window's surface needed? This is almost like hidden, except
183 // it will sometimes be true a little earlier: when the token has
184 // been shown, but is still waiting for its app transition to execute
185 // before making its windows shown.
186 boolean hiddenRequested;
187
188 // Have we told the window clients to hide themselves?
Wale Ogunwale89973222017-04-23 18:39:45 -0700189 private boolean mClientHidden;
190
191 // If true we will defer setting mClientHidden to true and reporting to the client that it is
192 // hidden.
193 boolean mDeferHidingClient;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800194
195 // Last visibility state we reported to the app token.
196 boolean reportedVisible;
197
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700198 // Last drawn state we reported to the app token.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700199 private boolean reportedDrawn;
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700200
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800201 // Set to true when the token has been removed from the window mgr.
202 boolean removed;
203
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800204 // Information about an application starting window if displayed.
205 StartingData startingData;
206 WindowState startingWindow;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800207 StartingSurface startingSurface;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800208 boolean startingDisplayed;
209 boolean startingMoved;
Jorim Jaggi60f9c972018-02-01 19:21:07 +0100210
Wale Ogunwale6c459212017-05-17 08:56:03 -0700211 // True if the hidden state of this token was forced to false due to a transferred starting
212 // window.
213 private boolean mHiddenSetFromTransferredStartingWindow;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800214 boolean firstWindowDrawn;
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700215 private final WindowState.UpdateReportedVisibilityResults mReportedVisibilityResults =
216 new WindowState.UpdateReportedVisibilityResults();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800217
218 // Input application handle used by the input dispatcher.
Jeff Brown9302c872011-07-13 22:51:29 -0700219 final InputApplicationHandle mInputApplicationHandle;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800220
Wale Ogunwale571771c2016-08-26 13:18:50 -0700221 // TODO: Have a WindowContainer state for tracking exiting/deferred removal.
Craig Mautner799bc1d2015-01-14 10:33:48 -0800222 boolean mIsExiting;
Craig Mautner9ef471f2014-02-07 13:11:47 -0800223
Craig Mautnerbb742462014-07-07 15:28:55 -0700224 boolean mLaunchTaskBehind;
Craig Mautner8746a472014-07-24 15:12:54 -0700225 boolean mEnteringAnimation;
Craig Mautnerbb742462014-07-07 15:28:55 -0700226
Wale Ogunwale72919d22016-12-08 18:58:50 -0800227 private boolean mAlwaysFocusable;
Wale Ogunwale6cae7652015-12-26 07:36:26 -0800228
Robert Carre12aece2016-02-02 22:43:27 -0800229 boolean mAppStopped;
Robert Carrfd10cd12016-06-29 16:41:50 -0700230 int mRotationAnimationHint;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700231 private int mPendingRelaunchCount;
Robert Carre12aece2016-02-02 22:43:27 -0800232
Jorim Jaggife762342016-10-13 14:33:27 +0200233 private boolean mLastContainsShowWhenLockedWindow;
234 private boolean mLastContainsDismissKeyguardWindow;
235
Jorim Jaggi0429f352015-12-22 16:29:16 +0100236 ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
Jorim Jaggi26c8c422016-05-09 19:57:25 -0700237 ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
Jorim Jaggi0429f352015-12-22 16:29:16 +0100238
Riddle Hsub398da32019-01-21 21:48:16 +0800239 /**
240 * The scale to fit at least one side of the activity to its parent. If the activity uses
241 * 1920x1080, and the actually size on the screen is 960x540, then the scale is 0.5.
242 */
243 private float mSizeCompatScale = 1f;
244 /**
245 * The bounds in global coordinates for activity in size compatibility mode.
246 * @see ActivityRecord#inSizeCompatMode
247 */
248 private Rect mSizeCompatBounds;
249
Wale Ogunwale6c459212017-05-17 08:56:03 -0700250 private boolean mDisablePreviewScreenshots;
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +0100251
Wale Ogunwale034a8ec2017-09-02 17:14:40 -0700252 private Task mLastParent;
Robert Carred3e83b2017-04-21 13:26:55 -0700253
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800254 // TODO: Remove after unification
255 ActivityRecord mActivityRecord;
256
chaviwd3bf08d2017-08-01 17:24:59 -0700257 /**
258 * See {@link #canTurnScreenOn()}
259 */
260 private boolean mCanTurnScreenOn = true;
261
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200262 /**
263 * If we are running an animation, this determines the transition type. Must be one of
264 * AppTransition.TRANSIT_* constants.
265 */
266 private int mTransit;
267
268 /**
269 * If we are running an animation, this determines the flags during this animation. Must be a
270 * bitwise combination of AppTransition.TRANSIT_FLAG_* constants.
271 */
272 private int mTransitFlags;
273
274 /** Whether our surface was set to be showing in the last call to {@link #prepareSurfaces} */
Jorim Jaggifd1891462017-12-29 15:41:36 +0100275 private boolean mLastSurfaceShowing = true;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200276
Evan Rosky2289ba12018-11-19 18:28:18 -0800277 /**
278 * This gets used during some open/close transitions as well as during a change transition
279 * where it represents the starting-state snapshot.
280 */
Jorim Jaggi988f6682017-11-17 17:46:43 +0100281 private AppWindowThumbnail mThumbnail;
Evan Rosky2289ba12018-11-19 18:28:18 -0800282 private final Rect mTransitStartRect = new Rect();
283
284 /**
285 * This leash is used to "freeze" the app surface in place after the state change, but before
286 * the animation is ready to start.
287 */
288 private SurfaceControl mTransitChangeLeash = null;
Jorim Jaggi988f6682017-11-17 17:46:43 +0100289
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000290 /** Have we been asked to have this token keep the screen frozen? */
291 private boolean mFreezingScreen;
292
293 /** Whether this token should be boosted at the top of all app window tokens. */
294 private boolean mNeedsZBoost;
Adrian Roos4d18a2e2017-12-19 19:08:05 +0100295 private Letterbox mLetterbox;
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000296
chaviw23ee71c2017-12-18 11:29:41 -0800297 private final Point mTmpPoint = new Point();
chaviw23012112017-12-20 15:29:04 -0800298 private final Rect mTmpRect = new Rect();
Evan Rosky2289ba12018-11-19 18:28:18 -0800299 private final Rect mTmpPrevBounds = new Rect();
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100300 private RemoteAnimationDefinition mRemoteAnimationDefinition;
Jorim Jaggi6de61012018-03-19 14:53:23 +0100301 private AnimatingAppWindowTokenRegistry mAnimatingAppWindowTokenRegistry;
chaviw23ee71c2017-12-18 11:29:41 -0800302
chaviw4ad54912018-05-30 11:05:44 -0700303 /**
304 * A flag to determine if this AWT is in the process of closing or entering PIP. This is needed
305 * to help AWT know that the app is in the process of closing but hasn't yet started closing on
306 * the WM side.
307 */
308 private boolean mWillCloseOrEnterPip;
309
Vishnu Naira2977262018-07-26 13:31:26 -0700310 /** Layer used to constrain the animation to a token's stack bounds. */
311 SurfaceControl mAnimationBoundsLayer;
312
313 /** Whether this token needs to create mAnimationBoundsLayer for cropping animations. */
314 boolean mNeedsAnimationBoundsLayer;
315
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800316 private static final int STARTING_WINDOW_TYPE_NONE = 0;
317 private static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
318 private static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
319
chaviwdcf76ec2019-01-11 16:48:46 -0800320 private AppSaturationInfo mLastAppSaturationInfo;
321
322 private final ColorDisplayService.ColorTransformController mColorTransformController =
323 (matrix, translation) -> mWmService.mH.post(() -> {
324 synchronized (mWmService.mGlobalLock) {
325 if (mLastAppSaturationInfo == null) {
326 mLastAppSaturationInfo = new AppSaturationInfo();
327 }
328
329 mLastAppSaturationInfo.setSaturation(matrix, translation);
330 updateColorTransform();
331 }
332 });
333
Winson Chung48b25652018-10-22 14:04:30 -0700334 AppWindowToken(WindowManagerService service, IApplicationToken token,
335 ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
336 long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers,
Jorim Jaggi91d382a2019-03-27 17:00:48 +0100337 int targetSdk, int orientation, int rotationAnimationHint,
Winson Chung48b25652018-10-22 14:04:30 -0700338 boolean launchTaskBehind, boolean alwaysFocusable,
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800339 ActivityRecord activityRecord) {
Winson Chung48b25652018-10-22 14:04:30 -0700340 this(service, token, activityComponent, voiceInteraction, dc, fullscreen);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800341 // TODO: remove after unification
342 mActivityRecord = activityRecord;
343 mActivityRecord.registerConfigurationChangeListener(this);
Wale Ogunwale72919d22016-12-08 18:58:50 -0800344 mInputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800345 mShowForAllUsers = showForAllUsers;
346 mTargetSdk = targetSdk;
347 mOrientation = orientation;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800348 mLaunchTaskBehind = launchTaskBehind;
349 mAlwaysFocusable = alwaysFocusable;
350 mRotationAnimationHint = rotationAnimationHint;
351
352 // Application tokens start out hidden.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200353 setHidden(true);
Wale Ogunwale72919d22016-12-08 18:58:50 -0800354 hiddenRequested = true;
chaviwdcf76ec2019-01-11 16:48:46 -0800355
356 ColorDisplayService.ColorDisplayServiceInternal cds = LocalServices.getService(
357 ColorDisplayService.ColorDisplayServiceInternal.class);
358 cds.attachColorTransformController(activityRecord.packageName, activityRecord.mUserId,
359 new WeakReference<>(mColorTransformController));
Wale Ogunwale72919d22016-12-08 18:58:50 -0800360 }
361
Winson Chung48b25652018-10-22 14:04:30 -0700362 AppWindowToken(WindowManagerService service, IApplicationToken token,
363 ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
364 boolean fillsParent) {
Wale Ogunwale5cd907d2017-01-26 14:14:08 -0800365 super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true, dc,
366 false /* ownerCanManageAppTokens */);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700367 appToken = token;
Winson Chung48b25652018-10-22 14:04:30 -0700368 mActivityComponent = activityComponent;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800369 mVoiceInteraction = voiceInteraction;
Wale Ogunwale17f175c2017-02-07 16:54:10 -0800370 mFillsParent = fillsParent;
Robert Carr0bcbe642018-10-11 19:07:43 -0700371 mInputApplicationHandle = new InputApplicationHandle(appToken.asBinder());
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800372 }
373
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800374 void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
375 firstWindowDrawn = true;
376
377 // We now have a good window to show, remove dead placeholders
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700378 removeDeadWindows();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800379
Jorim Jaggi02886a82016-12-06 09:10:06 -0800380 if (startingWindow != null) {
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800381 if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Slog.v(TAG, "Finish starting "
382 + win.mToken + ": first real window is shown, no animation");
383 // If this initial window is animating, stop it -- we will do an animation to reveal
384 // it from behind the starting window, so there is no need for it to also be doing its
385 // own stuff.
Jorim Jaggia5e10572017-11-15 14:36:26 +0100386 win.cancelAnimation();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800387 removeStartingWindow();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800388 }
389 updateReportedVisibilityLocked();
390 }
391
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800392 void updateReportedVisibilityLocked() {
393 if (appToken == null) {
394 return;
395 }
396
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700397 if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700398 final int count = mChildren.size();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800399
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700400 mReportedVisibilityResults.reset();
401
402 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700403 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700404 win.updateReportedVisibility(mReportedVisibilityResults);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800405 }
406
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700407 int numInteresting = mReportedVisibilityResults.numInteresting;
408 int numVisible = mReportedVisibilityResults.numVisible;
409 int numDrawn = mReportedVisibilityResults.numDrawn;
410 boolean nowGone = mReportedVisibilityResults.nowGone;
411
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700412 boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200413 boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting && !isHidden();
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700414 if (!nowGone) {
415 // If the app is not yet gone, then it can only become visible/drawn.
416 if (!nowDrawn) {
417 nowDrawn = reportedDrawn;
418 }
419 if (!nowVisible) {
420 nowVisible = reportedVisible;
421 }
422 }
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800423 if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800424 + numInteresting + " visible=" + numVisible);
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700425 if (nowDrawn != reportedDrawn) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800426 if (mActivityRecord != null) {
427 mActivityRecord.onWindowsDrawn(nowDrawn, SystemClock.uptimeMillis());
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700428 }
429 reportedDrawn = nowDrawn;
430 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800431 if (nowVisible != reportedVisible) {
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700432 if (DEBUG_VISIBILITY) Slog.v(TAG,
433 "Visibility changed in " + this + ": vis=" + nowVisible);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800434 reportedVisible = nowVisible;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800435 if (mActivityRecord != null) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800436 if (nowVisible) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800437 onWindowsVisible();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800438 } else {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800439 onWindowsGone();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800440 }
441 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800442 }
443 }
444
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800445 private void onWindowsGone() {
446 if (mActivityRecord == null) {
447 return;
448 }
449 if (DEBUG_VISIBILITY) {
450 Slog.v(TAG_WM, "Reporting gone in " + mActivityRecord.appToken);
451 }
452 mActivityRecord.onWindowsGone();
453 }
454
455 private void onWindowsVisible() {
456 if (mActivityRecord == null) {
457 return;
458 }
459 if (DEBUG_VISIBILITY) {
460 Slog.v(TAG_WM, "Reporting visible in " + mActivityRecord.appToken);
461 }
462 mActivityRecord.onWindowsVisible();
463 }
464
Wale Ogunwale89973222017-04-23 18:39:45 -0700465 boolean isClientHidden() {
466 return mClientHidden;
467 }
468
469 void setClientHidden(boolean hideClient) {
470 if (mClientHidden == hideClient || (hideClient && mDeferHidingClient)) {
471 return;
472 }
Jorim Jaggi067b5bf2018-02-23 17:42:39 +0100473 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "setClientHidden: " + this
474 + " clientHidden=" + hideClient + " Callers=" + Debug.getCallers(5));
Wale Ogunwale89973222017-04-23 18:39:45 -0700475 mClientHidden = hideClient;
476 sendAppVisibilityToClients();
477 }
478
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800479 void setVisibility(boolean visible, boolean deferHidingClient) {
480 final AppTransition appTransition = getDisplayContent().mAppTransition;
481
482 // Don't set visibility to false if we were already not visible. This prevents WM from
483 // adding the app to the closing app list which doesn't make sense for something that is
484 // already not visible. However, set visibility to true even if we are already visible.
485 // This makes sure the app is added to the opening apps list so that the right
486 // transition can be selected.
487 // TODO: Probably a good idea to separate the concept of opening/closing apps from the
488 // concept of setting visibility...
489 if (!visible && hiddenRequested) {
490
491 if (!deferHidingClient && mDeferHidingClient) {
492 // We previously deferred telling the client to hide itself when visibility was
493 // initially set to false. Now we would like it to hide, so go ahead and set it.
494 mDeferHidingClient = deferHidingClient;
495 setClientHidden(true);
496 }
497 return;
498 }
499
500 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) {
501 Slog.v(TAG_WM, "setAppVisibility("
502 + appToken + ", visible=" + visible + "): " + appTransition
503 + " hidden=" + isHidden() + " hiddenRequested="
504 + hiddenRequested + " Callers=" + Debug.getCallers(6));
505 }
506
507 final DisplayContent displayContent = getDisplayContent();
508 displayContent.mOpeningApps.remove(this);
509 displayContent.mClosingApps.remove(this);
510 waitingToShow = false;
511 hiddenRequested = !visible;
512 mDeferHidingClient = deferHidingClient;
513
514 if (!visible) {
515 // If the app is dead while it was visible, we kept its dead window on screen.
516 // Now that the app is going invisible, we can remove it. It will be restarted
517 // if made visible again.
518 removeDeadWindows();
519 } else {
520 if (!appTransition.isTransitionSet()
521 && appTransition.isReady()) {
522 // Add the app mOpeningApps if transition is unset but ready. This means
523 // we're doing a screen freeze, and the unfreeze will wait for all opening
524 // apps to be ready.
525 displayContent.mOpeningApps.add(this);
526 }
527 startingMoved = false;
528 // If the token is currently hidden (should be the common case), or has been
529 // stopped, then we need to set up to wait for its windows to be ready.
530 if (isHidden() || mAppStopped) {
531 clearAllDrawn();
532
533 // If the app was already visible, don't reset the waitingToShow state.
534 if (isHidden()) {
535 waitingToShow = true;
536 }
537 }
538
539 // In the case where we are making an app visible but holding off for a transition,
540 // we still need to tell the client to make its windows visible so they get drawn.
541 // Otherwise, we will wait on performing the transition until all windows have been
542 // drawn, they never will be, and we are sad.
543 setClientHidden(false);
544
545 requestUpdateWallpaperIfNeeded();
546
547 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "No longer Stopped: " + this);
548 mAppStopped = false;
549
550 transferStartingWindowFromHiddenAboveTokenIfNeeded();
551 }
552
553 // If we are preparing an app transition, then delay changing
554 // the visibility of this token until we execute that transition.
555 if (okToAnimate() && appTransition.isTransitionSet()) {
556 inPendingTransaction = true;
557 if (visible) {
558 displayContent.mOpeningApps.add(this);
559 mEnteringAnimation = true;
560 } else {
561 displayContent.mClosingApps.add(this);
562 mEnteringAnimation = false;
563 }
564 if (appTransition.getAppTransition()
565 == WindowManager.TRANSIT_TASK_OPEN_BEHIND) {
566 // We're launchingBehind, add the launching activity to mOpeningApps.
567 final WindowState win = getDisplayContent().findFocusedWindow();
568 if (win != null) {
569 final AppWindowToken focusedToken = win.mAppToken;
570 if (focusedToken != null) {
571 if (DEBUG_APP_TRANSITIONS) {
572 Slog.d(TAG_WM, "TRANSIT_TASK_OPEN_BEHIND, "
573 + " adding " + focusedToken + " to mOpeningApps");
574 }
575 // Force animation to be loaded.
576 focusedToken.setHidden(true);
577 displayContent.mOpeningApps.add(focusedToken);
578 }
579 }
580 }
Garfield Tanb6776602019-02-20 14:44:26 -0800581 // Changes in opening apps and closing apps may cause orientation change.
582 reportDescendantOrientationChangeIfNeeded();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800583 return;
584 }
585
586 commitVisibility(null, visible, TRANSIT_UNSET, true, mVoiceInteraction);
587 updateReportedVisibilityLocked();
588 }
589
590 boolean commitVisibility(WindowManager.LayoutParams lp,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700591 boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
592
593 boolean delayed = false;
594 inPendingTransaction = false;
Wale Ogunwale9e4721f2017-05-23 19:37:30 -0700595 // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually
596 // been set by the app now.
597 mHiddenSetFromTransferredStartingWindow = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700598
599 // Allow for state changes and animation to be applied if:
600 // * token is transitioning visibility state
601 // * or the token was marked as hidden and is exiting before we had a chance to play the
602 // transition animation
603 // * or this is an opening app and windows are being replaced.
604 boolean visibilityChanged = false;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200605 if (isHidden() == visible || (isHidden() && mIsExiting) || (visible && waitingForReplacement())) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800606 final AccessibilityController accessibilityController =
607 mWmService.mAccessibilityController;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700608 boolean changed = false;
609 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM,
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200610 "Changing app " + this + " hidden=" + isHidden() + " performLayout=" + performLayout);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700611
612 boolean runningAppAnimation = false;
613
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100614 if (transit != WindowManager.TRANSIT_UNSET) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200615 if (applyAnimationLocked(lp, transit, visible, isVoiceInteraction)) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700616 delayed = runningAppAnimation = true;
617 }
618 final WindowState window = findMainWindow();
Rhed Jao02655dc2018-10-30 20:44:52 +0800619 if (window != null && accessibilityController != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700620 accessibilityController.onAppWindowTransitionLocked(window, transit);
621 }
622 changed = true;
623 }
624
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700625 final int windowsCount = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700626 for (int i = 0; i < windowsCount; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700627 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700628 changed |= win.onAppVisibilityChanged(visible, runningAppAnimation);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700629 }
630
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200631 setHidden(!visible);
632 hiddenRequested = !visible;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700633 visibilityChanged = true;
634 if (!visible) {
635 stopFreezingScreen(true, true);
636 } else {
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700637 // If we are being set visible, and the starting window is not yet displayed,
638 // then make sure it doesn't get displayed.
639 if (startingWindow != null && !startingWindow.isDrawnLw()) {
640 startingWindow.mPolicyVisibility = false;
641 startingWindow.mPolicyVisibilityAfterAnim = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700642 }
Jorim Jaggi38d44ec2017-06-14 16:04:59 -0700643
644 // We are becoming visible, so better freeze the screen with the windows that are
645 // getting visible so we also wait for them.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800646 forAllWindows(mWmService::makeWindowFreezingScreenIfNeededLocked, true);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700647 }
648
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800649 if (DEBUG_APP_TRANSITIONS) {
650 Slog.v(TAG_WM, "commitVisibility: " + this
651 + ": hidden=" + isHidden() + " hiddenRequested=" + hiddenRequested);
652 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700653
654 if (changed) {
Arthur Hung95b38a92018-07-20 18:56:12 +0800655 getDisplayContent().getInputMonitor().setUpdateInputWindowsNeededLw();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700656 if (performLayout) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800657 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700658 false /*updateInputWindows*/);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800659 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700660 }
Arthur Hung95b38a92018-07-20 18:56:12 +0800661 getDisplayContent().getInputMonitor().updateInputWindowsLw(false /*force*/);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700662 }
663 }
664
lumarkd14173e2019-03-27 19:14:33 +0800665 if (isReallyAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700666 delayed = true;
Jorim Jaggiab9fcb22018-03-15 23:46:12 +0100667 } else {
668
669 // We aren't animating anything, but exiting windows rely on the animation finished
670 // callback being called in case the AppWindowToken was pretending to be animating,
671 // which we might have done because we were in closing/opening apps list.
672 onAnimationFinished();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700673 }
674
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700675 for (int i = mChildren.size() - 1; i >= 0 && !delayed; i--) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100676 if ((mChildren.get(i)).isSelfOrChildAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700677 delayed = true;
678 }
679 }
680
681 if (visibilityChanged) {
682 if (visible && !delayed) {
683 // The token was made immediately visible, there will be no entrance animation.
684 // We need to inform the client the enter animation was finished.
685 mEnteringAnimation = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800686 mWmService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(
687 token);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700688 }
Robert Carr61b81112017-07-17 18:08:15 -0700689
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800690 // If we're becoming visible, immediately change client visibility as well. there seem
691 // to be some edge cases where we change our visibility but client visibility never gets
692 // updated.
Jorim Jaggi110839b2018-01-22 12:49:04 +0100693 // If we're becoming invisible, update the client visibility if we are not running an
694 // animation. Otherwise, we'll update client visibility in onAnimationFinished.
Jorim Jaggi3cad57f2018-02-20 18:32:01 +0100695 if (visible || !isReallyAnimating()) {
Jorim Jaggi110839b2018-01-22 12:49:04 +0100696 setClientHidden(!visible);
Jorim Jaggi4876b4a2018-01-11 15:43:49 +0100697 }
698
lumark588a3e82018-07-20 18:53:54 +0800699 if (!getDisplayContent().mClosingApps.contains(this)
700 && !getDisplayContent().mOpeningApps.contains(this)) {
chaviwa953fcf2018-03-01 12:00:39 -0800701 // The token is not closing nor opening, so even if there is an animation set, that
702 // doesn't mean that it goes through the normal app transition cycle so we have
703 // to inform the docked controller about visibility change.
704 // TODO(multi-display): notify docked divider on all displays where visibility was
705 // affected.
lumark588a3e82018-07-20 18:53:54 +0800706 getDisplayContent().getDockedDividerController().notifyAppVisibilityChanged();
chaviwa953fcf2018-03-01 12:00:39 -0800707
708 // Take the screenshot before possibly hiding the WSA, otherwise the screenshot
709 // will not be taken.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800710 mWmService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible);
chaviwa953fcf2018-03-01 12:00:39 -0800711 }
712
Robert Carre7cc44d2017-03-20 19:04:30 -0700713 // If we are hidden but there is no delay needed we immediately
714 // apply the Surface transaction so that the ActivityManager
Robert Carr61b81112017-07-17 18:08:15 -0700715 // can have some guarantee on the Surface state following
716 // setting the visibility. This captures cases like dismissing
717 // the docked or pinned stack where there is no app transition.
718 //
719 // In the case of a "Null" animation, there will be
720 // no animation but there will still be a transition set.
721 // We still need to delay hiding the surface such that it
722 // can be synchronized with showing the next surface in the transition.
lumark588a3e82018-07-20 18:53:54 +0800723 if (isHidden() && !delayed && !getDisplayContent().mAppTransition.isTransitionSet()) {
Robert Carr6914f082017-03-20 19:04:30 -0700724 SurfaceControl.openTransaction();
725 for (int i = mChildren.size() - 1; i >= 0; i--) {
726 mChildren.get(i).mWinAnimator.hide("immediately hidden");
727 }
728 SurfaceControl.closeTransaction();
729 }
Garfield Tanb6776602019-02-20 14:44:26 -0800730
731 // Visibility changes may cause orientation request change.
732 reportDescendantOrientationChangeIfNeeded();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700733 }
734
735 return delayed;
736 }
737
Garfield Tanb6776602019-02-20 14:44:26 -0800738 private void reportDescendantOrientationChangeIfNeeded() {
739 // Orientation request is exposed only when we're visible. Therefore visibility change
740 // will change requested orientation. Notify upward the hierarchy ladder to adjust
741 // configuration. This is important to cases where activities with incompatible
742 // orientations launch, or user goes back from an activity of bi-orientation to an
743 // activity with specified orientation.
744 if (mActivityRecord.getRequestedConfigurationOrientation() == getConfiguration().orientation
745 || getOrientationIgnoreVisibility() == SCREEN_ORIENTATION_UNSET) {
746 return;
747 }
748
749 final IBinder freezeToken =
750 mActivityRecord.mayFreezeScreenLocked(mActivityRecord.app)
751 ? mActivityRecord.appToken : null;
752 onDescendantOrientationChanged(freezeToken, mActivityRecord);
753 }
754
Jorim Jaggi87fdbcb2017-08-17 13:41:11 +0200755 /**
756 * @return The to top most child window for which {@link LayoutParams#isFullscreen()} returns
757 * true.
758 */
759 WindowState getTopFullscreenWindow() {
760 for (int i = mChildren.size() - 1; i >= 0; i--) {
761 final WindowState win = mChildren.get(i);
762 if (win != null && win.mAttrs.isFullscreen()) {
763 return win;
764 }
765 }
766 return null;
767 }
768
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800769 WindowState findMainWindow() {
Matthew Ng53e66b22018-01-12 17:13:13 -0800770 return findMainWindow(true);
771 }
772
773 /**
774 * Finds the main window that either has type base application or application starting if
775 * requested.
776 *
777 * @param includeStartingApp Allow to search application-starting windows to also be returned.
778 * @return The main window of type base application or application starting if requested.
779 */
780 WindowState findMainWindow(boolean includeStartingApp) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700781 WindowState candidate = null;
Matthew Ng53e66b22018-01-12 17:13:13 -0800782 for (int j = mChildren.size() - 1; j >= 0; --j) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700783 final WindowState win = mChildren.get(j);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700784 final int type = win.mAttrs.type;
785 // No need to loop through child window as base application and starting types can't be
786 // child windows.
Matthew Ng53e66b22018-01-12 17:13:13 -0800787 if (type == TYPE_BASE_APPLICATION
788 || (includeStartingApp && type == TYPE_APPLICATION_STARTING)) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700789 // In cases where there are multiple windows, we prefer the non-exiting window. This
Sungsoo Lim0d3d1f82015-12-02 14:47:59 +0900790 // happens for example when replacing windows during an activity relaunch. When
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700791 // constructing the animation, we want the new window, not the exiting one.
Wale Ogunwalec48a3542016-02-19 15:18:45 -0800792 if (win.mAnimatingExit) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700793 candidate = win;
794 } else {
795 return win;
796 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800797 }
798 }
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700799 return candidate;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800800 }
801
Wale Ogunwale6cae7652015-12-26 07:36:26 -0800802 boolean windowsAreFocusable() {
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800803 if (mTargetSdk < Build.VERSION_CODES.Q) {
804 final int pid = mActivityRecord != null
805 ? (mActivityRecord.app != null ? mActivityRecord.app.getPid() : 0) : 0;
806 final AppWindowToken topFocusedAppOfMyProcess =
807 mWmService.mRoot.mTopFocusedAppByProcess.get(pid);
808 if (topFocusedAppOfMyProcess != null && topFocusedAppOfMyProcess != this) {
809 // For the apps below Q, there can be only one app which has the focused window per
810 // process, because legacy apps may not be ready for a multi-focus system.
811 return false;
812 }
813 }
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700814 return getWindowConfiguration().canReceiveKeys() || mAlwaysFocusable;
Wale Ogunwaled045c822015-12-02 09:14:28 -0800815 }
816
Wale Ogunwale571771c2016-08-26 13:18:50 -0700817 @Override
Wale Ogunwale44f21802016-09-02 12:49:48 -0700818 boolean isVisible() {
Wale Ogunwalee471be62016-10-03 07:53:55 -0700819 // If the app token isn't hidden then it is considered visible and there is no need to check
820 // its children windows to see if they are visible.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200821 return !isHidden();
Wale Ogunwale44f21802016-09-02 12:49:48 -0700822 }
823
824 @Override
Wale Ogunwalee287e192017-04-21 09:30:12 -0700825 void removeImmediately() {
826 onRemovedFromDisplay();
Yunfan Chen3a77f282018-12-12 15:47:52 -0800827 if (mActivityRecord != null) {
828 mActivityRecord.unregisterConfigurationChangeListener(this);
829 }
Wale Ogunwalee287e192017-04-21 09:30:12 -0700830 super.removeImmediately();
831 }
832
833 @Override
Wale Ogunwale571771c2016-08-26 13:18:50 -0700834 void removeIfPossible() {
Craig Mautnere3119b72015-01-20 15:02:36 -0800835 mIsExiting = false;
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800836 removeAllWindowsIfPossible();
Bryce Lee6d410262017-02-28 15:30:17 -0800837 removeImmediately();
Craig Mautnere3119b72015-01-20 15:02:36 -0800838 }
839
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700840 @Override
841 boolean checkCompleteDeferredRemoval() {
842 if (mIsExiting) {
843 removeIfPossible();
844 }
845 return super.checkCompleteDeferredRemoval();
846 }
847
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700848 void onRemovedFromDisplay() {
Wale Ogunwalee287e192017-04-21 09:30:12 -0700849 if (mRemovingFromDisplay) {
850 return;
851 }
852 mRemovingFromDisplay = true;
853
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700854 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app token: " + this);
855
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800856 boolean delayed = commitVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700857
lumark588a3e82018-07-20 18:53:54 +0800858 getDisplayContent().mOpeningApps.remove(this);
Evan Rosky2289ba12018-11-19 18:28:18 -0800859 getDisplayContent().mChangingApps.remove(this);
lumark588a3e82018-07-20 18:53:54 +0800860 getDisplayContent().mUnknownAppVisibilityController.appRemovedOrHidden(this);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800861 mWmService.mTaskSnapshotController.onAppRemoved(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700862 waitingToShow = false;
lumark588a3e82018-07-20 18:53:54 +0800863 if (getDisplayContent().mClosingApps.contains(this)) {
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700864 delayed = true;
lumark588a3e82018-07-20 18:53:54 +0800865 } else if (getDisplayContent().mAppTransition.isTransitionSet()) {
866 getDisplayContent().mClosingApps.add(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700867 delayed = true;
868 }
869
870 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app " + this + " delayed=" + delayed
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200871 + " animation=" + getAnimation() + " animating=" + isSelfAnimating());
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700872
873 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: "
874 + this + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
875
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800876 if (startingData != null) {
877 removeStartingWindow();
Jorim Jaggi19be6052017-08-03 18:33:43 +0200878 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800879
Winson Chung87e5d552017-04-05 11:49:38 -0700880 // If this window was animating, then we need to ensure that the app transition notifies
lumark588a3e82018-07-20 18:53:54 +0800881 // that animations have completed in DisplayContent.handleAnimatingStoppedAndTransition(),
882 // so add to that list now
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200883 if (isSelfAnimating()) {
lumark588a3e82018-07-20 18:53:54 +0800884 getDisplayContent().mNoAnimationNotifyOnTransitionFinished.add(token);
Winson Chung87e5d552017-04-05 11:49:38 -0700885 }
886
Wale Ogunwalee287e192017-04-21 09:30:12 -0700887 final TaskStack stack = getStack();
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700888 if (delayed && !isEmpty()) {
889 // set the token aside because it has an active animation to be finished
890 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM,
891 "removeAppToken make exiting: " + this);
Wale Ogunwalee287e192017-04-21 09:30:12 -0700892 if (stack != null) {
893 stack.mExitingAppTokens.add(this);
894 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700895 mIsExiting = true;
896 } else {
897 // Make sure there is no animation running on this token, so any windows associated
898 // with it will be removed as soon as their animations are complete
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200899 cancelAnimation();
Wale Ogunwale3106ae012017-05-16 08:56:37 -0700900 if (stack != null) {
901 stack.mExitingAppTokens.remove(this);
902 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700903 removeIfPossible();
904 }
905
906 removed = true;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700907 stopFreezingScreen(true, true);
Bryce Lee6d410262017-02-28 15:30:17 -0800908
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800909 final DisplayContent dc = getDisplayContent();
910 if (dc.mFocusedApp == this) {
911 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + this
912 + " displayId=" + dc.getDisplayId());
913 dc.setFocusedApp(null);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800914 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700915 }
Riddle Hsu192fe762019-01-15 23:41:57 +0800916 if (mLetterbox != null) {
917 mLetterbox.destroy();
918 mLetterbox = null;
919 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700920
921 if (!delayed) {
922 updateReportedVisibilityLocked();
923 }
Wale Ogunwalee287e192017-04-21 09:30:12 -0700924
925 mRemovingFromDisplay = false;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700926 }
927
Chong Zhange05bcb12016-07-26 17:47:29 -0700928 void clearAnimatingFlags() {
Chong Zhangb0d26702016-08-12 16:03:29 -0700929 boolean wallpaperMightChange = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700930 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700931 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700932 wallpaperMightChange |= win.clearAnimatingFlags();
Chong Zhange05bcb12016-07-26 17:47:29 -0700933 }
Chong Zhangb0d26702016-08-12 16:03:29 -0700934 if (wallpaperMightChange) {
935 requestUpdateWallpaperIfNeeded();
936 }
Chong Zhange05bcb12016-07-26 17:47:29 -0700937 }
938
Robert Carre12aece2016-02-02 22:43:27 -0800939 void destroySurfaces() {
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700940 destroySurfaces(false /*cleanupOnResume*/);
941 }
942
943 /**
944 * Destroy surfaces which have been marked as eligible by the animator, taking care to ensure
945 * the client has finished with them.
946 *
947 * @param cleanupOnResume whether this is done when app is resumed without fully stopped. If
948 * set to true, destroy only surfaces of removed windows, and clear relevant flags of the
949 * others so that they are ready to be reused. If set to false (common case), destroy all
950 * surfaces that's eligible, if the app is already stopped.
951 */
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700952 private void destroySurfaces(boolean cleanupOnResume) {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700953 boolean destroyedSomething = false;
Jorim Jaggia5e10572017-11-15 14:36:26 +0100954
955 // Copying to a different list as multiple children can be removed.
Jorim Jaggi59f3e922018-01-05 15:40:32 +0100956 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
Jorim Jaggia5e10572017-11-15 14:36:26 +0100957 for (int i = children.size() - 1; i >= 0; i--) {
958 final WindowState win = children.get(i);
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700959 destroyedSomething |= win.destroySurface(cleanupOnResume, mAppStopped);
Robert Carre12aece2016-02-02 22:43:27 -0800960 }
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700961 if (destroyedSomething) {
962 final DisplayContent dc = getDisplayContent();
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700963 dc.assignWindowLayers(true /*setLayoutNeeded*/);
Adrian Roos23df3a32018-03-15 15:41:13 +0100964 updateLetterboxSurface(null);
Robert Carre12aece2016-02-02 22:43:27 -0800965 }
966 }
967
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800968 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700969 * Notify that the app is now resumed, and it was not stopped before, perform a clean
970 * up of the surfaces
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800971 */
Jorim Jaggibae01b12017-04-11 16:29:10 -0700972 void notifyAppResumed(boolean wasStopped) {
Chong Zhangad24f962016-08-25 12:12:33 -0700973 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppResumed: wasStopped=" + wasStopped
Jorim Jaggibae01b12017-04-11 16:29:10 -0700974 + " " + this);
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700975 mAppStopped = false;
chaviwd3bf08d2017-08-01 17:24:59 -0700976 // Allow the window to turn the screen on once the app is resumed again.
977 setCanTurnScreenOn(true);
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700978 if (!wasStopped) {
979 destroySurfaces(true /*cleanupOnResume*/);
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800980 }
Robert Carre12aece2016-02-02 22:43:27 -0800981 }
982
Chong Zhangbef461f2015-10-27 11:38:24 -0700983 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700984 * Notify that the app has stopped, and it is okay to destroy any surfaces which were
985 * keeping alive in case they were still being used.
986 */
987 void notifyAppStopped() {
988 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: " + this);
989 mAppStopped = true;
990 destroySurfaces();
991 // Remove any starting window that was added for this app if they are still around.
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800992 removeStartingWindow();
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700993 }
994
Chong Zhang92147042016-05-09 12:47:11 -0700995 void clearAllDrawn() {
996 allDrawn = false;
997 deferClearAllDrawn = false;
Chong Zhangbef461f2015-10-27 11:38:24 -0700998 }
999
Bryce Lee6d410262017-02-28 15:30:17 -08001000 Task getTask() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001001 return (Task) getParent();
Bryce Lee6d410262017-02-28 15:30:17 -08001002 }
1003
Jorim Jaggi3878ca32017-02-02 17:13:05 -08001004 TaskStack getStack() {
1005 final Task task = getTask();
1006 if (task != null) {
1007 return task.mStack;
1008 } else {
1009 return null;
1010 }
1011 }
1012
Bryce Lee6d410262017-02-28 15:30:17 -08001013 @Override
Riddle Hsu3a4bb612019-01-31 00:02:22 +08001014 void onParentChanged() {
1015 super.onParentChanged();
Bryce Lee6d410262017-02-28 15:30:17 -08001016
Robert Carred3e83b2017-04-21 13:26:55 -07001017 final Task task = getTask();
1018
Bryce Lee6d410262017-02-28 15:30:17 -08001019 // When the associated task is {@code null}, the {@link AppWindowToken} can no longer
1020 // access visual elements like the {@link DisplayContent}. We must remove any associations
1021 // such as animations.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001022 if (!mReparenting) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001023 if (task == null) {
1024 // It is possible we have been marked as a closing app earlier. We must remove ourselves
1025 // from this list so we do not participate in any future animations.
lumark588a3e82018-07-20 18:53:54 +08001026 getDisplayContent().mClosingApps.remove(this);
Robert Carred3e83b2017-04-21 13:26:55 -07001027 } else if (mLastParent != null && mLastParent.mStack != null) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001028 task.mStack.mExitingAppTokens.remove(this);
1029 }
Bryce Lee6d410262017-02-28 15:30:17 -08001030 }
Jorim Jaggi6de61012018-03-19 14:53:23 +01001031 final TaskStack stack = getStack();
1032
1033 // If we reparent, make sure to remove ourselves from the old animation registry.
1034 if (mAnimatingAppWindowTokenRegistry != null) {
1035 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
1036 }
1037 mAnimatingAppWindowTokenRegistry = stack != null
1038 ? stack.getAnimatingAppWindowTokenRegistry()
1039 : null;
1040
Robert Carred3e83b2017-04-21 13:26:55 -07001041 mLastParent = task;
chaviwdcf76ec2019-01-11 16:48:46 -08001042
1043 updateColorTransform();
Bryce Lee6d410262017-02-28 15:30:17 -08001044 }
1045
Wale Ogunwalefa854eb2016-09-20 13:43:52 -07001046 void postWindowRemoveStartingWindowCleanup(WindowState win) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001047 // TODO: Something smells about the code below...Is there a better way?
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001048 if (startingWindow == win) {
1049 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Notify removed startingWindow " + win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001050 removeStartingWindow();
Wale Ogunwale6c459212017-05-17 08:56:03 -07001051 } else if (mChildren.size() == 0) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001052 // If this is the last window and we had requested a starting transition window,
1053 // well there is no point now.
Jorim Jaggi02886a82016-12-06 09:10:06 -08001054 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Nulling last startingData");
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001055 startingData = null;
Wale Ogunwale6c459212017-05-17 08:56:03 -07001056 if (mHiddenSetFromTransferredStartingWindow) {
1057 // We set the hidden state to false for the token from a transferred starting window.
1058 // We now reset it back to true since the starting window was the last window in the
1059 // token.
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001060 setHidden(true);
Wale Ogunwale6c459212017-05-17 08:56:03 -07001061 }
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01001062 } else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001063 // If this is the last window except for a starting transition window,
1064 // we need to get rid of the starting transition.
Jorim Jaggie4b0f282017-05-17 15:10:29 +02001065 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Last window, removing starting window "
1066 + win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001067 removeStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001068 }
1069 }
1070
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001071 void removeDeadWindows() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001072 for (int winNdx = mChildren.size() - 1; winNdx >= 0; --winNdx) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001073 WindowState win = mChildren.get(winNdx);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001074 if (win.mAppDied) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001075 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.w(TAG,
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001076 "removeDeadWindows: " + win);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001077 // Set mDestroying, we don't want any animation or delayed removal here.
1078 win.mDestroying = true;
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001079 // Also removes child windows.
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001080 win.removeIfPossible();
Chong Zhang112eb8c2015-11-02 11:17:00 -08001081 }
1082 }
1083 }
1084
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001085 boolean hasWindowsAlive() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001086 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001087 // No need to loop through child windows as the answer should be the same as that of the
1088 // parent window.
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001089 if (!(mChildren.get(i)).mAppDied) {
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001090 return true;
1091 }
1092 }
1093 return false;
1094 }
1095
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001096 void setWillReplaceWindows(boolean animate) {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001097 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
1098 "Marking app token " + this + " with replacing windows.");
Robert Carra1eb4392015-12-10 12:43:51 -08001099
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001100 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001101 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001102 w.setWillReplaceWindow(animate);
Robert Carra1eb4392015-12-10 12:43:51 -08001103 }
Robert Carra1eb4392015-12-10 12:43:51 -08001104 }
1105
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001106 void setWillReplaceChildWindows() {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001107 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Marking app token " + this
Robert Carr23fa16b2016-01-13 13:19:58 -08001108 + " with replacing child windows.");
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001109 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001110 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001111 w.setWillReplaceChildWindows();
Robert Carr23fa16b2016-01-13 13:19:58 -08001112 }
1113 }
1114
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001115 void clearWillReplaceWindows() {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001116 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
1117 "Resetting app token " + this + " of replacing window marks.");
Chong Zhangf596cd52016-01-05 13:42:44 -08001118
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001119 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001120 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001121 w.clearWillReplaceWindow();
Chong Zhangf596cd52016-01-05 13:42:44 -08001122 }
1123 }
1124
Chong Zhang4d7369a2016-04-25 16:09:14 -07001125 void requestUpdateWallpaperIfNeeded() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001126 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001127 final WindowState w = mChildren.get(i);
Chong Zhang4d7369a2016-04-25 16:09:14 -07001128 w.requestUpdateWallpaperIfNeeded();
1129 }
1130 }
1131
Chong Zhangd78ddb42016-03-02 17:01:14 -08001132 boolean isRelaunching() {
1133 return mPendingRelaunchCount > 0;
1134 }
1135
Robert Carr68375192017-06-13 12:41:53 -07001136 boolean shouldFreezeBounds() {
1137 final Task task = getTask();
1138
1139 // For freeform windows, we can't freeze the bounds at the moment because this would make
1140 // the resizing unresponsive.
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001141 if (task == null || task.inFreeformWindowingMode()) {
Robert Carr68375192017-06-13 12:41:53 -07001142 return false;
1143 }
1144
1145 // We freeze the bounds while drag resizing to deal with the time between
1146 // the divider/drag handle being released, and the handling it's new
1147 // configuration. If we are relaunched outside of the drag resizing state,
1148 // we need to be careful not to do this.
1149 return getTask().isDragResizing();
1150 }
1151
Chong Zhangd78ddb42016-03-02 17:01:14 -08001152 void startRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001153 if (shouldFreezeBounds()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08001154 freezeBounds();
1155 }
Robert Carrd5c7dd62017-03-08 10:39:30 -08001156
1157 // In the process of tearing down before relaunching, the app will
1158 // try and clean up it's child surfaces. We need to prevent this from
1159 // happening, so we sever the children, transfering their ownership
1160 // from the client it-self to the parent surface (owned by us).
Robert Carr29daa922018-04-27 11:56:48 -07001161 detachChildren();
1162
1163 mPendingRelaunchCount++;
1164 }
1165
1166 void detachChildren() {
Robert Carrfd8e93b2018-05-10 13:40:25 -07001167 SurfaceControl.openTransaction();
Robert Carrd5c7dd62017-03-08 10:39:30 -08001168 for (int i = mChildren.size() - 1; i >= 0; i--) {
1169 final WindowState w = mChildren.get(i);
1170 w.mWinAnimator.detachChildren();
1171 }
Robert Carrfd8e93b2018-05-10 13:40:25 -07001172 SurfaceControl.closeTransaction();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001173 }
1174
1175 void finishRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001176 unfreezeBounds();
1177
Chong Zhangd78ddb42016-03-02 17:01:14 -08001178 if (mPendingRelaunchCount > 0) {
1179 mPendingRelaunchCount--;
Bryce Lee081554b2017-05-25 07:52:12 -07001180 } else {
1181 // Update keyguard flags upon finishing relaunch.
1182 checkKeyguardFlagsChanged();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001183 }
1184 }
1185
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001186 void clearRelaunching() {
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001187 if (mPendingRelaunchCount == 0) {
1188 return;
1189 }
Robert Carr68375192017-06-13 12:41:53 -07001190 unfreezeBounds();
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001191 mPendingRelaunchCount = 0;
1192 }
1193
Wale Ogunwale07bcab72016-10-14 15:30:09 -07001194 /**
1195 * Returns true if the new child window we are adding to this token is considered greater than
1196 * the existing child window in this token in terms of z-order.
1197 */
1198 @Override
1199 protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
1200 WindowState existingWindow) {
1201 final int type1 = newWindow.mAttrs.type;
1202 final int type2 = existingWindow.mAttrs.type;
1203
1204 // Base application windows should be z-ordered BELOW all other windows in the app token.
1205 if (type1 == TYPE_BASE_APPLICATION && type2 != TYPE_BASE_APPLICATION) {
1206 return false;
1207 } else if (type1 != TYPE_BASE_APPLICATION && type2 == TYPE_BASE_APPLICATION) {
1208 return true;
1209 }
1210
1211 // Starting windows should be z-ordered ABOVE all other windows in the app token.
1212 if (type1 == TYPE_APPLICATION_STARTING && type2 != TYPE_APPLICATION_STARTING) {
1213 return true;
1214 } else if (type1 != TYPE_APPLICATION_STARTING && type2 == TYPE_APPLICATION_STARTING) {
1215 return false;
1216 }
1217
1218 // Otherwise the new window is greater than the existing window.
1219 return true;
1220 }
1221
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001222 @Override
Robert Carra1eb4392015-12-10 12:43:51 -08001223 void addWindow(WindowState w) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001224 super.addWindow(w);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001225
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001226 boolean gotReplacementWindow = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001227 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001228 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001229 gotReplacementWindow |= candidate.setReplacementWindowIfNeeded(w);
1230 }
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001231
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001232 // if we got a replacement window, reset the timeout to give drawing more time
1233 if (gotReplacementWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001234 mWmService.scheduleWindowReplacementTimeouts(this);
Robert Carra1eb4392015-12-10 12:43:51 -08001235 }
Jorim Jaggife762342016-10-13 14:33:27 +02001236 checkKeyguardFlagsChanged();
1237 }
1238
1239 @Override
1240 void removeChild(WindowState child) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001241 if (!mChildren.contains(child)) {
1242 // This can be true when testing.
1243 return;
1244 }
Jorim Jaggife762342016-10-13 14:33:27 +02001245 super.removeChild(child);
1246 checkKeyguardFlagsChanged();
Adrian Roos23df3a32018-03-15 15:41:13 +01001247 updateLetterboxSurface(child);
Robert Carra1eb4392015-12-10 12:43:51 -08001248 }
1249
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001250 private boolean waitingForReplacement() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001251 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001252 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001253 if (candidate.waitingForReplacement()) {
Robert Carra1eb4392015-12-10 12:43:51 -08001254 return true;
1255 }
1256 }
1257 return false;
1258 }
1259
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001260 void onWindowReplacementTimeout() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001261 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001262 (mChildren.get(i)).onWindowReplacementTimeout();
Robert Carra1eb4392015-12-10 12:43:51 -08001263 }
1264 }
1265
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001266 void reparent(Task task, int position) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001267 if (DEBUG_ADD_REMOVE) {
1268 Slog.i(TAG_WM, "reparent: moving app token=" + this
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001269 + " to task=" + task.mTaskId + " at " + position);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001270 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001271 if (task == null) {
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001272 throw new IllegalArgumentException("reparent: could not find task");
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001273 }
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001274 final Task currentTask = getTask();
1275 if (task == currentTask) {
Winson Chung30480042017-01-26 10:55:34 -08001276 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001277 "window token=" + this + " already child of task=" + currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001278 }
Bryce Lee6d410262017-02-28 15:30:17 -08001279
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001280 if (currentTask.mStack != task.mStack) {
Bryce Lee6d410262017-02-28 15:30:17 -08001281 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001282 "window token=" + this + " current task=" + currentTask
Bryce Lee6d410262017-02-28 15:30:17 -08001283 + " belongs to a different stack than " + task);
1284 }
1285
Winson Chung30480042017-01-26 10:55:34 -08001286 if (DEBUG_ADD_REMOVE) Slog.i(TAG, "reParentWindowToken: removing window token=" + this
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001287 + " from task=" + currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001288 final DisplayContent prevDisplayContent = getDisplayContent();
1289
Bryce Lee6d410262017-02-28 15:30:17 -08001290 mReparenting = true;
1291
Winson Chung30480042017-01-26 10:55:34 -08001292 getParent().removeChild(this);
1293 task.addChild(this, position);
1294
Bryce Lee6d410262017-02-28 15:30:17 -08001295 mReparenting = false;
1296
Winson Chung30480042017-01-26 10:55:34 -08001297 // Relayout display(s).
1298 final DisplayContent displayContent = task.getDisplayContent();
1299 displayContent.setLayoutNeeded();
1300 if (prevDisplayContent != displayContent) {
1301 onDisplayChanged(displayContent);
1302 prevDisplayContent.setLayoutNeeded();
1303 }
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001304 getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
Winson Chung30480042017-01-26 10:55:34 -08001305 }
1306
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001307 @Override
1308 void onDisplayChanged(DisplayContent dc) {
1309 DisplayContent prevDc = mDisplayContent;
1310 super.onDisplayChanged(dc);
Evan Rosky25b56192019-02-06 16:10:56 -08001311 if (prevDc == null) {
1312 return;
1313 }
1314 if (prevDc.mChangingApps.contains(this)) {
1315 // This gets called *after* the AppWindowToken has been reparented to the new display.
1316 // That reparenting resulted in this window changing modes (eg. FREEFORM -> FULLSCREEN),
1317 // so this token is now "frozen" while waiting for the animation to start on prevDc
1318 // (which will be cancelled since the window is no-longer a child). However, since this
1319 // is no longer a child of prevDc, this won't be notified of the cancelled animation,
1320 // so we need to cancel the change transition here.
1321 clearChangeLeash(getPendingTransaction(), true /* cancel */);
1322 }
1323 if (prevDc.mFocusedApp == this) {
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001324 prevDc.setFocusedApp(null);
lumarkbf844642018-11-23 17:11:36 +08001325 final TaskStack stack = dc.getTopStack();
1326 if (stack != null) {
1327 final Task task = stack.getTopChild();
1328 if (task != null && task.getTopChild() == this) {
1329 dc.setFocusedApp(this);
1330 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001331 }
1332 }
Riddle Hsu192fe762019-01-15 23:41:57 +08001333
1334 if (prevDc != mDisplayContent && mLetterbox != null) {
1335 mLetterbox.onMovedToDisplay(mDisplayContent.getDisplayId());
1336 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001337 }
1338
Jorim Jaggi0429f352015-12-22 16:29:16 +01001339 /**
1340 * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds
1341 * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even
1342 * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen
1343 * with a queue.
1344 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001345 private void freezeBounds() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001346 final Task task = getTask();
1347 mFrozenBounds.offer(new Rect(task.mPreparedFrozenBounds));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001348
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001349 if (task.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001350 // We didn't call prepareFreezingBounds on the task, so use the current value.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001351 mFrozenMergedConfig.offer(new Configuration(task.getConfiguration()));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001352 } else {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001353 mFrozenMergedConfig.offer(new Configuration(task.mPreparedFrozenMergedConfig));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001354 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001355 // Calling unset() to make it equal to Configuration.EMPTY.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001356 task.mPreparedFrozenMergedConfig.unset();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001357 }
1358
1359 /**
1360 * Unfreezes the previously frozen bounds. See {@link #freezeBounds}.
1361 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001362 private void unfreezeBounds() {
Robert Carr68375192017-06-13 12:41:53 -07001363 if (mFrozenBounds.isEmpty()) {
1364 return;
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001365 }
Robert Carr68375192017-06-13 12:41:53 -07001366 mFrozenBounds.remove();
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001367 if (!mFrozenMergedConfig.isEmpty()) {
1368 mFrozenMergedConfig.remove();
1369 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001370 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001371 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001372 win.onUnfreezeBounds();
Jorim Jaggi4846ee32016-01-07 17:39:12 +01001373 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001374 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001375 }
1376
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001377 void setAppLayoutChanges(int changes, String reason) {
1378 if (!mChildren.isEmpty()) {
1379 final DisplayContent dc = getDisplayContent();
1380 dc.pendingLayoutChanges |= changes;
1381 if (DEBUG_LAYOUT_REPEATS) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001382 mWmService.mWindowPlacerLocked.debugLayoutRepeats(reason, dc.pendingLayoutChanges);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001383 }
1384 }
1385 }
1386
1387 void removeReplacedWindowIfNeeded(WindowState replacement) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001388 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001389 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001390 if (win.removeReplacedWindowIfNeeded(replacement)) {
1391 return;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001392 }
1393 }
1394 }
1395
1396 void startFreezingScreen() {
1397 if (DEBUG_ORIENTATION) logWithStack(TAG, "Set freezing of " + appToken + ": hidden="
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001398 + isHidden() + " freezing=" + mFreezingScreen + " hiddenRequested="
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001399 + hiddenRequested);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001400 if (!hiddenRequested) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001401 if (!mFreezingScreen) {
1402 mFreezingScreen = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001403 mWmService.registerAppFreezeListener(this);
1404 mWmService.mAppsFreezingScreen++;
1405 if (mWmService.mAppsFreezingScreen == 1) {
1406 mWmService.startFreezingDisplayLocked(0, 0, getDisplayContent());
1407 mWmService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
1408 mWmService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001409 }
1410 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001411 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001412 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001413 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001414 w.onStartFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001415 }
1416 }
1417 }
1418
1419 void stopFreezingScreen(boolean unfreezeSurfaceNow, boolean force) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001420 if (!mFreezingScreen) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001421 return;
1422 }
1423 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + this + " force=" + force);
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001424 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001425 boolean unfrozeWindows = false;
1426 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001427 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001428 unfrozeWindows |= w.onStopFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001429 }
1430 if (force || unfrozeWindows) {
1431 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "No longer freezing: " + this);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001432 mFreezingScreen = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001433 mWmService.unregisterAppFreezeListener(this);
1434 mWmService.mAppsFreezingScreen--;
1435 mWmService.mLastFinishedFreezeSource = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001436 }
1437 if (unfreezeSurfaceNow) {
1438 if (unfrozeWindows) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001439 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001440 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001441 mWmService.stopFreezingDisplayLocked();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001442 }
1443 }
1444
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001445 @Override
1446 public void onAppFreezeTimeout() {
1447 Slog.w(TAG_WM, "Force clearing freeze: " + this);
1448 stopFreezingScreen(true, true);
1449 }
1450
Jorim Jaggi60f9c972018-02-01 19:21:07 +01001451 /**
1452 * Tries to transfer the starting window from a token that's above ourselves in the task but
1453 * not visible anymore. This is a common scenario apps use: Trampoline activity T start main
1454 * activity M in the same task. Now, when reopening the task, T starts on top of M but then
1455 * immediately finishes after, so we have to transfer T to M.
1456 */
1457 void transferStartingWindowFromHiddenAboveTokenIfNeeded() {
1458 final Task task = getTask();
1459 for (int i = task.mChildren.size() - 1; i >= 0; i--) {
1460 final AppWindowToken fromToken = task.mChildren.get(i);
1461 if (fromToken == this) {
1462 return;
1463 }
1464 if (fromToken.hiddenRequested && transferStartingWindow(fromToken.token)) {
1465 return;
1466 }
1467 }
1468 }
1469
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001470 boolean transferStartingWindow(IBinder transferFrom) {
Wale Ogunwale02319a62016-09-26 15:21:22 -07001471 final AppWindowToken fromToken = getDisplayContent().getAppWindowToken(transferFrom);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001472 if (fromToken == null) {
1473 return false;
1474 }
1475
1476 final WindowState tStartingWindow = fromToken.startingWindow;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08001477 if (tStartingWindow != null && fromToken.startingSurface != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001478 // In this case, the starting icon has already been displayed, so start
1479 // letting windows get shown immediately without any more transitions.
lumark588a3e82018-07-20 18:53:54 +08001480 getDisplayContent().mSkipAppTransitionAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001481
1482 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Moving existing starting " + tStartingWindow
1483 + " from " + fromToken + " to " + this);
1484
1485 final long origId = Binder.clearCallingIdentity();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001486 try {
1487 // Transfer the starting window over to the new token.
1488 startingData = fromToken.startingData;
1489 startingSurface = fromToken.startingSurface;
1490 startingDisplayed = fromToken.startingDisplayed;
1491 fromToken.startingDisplayed = false;
1492 startingWindow = tStartingWindow;
1493 reportedVisible = fromToken.reportedVisible;
1494 fromToken.startingData = null;
1495 fromToken.startingSurface = null;
1496 fromToken.startingWindow = null;
1497 fromToken.startingMoved = true;
1498 tStartingWindow.mToken = this;
1499 tStartingWindow.mAppToken = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001500
Peter Visontay3556a3b2017-11-01 17:23:17 +00001501 if (DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
1502 "Removing starting " + tStartingWindow + " from " + fromToken);
1503 fromToken.removeChild(tStartingWindow);
1504 fromToken.postWindowRemoveStartingWindowCleanup(tStartingWindow);
1505 fromToken.mHiddenSetFromTransferredStartingWindow = false;
1506 addWindow(tStartingWindow);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001507
Peter Visontay3556a3b2017-11-01 17:23:17 +00001508 // Propagate other interesting state between the tokens. If the old token is displayed,
1509 // we should immediately force the new one to be displayed. If it is animating, we need
1510 // to move that animation to the new one.
1511 if (fromToken.allDrawn) {
1512 allDrawn = true;
1513 deferClearAllDrawn = fromToken.deferClearAllDrawn;
1514 }
1515 if (fromToken.firstWindowDrawn) {
1516 firstWindowDrawn = true;
1517 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001518 if (!fromToken.isHidden()) {
1519 setHidden(false);
Peter Visontay3556a3b2017-11-01 17:23:17 +00001520 hiddenRequested = false;
1521 mHiddenSetFromTransferredStartingWindow = true;
1522 }
1523 setClientHidden(fromToken.mClientHidden);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001524
Jorim Jaggi980c9de2017-11-17 01:41:37 +01001525 transferAnimation(fromToken);
1526
1527 // When transferring an animation, we no longer need to apply an animation to the
1528 // the token we transfer the animation over. Thus, remove the animation from
1529 // pending opening apps.
lumark588a3e82018-07-20 18:53:54 +08001530 getDisplayContent().mOpeningApps.remove(this);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001531
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001532 mWmService.updateFocusedWindowLocked(
Peter Visontay3556a3b2017-11-01 17:23:17 +00001533 UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/);
1534 getDisplayContent().setLayoutNeeded();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001535 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001536 } finally {
1537 Binder.restoreCallingIdentity(origId);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001538 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001539 return true;
1540 } else if (fromToken.startingData != null) {
1541 // The previous app was getting ready to show a
1542 // starting window, but hasn't yet done so. Steal it!
1543 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
1544 "Moving pending starting from " + fromToken + " to " + this);
1545 startingData = fromToken.startingData;
1546 fromToken.startingData = null;
1547 fromToken.startingMoved = true;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001548 scheduleAddStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001549 return true;
1550 }
1551
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001552 // TODO: Transfer thumbnail
1553
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001554 return false;
1555 }
1556
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001557 boolean isLastWindow(WindowState win) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001558 return mChildren.size() == 1 && mChildren.get(0) == win;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001559 }
1560
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001561 @Override
1562 void onAppTransitionDone() {
1563 sendingToBottom = false;
1564 }
1565
Wale Ogunwale51362492016-09-08 17:49:17 -07001566 /**
1567 * We override because this class doesn't want its children affecting its reported orientation
1568 * in anyway.
1569 */
1570 @Override
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001571 int getOrientation(int candidate) {
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001572 if (candidate == SCREEN_ORIENTATION_BEHIND) {
1573 // Allow app to specify orientation regardless of its visibility state if the current
1574 // candidate want us to use orientation behind. I.e. the visible app on-top of this one
1575 // wants us to use the orientation of the app behind it.
1576 return mOrientation;
1577 }
1578
Bryce Lee61fbcbc2017-03-10 14:14:03 -08001579 // The {@link AppWindowToken} should only specify an orientation when it is not closing or
1580 // going to the bottom. Allowing closing {@link AppWindowToken} to participate can lead to
1581 // an Activity in another task being started in the wrong orientation during the transition.
lumark588a3e82018-07-20 18:53:54 +08001582 if (!(sendingToBottom || getDisplayContent().mClosingApps.contains(this))
1583 && (isVisible() || getDisplayContent().mOpeningApps.contains(this))) {
Bryce Leea163b762017-01-24 11:05:01 -08001584 return mOrientation;
Wale Ogunwale51362492016-09-08 17:49:17 -07001585 }
Bryce Leea163b762017-01-24 11:05:01 -08001586
1587 return SCREEN_ORIENTATION_UNSET;
Wale Ogunwale51362492016-09-08 17:49:17 -07001588 }
1589
Wale Ogunwaleb198b742016-12-01 08:44:09 -08001590 /** Returns the app's preferred orientation regardless of its currently visibility state. */
1591 int getOrientationIgnoreVisibility() {
1592 return mOrientation;
1593 }
1594
Riddle Hsub398da32019-01-21 21:48:16 +08001595 /** @return {@code true} if the compatibility bounds is taking effect. */
1596 boolean inSizeCompatMode() {
1597 return mSizeCompatBounds != null;
1598 }
1599
1600 @Override
1601 float getSizeCompatScale() {
1602 return inSizeCompatMode() ? mSizeCompatScale : super.getSizeCompatScale();
1603 }
1604
1605 /**
1606 * @return Non-empty bounds if the activity has override bounds.
1607 * @see ActivityRecord#resolveOverrideConfiguration(Configuration)
1608 */
1609 Rect getResolvedOverrideBounds() {
1610 // Get bounds from resolved override configuration because it is computed with orientation.
1611 return getResolvedOverrideConfiguration().windowConfiguration.getBounds();
1612 }
1613
Craig Mautnerdbb79912012-03-01 18:59:14 -08001614 @Override
Winson Chunge55c0192017-08-24 14:50:48 -07001615 public void onConfigurationChanged(Configuration newParentConfig) {
1616 final int prevWinMode = getWindowingMode();
Evan Rosky2289ba12018-11-19 18:28:18 -08001617 mTmpPrevBounds.set(getBounds());
Winson Chunge55c0192017-08-24 14:50:48 -07001618 super.onConfigurationChanged(newParentConfig);
Riddle Hsub398da32019-01-21 21:48:16 +08001619
1620 final Task task = getTask();
1621 final Rect overrideBounds = getResolvedOverrideBounds();
1622 if (task != null && !overrideBounds.isEmpty()
1623 // If the changes come from change-listener, the incoming parent configuration is
1624 // still the old one. Make sure their orientations are the same to reduce computing
1625 // the compatibility bounds for the intermediate state.
Riddle Hsu04164182019-03-07 18:03:27 +08001626 && (task.mTaskRecord == null || task.mTaskRecord
1627 .getConfiguration().orientation == newParentConfig.orientation)) {
Riddle Hsub398da32019-01-21 21:48:16 +08001628 final Rect taskBounds = task.getBounds();
1629 // Since we only center the activity horizontally, if only the fixed height is smaller
1630 // than its container, the override bounds don't need to take effect.
1631 if ((overrideBounds.width() != taskBounds.width()
1632 || overrideBounds.height() > taskBounds.height())) {
1633 calculateCompatBoundsTransformation(newParentConfig);
1634 updateSurfacePosition();
1635 } else if (mSizeCompatBounds != null) {
1636 mSizeCompatBounds = null;
1637 mSizeCompatScale = 1f;
1638 updateSurfacePosition();
1639 }
1640 }
1641
Winson Chunge55c0192017-08-24 14:50:48 -07001642 final int winMode = getWindowingMode();
1643
1644 if (prevWinMode == winMode) {
1645 return;
1646 }
1647
1648 if (prevWinMode != WINDOWING_MODE_UNDEFINED && winMode == WINDOWING_MODE_PINNED) {
1649 // Entering PiP from fullscreen, reset the snap fraction
1650 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(this);
Winson Chung82267ce2018-04-06 16:38:26 -07001651 } else if (prevWinMode == WINDOWING_MODE_PINNED && winMode != WINDOWING_MODE_UNDEFINED
1652 && !isHidden()) {
Winson Chunge55c0192017-08-24 14:50:48 -07001653 // Leaving PiP to fullscreen, save the snap fraction based on the pre-animation bounds
1654 // for the next re-entry into PiP (assuming the activity is not hidden or destroyed)
1655 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
1656 if (pinnedStack != null) {
Winson Chung8efa1652018-06-06 09:34:23 -07001657 final Rect stackBounds;
1658 if (pinnedStack.lastAnimatingBoundsWasToFullscreen()) {
1659 // We are animating the bounds, use the pre-animation bounds to save the snap
1660 // fraction
1661 stackBounds = pinnedStack.mPreAnimationBounds;
1662 } else {
1663 // We skip the animation if the fullscreen configuration is not compatible, so
1664 // use the current bounds to calculate the saved snap fraction instead
1665 // (see PinnedActivityStack.skipResizeAnimation())
1666 stackBounds = mTmpRect;
1667 pinnedStack.getBounds(stackBounds);
1668 }
Winson Chunge55c0192017-08-24 14:50:48 -07001669 mDisplayContent.mPinnedStackControllerLocked.saveReentrySnapFraction(this,
Winson Chung8efa1652018-06-06 09:34:23 -07001670 stackBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001671 }
Evan Rosky2289ba12018-11-19 18:28:18 -08001672 } else if (shouldStartChangeTransition(prevWinMode, winMode)) {
1673 initializeChangeTransition(mTmpPrevBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001674 }
1675 }
1676
Evan Rosky2289ba12018-11-19 18:28:18 -08001677 private boolean shouldStartChangeTransition(int prevWinMode, int newWinMode) {
Evan Rosky25b56192019-02-06 16:10:56 -08001678 if (mWmService.mDisableTransitionAnimation
1679 || !isVisible()
1680 || getDisplayContent().mAppTransition.isTransitionSet()
1681 || getSurfaceControl() == null) {
Evan Rosky2289ba12018-11-19 18:28:18 -08001682 return false;
1683 }
1684 // Only do an animation into and out-of freeform mode for now. Other mode
1685 // transition animations are currently handled by system-ui.
1686 return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
1687 }
1688
1689 /**
1690 * Initializes a change transition. Because the app is visible already, there is a small period
1691 * of time where the user can see the app content/window update before the transition starts.
1692 * To prevent this, we immediately take a snapshot and place the app/snapshot into a leash which
1693 * "freezes" the location/crop until the transition starts.
1694 * <p>
1695 * Here's a walk-through of the process:
1696 * 1. Create a temporary leash ("interim-change-leash") and reparent the app to it.
1697 * 2. Set the temporary leash's position/crop to the current state.
1698 * 3. Create a snapshot and place that at the top of the leash to cover up content changes.
1699 * 4. Once the transition is ready, it will reparent the app to the animation leash.
1700 * 5. Detach the interim-change-leash.
1701 */
1702 private void initializeChangeTransition(Rect startBounds) {
1703 mDisplayContent.prepareAppTransition(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
1704 false /* alwaysKeepCurrent */, 0, false /* forceOverride */);
1705 mDisplayContent.mChangingApps.add(this);
1706 mTransitStartRect.set(startBounds);
1707
1708 final SurfaceControl.Builder builder = makeAnimationLeash()
1709 .setParent(getAnimationLeashParent())
1710 .setName(getSurfaceControl() + " - interim-change-leash");
1711 mTransitChangeLeash = builder.build();
1712 Transaction t = getPendingTransaction();
1713 t.setWindowCrop(mTransitChangeLeash, startBounds.width(), startBounds.height());
1714 t.setPosition(mTransitChangeLeash, startBounds.left, startBounds.top);
1715 t.show(mTransitChangeLeash);
1716 t.reparent(getSurfaceControl(), mTransitChangeLeash);
1717 onAnimationLeashCreated(t, mTransitChangeLeash);
1718
Evan Rosky966759f2019-01-15 10:33:58 -08001719 // Skip creating snapshot if this transition is controlled by a remote animator which
1720 // doesn't need it.
1721 ArraySet<Integer> activityTypes = new ArraySet<>();
1722 activityTypes.add(getActivityType());
1723 RemoteAnimationAdapter adapter =
1724 mDisplayContent.mAppTransitionController.getRemoteAnimationOverride(
1725 this, TRANSIT_TASK_CHANGE_WINDOWING_MODE, activityTypes);
1726 if (adapter != null && !adapter.getChangeNeedsSnapshot()) {
1727 return;
1728 }
1729
Evan Rosky2289ba12018-11-19 18:28:18 -08001730 if (mThumbnail == null && getTask() != null) {
1731 final TaskSnapshotController snapshotCtrl = mWmService.mTaskSnapshotController;
1732 final ArraySet<Task> tasks = new ArraySet<>();
1733 tasks.add(getTask());
1734 snapshotCtrl.snapshotTasks(tasks);
1735 snapshotCtrl.addSkipClosingAppSnapshotTasks(tasks);
1736 final ActivityManager.TaskSnapshot snapshot = snapshotCtrl.getSnapshot(
1737 getTask().mTaskId, getTask().mUserId, false /* restoreFromDisk */,
1738 false /* reducedResolution */);
Yunfan Chendcb1fcf2019-02-07 19:08:41 +09001739 if (snapshot != null) {
1740 mThumbnail = new AppWindowThumbnail(t, this, snapshot.getSnapshot(),
1741 true /* relative */);
1742 }
Evan Rosky2289ba12018-11-19 18:28:18 -08001743 }
1744 }
1745
1746 boolean isInChangeTransition() {
Evan Roskyec9488c2019-03-01 19:32:12 -08001747 return mTransitChangeLeash != null || AppTransition.isChangeTransit(mTransit);
Evan Rosky2289ba12018-11-19 18:28:18 -08001748 }
1749
Evan Rosky966759f2019-01-15 10:33:58 -08001750 @VisibleForTesting
1751 AppWindowThumbnail getThumbnail() {
1752 return mThumbnail;
1753 }
1754
Riddle Hsub398da32019-01-21 21:48:16 +08001755 /**
1756 * Calculates the scale and offset to horizontal center the size compatibility bounds into the
1757 * region which is available to application.
1758 */
1759 private void calculateCompatBoundsTransformation(Configuration newParentConfig) {
1760 final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds();
1761 final Rect viewportBounds = parentAppBounds != null
1762 ? parentAppBounds : newParentConfig.windowConfiguration.getBounds();
Riddle Hsu04164182019-03-07 18:03:27 +08001763 final Rect appBounds = getWindowConfiguration().getAppBounds();
1764 final Rect contentBounds = appBounds != null ? appBounds : getResolvedOverrideBounds();
Riddle Hsub398da32019-01-21 21:48:16 +08001765 final float contentW = contentBounds.width();
1766 final float contentH = contentBounds.height();
1767 final float viewportW = viewportBounds.width();
1768 final float viewportH = viewportBounds.height();
1769 // Only allow to scale down.
1770 mSizeCompatScale = (contentW <= viewportW && contentH <= viewportH)
1771 ? 1 : Math.min(viewportW / contentW, viewportH / contentH);
1772 final int offsetX = (int) ((viewportW - contentW * mSizeCompatScale + 1) * 0.5f)
1773 + viewportBounds.left;
1774
1775 if (mSizeCompatBounds == null) {
1776 mSizeCompatBounds = new Rect();
1777 }
1778 mSizeCompatBounds.set(contentBounds);
1779 mSizeCompatBounds.offsetTo(0, 0);
1780 mSizeCompatBounds.scale(mSizeCompatScale);
Riddle Hsu04164182019-03-07 18:03:27 +08001781 // The decor inset is included in height.
1782 mSizeCompatBounds.bottom += viewportBounds.top;
Riddle Hsub398da32019-01-21 21:48:16 +08001783 mSizeCompatBounds.left += offsetX;
1784 mSizeCompatBounds.right += offsetX;
1785 }
1786
1787 @Override
1788 public Rect getBounds() {
1789 if (mSizeCompatBounds != null) {
1790 return mSizeCompatBounds;
1791 }
1792 return super.getBounds();
1793 }
1794
1795 @Override
1796 public boolean matchParentBounds() {
1797 if (super.matchParentBounds()) {
1798 return true;
1799 }
1800 // An activity in size compatibility mode may have override bounds which equals to its
1801 // parent bounds, so the exact bounds should also be checked.
1802 final WindowContainer parent = getParent();
1803 return parent == null || parent.getBounds().equals(getResolvedOverrideBounds());
1804 }
1805
Winson Chunge55c0192017-08-24 14:50:48 -07001806 @Override
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001807 void checkAppWindowsReadyToShow() {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001808 if (allDrawn == mLastAllDrawn) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001809 return;
1810 }
1811
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001812 mLastAllDrawn = allDrawn;
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001813 if (!allDrawn) {
1814 return;
1815 }
1816
1817 // The token has now changed state to having all windows shown... what to do, what to do?
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001818 if (mFreezingScreen) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001819 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001820 stopFreezingScreen(false, true);
1821 if (DEBUG_ORIENTATION) Slog.i(TAG,
1822 "Setting mOrientationChangeComplete=true because wtoken " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001823 + " numInteresting=" + mNumInterestingWindows + " numDrawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001824 // This will set mOrientationChangeComplete and cause a pass through layout.
1825 setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001826 "checkAppWindowsReadyToShow: freezingScreen");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001827 } else {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001828 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001829
1830 // We can now show all of the drawn windows!
lumark588a3e82018-07-20 18:53:54 +08001831 if (!getDisplayContent().mOpeningApps.contains(this) && canShowWindows()) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001832 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001833 }
1834 }
1835 }
1836
Matthew Ng5d23afa2017-06-21 16:16:24 -07001837 /**
Bryce Leed390deb2017-06-22 13:14:28 -07001838 * Returns whether the drawn window states of this {@link AppWindowToken} has considered every
1839 * child {@link WindowState}. A child is considered if it has been passed into
1840 * {@link #updateDrawnWindowStates(WindowState)} after being added. This is used to determine
1841 * whether states, such as {@code allDrawn}, can be set, which relies on state variables such as
1842 * {@code mNumInterestingWindows}, which depend on all {@link WindowState}s being considered.
1843 *
1844 * @return {@code true} If all children have been considered, {@code false}.
1845 */
1846 private boolean allDrawnStatesConsidered() {
Bryce Lee6311c4b2017-07-06 14:09:29 -07001847 for (int i = mChildren.size() - 1; i >= 0; --i) {
1848 final WindowState child = mChildren.get(i);
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001849 if (child.mightAffectAllDrawn() && !child.getDrawnStateEvaluated()) {
Bryce Leed390deb2017-06-22 13:14:28 -07001850 return false;
1851 }
1852 }
1853 return true;
1854 }
1855
1856 /**
Matthew Ng5d23afa2017-06-21 16:16:24 -07001857 * Determines if the token has finished drawing. This should only be called from
1858 * {@link DisplayContent#applySurfaceChangesTransaction}
1859 */
Matthew Ng498c71d2017-04-18 13:55:45 -07001860 void updateAllDrawn() {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001861 if (!allDrawn) {
Matthew Ng498c71d2017-04-18 13:55:45 -07001862 // Number of drawn windows can be less when a window is being relaunched, wait for
Bryce Leed390deb2017-06-22 13:14:28 -07001863 // all windows to be launched and drawn for this token be considered all drawn.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001864 final int numInteresting = mNumInterestingWindows;
Bryce Leed390deb2017-06-22 13:14:28 -07001865
1866 // We must make sure that all present children have been considered (determined by
1867 // {@link #allDrawnStatesConsidered}) before evaluating whether everything has been
1868 // drawn.
1869 if (numInteresting > 0 && allDrawnStatesConsidered()
1870 && mNumDrawnWindows >= numInteresting && !isRelaunching()) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001871 if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawn: " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001872 + " interesting=" + numInteresting + " drawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001873 allDrawn = true;
1874 // Force an additional layout pass where
1875 // WindowStateAnimator#commitFinishDrawingLocked() will call performShowLocked().
Matthew Ng498c71d2017-04-18 13:55:45 -07001876 if (mDisplayContent != null) {
1877 mDisplayContent.setLayoutNeeded();
1878 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001879 mWmService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
Robert Carrecc06b32017-04-18 14:25:10 -07001880
Winson Chunge7ba6862017-05-24 12:13:33 -07001881 // Notify the pinned stack upon all windows drawn. If there was an animation in
1882 // progress then this signal will resume that animation.
Wale Ogunwale61911492017-10-11 08:50:50 -07001883 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
Winson Chunge7ba6862017-05-24 12:13:33 -07001884 if (pinnedStack != null) {
1885 pinnedStack.onAllWindowsDrawn();
Robert Carrecc06b32017-04-18 14:25:10 -07001886 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001887 }
1888 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001889 }
1890
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001891 boolean keyDispatchingTimedOut(String reason, int windowPid) {
1892 return mActivityRecord != null && mActivityRecord.keyDispatchingTimedOut(reason, windowPid);
1893 }
1894
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001895 /**
1896 * Updated this app token tracking states for interesting and drawn windows based on the window.
1897 *
1898 * @return Returns true if the input window is considered interesting and drawn while all the
1899 * windows in this app token where not considered drawn as of the last pass.
1900 */
1901 boolean updateDrawnWindowStates(WindowState w) {
Bryce Leed390deb2017-06-22 13:14:28 -07001902 w.setDrawnStateEvaluated(true /*evaluated*/);
1903
Jorim Jaggie4b0f282017-05-17 15:10:29 +02001904 if (DEBUG_STARTING_WINDOW_VERBOSE && w == startingWindow) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001905 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + w.isOnScreen()
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001906 + " allDrawn=" + allDrawn + " freezingScreen=" + mFreezingScreen);
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001907 }
1908
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001909 if (allDrawn && !mFreezingScreen) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001910 return false;
1911 }
1912
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001913 if (mLastTransactionSequence != mWmService.mTransactionSequence) {
1914 mLastTransactionSequence = mWmService.mTransactionSequence;
Matthew Ng53e66b22018-01-12 17:13:13 -08001915 mNumDrawnWindows = 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001916 startingDisplayed = false;
Matthew Ng53e66b22018-01-12 17:13:13 -08001917
1918 // There is the main base application window, even if it is exiting, wait for it
1919 mNumInterestingWindows = findMainWindow(false /* includeStartingApp */) != null ? 1 : 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001920 }
1921
1922 final WindowStateAnimator winAnimator = w.mWinAnimator;
1923
1924 boolean isInterestingAndDrawn = false;
1925
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001926 if (!allDrawn && w.mightAffectAllDrawn()) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001927 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
1928 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001929 + ", isAnimationSet=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001930 if (!w.isDrawnLw()) {
1931 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController
1932 + " pv=" + w.mPolicyVisibility
1933 + " mDrawState=" + winAnimator.drawStateToString()
1934 + " ph=" + w.isParentWindowHidden() + " th=" + hiddenRequested
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001935 + " a=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001936 }
1937 }
1938
1939 if (w != startingWindow) {
1940 if (w.isInteresting()) {
Matthew Ng53e66b22018-01-12 17:13:13 -08001941 // Add non-main window as interesting since the main app has already been added
1942 if (findMainWindow(false /* includeStartingApp */) != w) {
1943 mNumInterestingWindows++;
1944 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001945 if (w.isDrawnLw()) {
1946 mNumDrawnWindows++;
1947
1948 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, "tokenMayBeDrawn: "
1949 + this + " w=" + w + " numInteresting=" + mNumInterestingWindows
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001950 + " freezingScreen=" + mFreezingScreen
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001951 + " mAppFreezing=" + w.mAppFreezing);
1952
1953 isInterestingAndDrawn = true;
1954 }
1955 }
1956 } else if (w.isDrawnLw()) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001957 if (mActivityRecord != null) {
1958 mActivityRecord.onStartingWindowDrawn(SystemClock.uptimeMillis());
Jorim Jaggi3878ca32017-02-02 17:13:05 -08001959 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001960 startingDisplayed = true;
1961 }
1962 }
1963
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001964 return isInterestingAndDrawn;
1965 }
1966
Adrian Roos23df3a32018-03-15 15:41:13 +01001967 void layoutLetterbox(WindowState winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001968 final WindowState w = findMainWindow();
Adrian Roosf93b6d22018-03-21 13:48:26 +01001969 if (w == null || winHint != null && w != winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001970 return;
1971 }
Jorim Jaggia32da382018-03-28 18:01:22 +02001972 final boolean surfaceReady = w.isDrawnLw() // Regular case
Adrian Roosf93b6d22018-03-21 13:48:26 +01001973 || w.mWinAnimator.mSurfaceDestroyDeferred // The preserved surface is still ready.
1974 || w.isDragResizeChanged(); // Waiting for relayoutWindow to call preserveSurface.
Jorim Jaggi4981f152019-03-26 18:58:45 +01001975 final boolean needsLetterbox = surfaceReady && w.isLetterboxedAppWindow() && fillsParent();
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001976 if (needsLetterbox) {
1977 if (mLetterbox == null) {
1978 mLetterbox = new Letterbox(() -> makeChildSurface(null));
Riddle Hsu192fe762019-01-15 23:41:57 +08001979 mLetterbox.attachInput(w);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001980 }
Adrian Roos7af9d972018-11-30 15:26:27 +01001981 getPosition(mTmpPoint);
Evan Rosky67c15642019-04-24 13:17:28 -07001982 // Get the bounds of the "space-to-fill". In multi-window mode, the task-level
1983 // represents this. In fullscreen-mode, the stack does (since the orientation letterbox
1984 // is also applied to the task).
1985 Rect spaceToFill = (inMultiWindowMode() || getStack() == null)
1986 ? getTask().getDisplayedBounds() : getStack().getDisplayedBounds();
Evan Rosky4fb1e912019-03-06 13:54:43 -08001987 mLetterbox.layout(spaceToFill, w.getFrameLw(), mTmpPoint);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001988 } else if (mLetterbox != null) {
Adrian Roos23df3a32018-03-15 15:41:13 +01001989 mLetterbox.hide();
1990 }
1991 }
1992
1993 void updateLetterboxSurface(WindowState winHint) {
1994 final WindowState w = findMainWindow();
1995 if (w != winHint && winHint != null && w != null) {
1996 return;
1997 }
1998 layoutLetterbox(winHint);
1999 if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) {
2000 mLetterbox.applySurfaceChanges(mPendingTransaction);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002001 }
2002 }
2003
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07002004 @Override
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002005 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002006 // For legacy reasons we process the TaskStack.mExitingAppTokens first in DisplayContent
2007 // before the non-exiting app tokens. So, we skip the exiting app tokens here.
2008 // TODO: Investigate if we need to continue to do this or if we can just process them
2009 // in-order.
2010 if (mIsExiting && !waitingForReplacement()) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002011 return false;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002012 }
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002013 return forAllWindowsUnchecked(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002014 }
2015
lumark588a3e82018-07-20 18:53:54 +08002016 @Override
2017 void forAllAppWindows(Consumer<AppWindowToken> callback) {
2018 callback.accept(this);
2019 }
2020
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002021 boolean forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback,
2022 boolean traverseTopToBottom) {
2023 return super.forAllWindows(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002024 }
2025
2026 @Override
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002027 AppWindowToken asAppWindowToken() {
2028 // I am an app window token!
2029 return this;
2030 }
2031
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002032 boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
2033 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
2034 IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
2035 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
2036 // If the display is frozen, we won't do anything until the actual window is
2037 // displayed so there is no reason to put in the starting window.
2038 if (!okToDisplay()) {
2039 return false;
2040 }
2041
2042 if (startingData != null) {
2043 return false;
2044 }
2045
2046 final WindowState mainWin = findMainWindow();
2047 if (mainWin != null && mainWin.mWinAnimator.getShown()) {
2048 // App already has a visible window...why would you want a starting window?
2049 return false;
2050 }
2051
2052 final ActivityManager.TaskSnapshot snapshot =
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002053 mWmService.mTaskSnapshotController.getSnapshot(
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002054 getTask().mTaskId, getTask().mUserId,
2055 false /* restoreFromDisk */, false /* reducedResolution */);
2056 final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
2057 allowTaskSnapshot, activityCreated, fromRecents, snapshot);
2058
2059 if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
2060 return createSnapshot(snapshot);
2061 }
2062
2063 // If this is a translucent window, then don't show a starting window -- the current
2064 // effect (a full-screen opaque starting window that fades away to the real contents
2065 // when it is ready) does not work for this.
2066 if (DEBUG_STARTING_WINDOW) {
2067 Slog.v(TAG, "Checking theme of starting window: 0x" + Integer.toHexString(theme));
2068 }
2069 if (theme != 0) {
2070 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
2071 com.android.internal.R.styleable.Window,
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002072 mWmService.mCurrentUserId);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002073 if (ent == null) {
2074 // Whoops! App doesn't exist. Um. Okay. We'll just pretend like we didn't
2075 // see that.
2076 return false;
2077 }
2078 final boolean windowIsTranslucent = ent.array.getBoolean(
2079 com.android.internal.R.styleable.Window_windowIsTranslucent, false);
2080 final boolean windowIsFloating = ent.array.getBoolean(
2081 com.android.internal.R.styleable.Window_windowIsFloating, false);
2082 final boolean windowShowWallpaper = ent.array.getBoolean(
2083 com.android.internal.R.styleable.Window_windowShowWallpaper, false);
2084 final boolean windowDisableStarting = ent.array.getBoolean(
2085 com.android.internal.R.styleable.Window_windowDisablePreview, false);
2086 if (DEBUG_STARTING_WINDOW) {
2087 Slog.v(TAG, "Translucent=" + windowIsTranslucent
2088 + " Floating=" + windowIsFloating
2089 + " ShowWallpaper=" + windowShowWallpaper);
2090 }
2091 if (windowIsTranslucent) {
2092 return false;
2093 }
2094 if (windowIsFloating || windowDisableStarting) {
2095 return false;
2096 }
2097 if (windowShowWallpaper) {
2098 if (getDisplayContent().mWallpaperController
2099 .getWallpaperTarget() == null) {
2100 // If this theme is requesting a wallpaper, and the wallpaper
2101 // is not currently visible, then this effectively serves as
2102 // an opaque window and our starting window transition animation
2103 // can still work. We just need to make sure the starting window
2104 // is also showing the wallpaper.
2105 windowFlags |= FLAG_SHOW_WALLPAPER;
2106 } else {
2107 return false;
2108 }
2109 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002110 }
Yunfan Chen8a8c0ed2018-12-18 16:46:32 -08002111
2112 if (transferStartingWindow(transferFrom)) {
2113 return true;
2114 }
2115
2116 // There is no existing starting window, and we don't want to create a splash screen, so
2117 // that's it!
2118 if (type != STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
2119 return false;
2120 }
2121
2122 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SplashScreenStartingData");
2123 startingData = new SplashScreenStartingData(mWmService, pkg,
2124 theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
2125 getMergedOverrideConfiguration());
2126 scheduleAddStartingWindow();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002127 return true;
2128 }
2129
2130
2131 private boolean createSnapshot(ActivityManager.TaskSnapshot snapshot) {
2132 if (snapshot == null) {
2133 return false;
2134 }
2135
2136 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SnapshotStartingData");
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002137 startingData = new SnapshotStartingData(mWmService, snapshot);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002138 scheduleAddStartingWindow();
2139 return true;
2140 }
2141
2142 void scheduleAddStartingWindow() {
2143 // Note: we really want to do sendMessageAtFrontOfQueue() because we
2144 // want to process the message ASAP, before any other queued
2145 // messages.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002146 if (!mWmService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002147 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING");
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002148 mWmService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002149 }
2150 }
2151
2152 private final Runnable mAddStartingWindow = new Runnable() {
2153
2154 @Override
2155 public void run() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002156 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002157 // There can only be one adding request, silly caller!
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002158 mWmService.mAnimationHandler.removeCallbacks(this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002159 }
2160
2161 if (startingData == null) {
2162 // Animation has been canceled... do nothing.
2163 if (DEBUG_STARTING_WINDOW) {
2164 Slog.v(TAG, "startingData was nulled out before handling"
2165 + " mAddStartingWindow: " + AppWindowToken.this);
2166 }
2167 return;
2168 }
2169
2170 if (DEBUG_STARTING_WINDOW) {
2171 Slog.v(TAG, "Add starting " + this + ": startingData=" + startingData);
2172 }
2173
2174 WindowManagerPolicy.StartingSurface surface = null;
2175 try {
2176 surface = startingData.createStartingSurface(AppWindowToken.this);
2177 } catch (Exception e) {
2178 Slog.w(TAG, "Exception when adding starting window", e);
2179 }
2180 if (surface != null) {
2181 boolean abort = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002182 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002183 // If the window was successfully added, then
2184 // we need to remove it.
2185 if (removed || startingData == null) {
2186 if (DEBUG_STARTING_WINDOW) {
2187 Slog.v(TAG, "Aborted starting " + AppWindowToken.this
2188 + ": removed=" + removed + " startingData=" + startingData);
2189 }
2190 startingWindow = null;
2191 startingData = null;
2192 abort = true;
2193 } else {
2194 startingSurface = surface;
2195 }
2196 if (DEBUG_STARTING_WINDOW && !abort) {
2197 Slog.v(TAG, "Added starting " + AppWindowToken.this + ": startingWindow="
2198 + startingWindow + " startingView=" + startingSurface);
2199 }
2200 }
2201 if (abort) {
2202 surface.remove();
2203 }
2204 } else if (DEBUG_STARTING_WINDOW) {
2205 Slog.v(TAG, "Surface returned was null: " + AppWindowToken.this);
2206 }
2207 }
2208 };
2209
2210 private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
2211 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents,
2212 ActivityManager.TaskSnapshot snapshot) {
2213 if (getDisplayContent().mAppTransition.getAppTransition()
2214 == TRANSIT_DOCK_TASK_FROM_RECENTS) {
2215 // TODO(b/34099271): Remove this statement to add back the starting window and figure
2216 // out why it causes flickering, the starting window appears over the thumbnail while
2217 // the docked from recents transition occurs
2218 return STARTING_WINDOW_TYPE_NONE;
2219 } else if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
2220 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2221 } else if (taskSwitch && allowTaskSnapshot) {
Kevin716a9db2018-12-18 16:53:39 -08002222 if (mWmService.mLowRamTaskSnapshotsAndRecents) {
Kevin58b47f12018-12-17 14:09:01 -08002223 // For low RAM devices, we use the splash screen starting window instead of the
2224 // task snapshot starting window.
2225 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2226 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002227 return snapshot == null ? STARTING_WINDOW_TYPE_NONE
2228 : snapshotOrientationSameAsTask(snapshot) || fromRecents
2229 ? STARTING_WINDOW_TYPE_SNAPSHOT : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2230 } else {
2231 return STARTING_WINDOW_TYPE_NONE;
2232 }
2233 }
2234
2235
2236 private boolean snapshotOrientationSameAsTask(ActivityManager.TaskSnapshot snapshot) {
2237 if (snapshot == null) {
2238 return false;
2239 }
2240 return getTask().getConfiguration().orientation == snapshot.getOrientation();
2241 }
2242
2243 void removeStartingWindow() {
2244 if (startingWindow == null) {
2245 if (startingData != null) {
2246 // Starting window has not been added yet, but it is scheduled to be added.
2247 // Go ahead and cancel the request.
2248 if (DEBUG_STARTING_WINDOW) {
2249 Slog.v(TAG_WM, "Clearing startingData for token=" + this);
2250 }
2251 startingData = null;
2252 }
2253 return;
2254 }
2255
2256 final WindowManagerPolicy.StartingSurface surface;
2257 if (startingData != null) {
2258 surface = startingSurface;
2259 startingData = null;
2260 startingSurface = null;
2261 startingWindow = null;
2262 startingDisplayed = false;
2263 if (surface == null) {
2264 if (DEBUG_STARTING_WINDOW) {
2265 Slog.v(TAG_WM, "startingWindow was set but startingSurface==null, couldn't "
2266 + "remove");
2267 }
2268 return;
2269 }
2270 } else {
2271 if (DEBUG_STARTING_WINDOW) {
2272 Slog.v(TAG_WM, "Tried to remove starting window but startingWindow was null:"
2273 + this);
2274 }
2275 return;
2276 }
2277
2278 if (DEBUG_STARTING_WINDOW) {
2279 Slog.v(TAG_WM, "Schedule remove starting " + this
2280 + " startingWindow=" + startingWindow
2281 + " startingView=" + startingSurface
2282 + " Callers=" + Debug.getCallers(5));
2283 }
2284
2285 // Use the same thread to remove the window as we used to add it, as otherwise we end up
2286 // with things in the view hierarchy being called from different threads.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002287 mWmService.mAnimationHandler.post(() -> {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002288 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Removing startingView=" + surface);
2289 try {
2290 surface.remove();
2291 } catch (Exception e) {
2292 Slog.w(TAG_WM, "Exception when removing starting window", e);
2293 }
2294 });
2295 }
2296
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002297 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -07002298 boolean fillsParent() {
2299 return mFillsParent;
2300 }
2301
2302 void setFillsParent(boolean fillsParent) {
2303 mFillsParent = fillsParent;
2304 }
2305
Jorim Jaggife762342016-10-13 14:33:27 +02002306 boolean containsDismissKeyguardWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002307 // Window state is transient during relaunch. We are not guaranteed to be frozen during the
2308 // entirety of the relaunch.
2309 if (isRelaunching()) {
2310 return mLastContainsDismissKeyguardWindow;
2311 }
2312
Jorim Jaggife762342016-10-13 14:33:27 +02002313 for (int i = mChildren.size() - 1; i >= 0; i--) {
2314 if ((mChildren.get(i).mAttrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
2315 return true;
2316 }
2317 }
2318 return false;
2319 }
2320
2321 boolean containsShowWhenLockedWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002322 // When we are relaunching, it is possible for us to be unfrozen before our previous
2323 // windows have been added back. Using the cached value ensures that our previous
2324 // showWhenLocked preference is honored until relaunching is complete.
2325 if (isRelaunching()) {
2326 return mLastContainsShowWhenLockedWindow;
2327 }
2328
Jorim Jaggife762342016-10-13 14:33:27 +02002329 for (int i = mChildren.size() - 1; i >= 0; i--) {
2330 if ((mChildren.get(i).mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
2331 return true;
2332 }
2333 }
Bryce Lee081554b2017-05-25 07:52:12 -07002334
Jorim Jaggife762342016-10-13 14:33:27 +02002335 return false;
2336 }
2337
2338 void checkKeyguardFlagsChanged() {
2339 final boolean containsDismissKeyguard = containsDismissKeyguardWindow();
2340 final boolean containsShowWhenLocked = containsShowWhenLockedWindow();
2341 if (containsDismissKeyguard != mLastContainsDismissKeyguardWindow
2342 || containsShowWhenLocked != mLastContainsShowWhenLockedWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002343 mWmService.notifyKeyguardFlagsChanged(null /* callback */,
lumark588a3e82018-07-20 18:53:54 +08002344 getDisplayContent().getDisplayId());
Jorim Jaggife762342016-10-13 14:33:27 +02002345 }
2346 mLastContainsDismissKeyguardWindow = containsDismissKeyguard;
2347 mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
2348 }
2349
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002350 WindowState getImeTargetBelowWindow(WindowState w) {
2351 final int index = mChildren.indexOf(w);
2352 if (index > 0) {
2353 final WindowState target = mChildren.get(index - 1);
2354 if (target.canBeImeTarget()) {
2355 return target;
2356 }
2357 }
2358 return null;
2359 }
2360
2361 WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
2362 WindowState candidate = null;
2363 for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
2364 final WindowState w = mChildren.get(i);
2365 if (w.mRemoved) {
2366 continue;
2367 }
Jorim Jaggi35d328a2018-08-14 17:00:20 +02002368 if (candidate == null) {
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002369 candidate = w;
2370 }
2371 }
2372 return candidate;
2373 }
2374
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002375 /**
2376 * See {@link Activity#setDisablePreviewScreenshots}.
2377 */
2378 void setDisablePreviewScreenshots(boolean disable) {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002379 mDisablePreviewScreenshots = disable;
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002380 }
2381
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002382 /**
chaviwd3bf08d2017-08-01 17:24:59 -07002383 * Sets whether the current launch can turn the screen on. See {@link #canTurnScreenOn()}
2384 */
2385 void setCanTurnScreenOn(boolean canTurnScreenOn) {
2386 mCanTurnScreenOn = canTurnScreenOn;
2387 }
2388
2389 /**
2390 * Indicates whether the current launch can turn the screen on. This is to prevent multiple
2391 * relayouts from turning the screen back on. The screen should only turn on at most
2392 * once per activity resume.
2393 *
2394 * @return true if the screen can be turned on.
2395 */
2396 boolean canTurnScreenOn() {
2397 return mCanTurnScreenOn;
2398 }
2399
2400 /**
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002401 * Retrieves whether we'd like to generate a snapshot that's based solely on the theme. This is
2402 * the case when preview screenshots are disabled {@link #setDisablePreviewScreenshots} or when
2403 * we can't take a snapshot for other reasons, for example, if we have a secure window.
2404 *
2405 * @return True if we need to generate an app theme snapshot, false if we'd like to take a real
2406 * screenshot.
2407 */
2408 boolean shouldUseAppThemeSnapshot() {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002409 return mDisablePreviewScreenshots || forAllWindows(w -> (w.mAttrs.flags & FLAG_SECURE) != 0,
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002410 true /* topToBottom */);
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002411 }
2412
Jorim Jaggibe418292018-03-26 16:14:12 +02002413 SurfaceControl getAppAnimationLayer() {
Jorim Jaggi391790622018-04-18 15:30:44 +02002414 return getAppAnimationLayer(isActivityTypeHome() ? ANIMATION_LAYER_HOME
2415 : needsZBoost() ? ANIMATION_LAYER_BOOSTED
2416 : ANIMATION_LAYER_STANDARD);
Jorim Jaggibe418292018-03-26 16:14:12 +02002417 }
2418
chaviw23ee71c2017-12-18 11:29:41 -08002419 @Override
Jorim Jaggi596a1992017-12-29 14:48:02 +01002420 public SurfaceControl getAnimationLeashParent() {
Robert Carrb9506032018-02-13 13:54:00 -08002421 // All normal app transitions take place in an animation layer which is below the pinned
2422 // stack but may be above the parent stacks of the given animating apps.
2423 // For transitions in the pinned stack (menu activity) we just let them occur as a child
2424 // of the pinned stack.
2425 if (!inPinnedWindowingMode()) {
2426 return getAppAnimationLayer();
2427 } else {
2428 return getStack().getSurfaceControl();
2429 }
chaviw23ee71c2017-12-18 11:29:41 -08002430 }
2431
Jorim Jaggic6976f02018-04-18 16:31:07 +02002432 private boolean shouldAnimate(int transit) {
2433 final boolean isSplitScreenPrimary =
2434 getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
2435 final boolean allowSplitScreenPrimaryAnimation = transit != TRANSIT_WALLPAPER_OPEN;
2436
lumark54284462019-03-05 20:44:27 +08002437 // Don't animate when the task runs recents animation.
2438 final RecentsAnimationController controller = mWmService.getRecentsAnimationController();
2439 if (controller != null && controller.isAnimatingTask(getTask())) {
2440 return false;
2441 }
2442
Jorim Jaggic6976f02018-04-18 16:31:07 +02002443 // We animate always if it's not split screen primary, and only some special cases in split
2444 // screen primary because it causes issues with stack clipping when we run an un-minimize
2445 // animation at the same time.
2446 return !isSplitScreenPrimary || allowSplitScreenPrimaryAnimation;
2447 }
2448
Vishnu Naira2977262018-07-26 13:31:26 -07002449 /**
2450 * Creates a layer to apply crop to an animation.
2451 */
2452 private SurfaceControl createAnimationBoundsLayer(Transaction t) {
2453 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.i(TAG, "Creating animation bounds layer");
2454 final SurfaceControl.Builder builder = makeAnimationLeash()
2455 .setParent(getAnimationLeashParent())
Vishnu Naire86bd982018-11-28 13:23:17 -08002456 .setName(getSurfaceControl() + " - animation-bounds");
Vishnu Naira2977262018-07-26 13:31:26 -07002457 final SurfaceControl boundsLayer = builder.build();
2458 t.show(boundsLayer);
2459 return boundsLayer;
2460 }
2461
Evan Roskyed6767f2018-10-26 17:21:06 -07002462 @Override
2463 Rect getDisplayedBounds() {
2464 final Task task = getTask();
2465 if (task != null) {
2466 final Rect overrideDisplayedBounds = task.getOverrideDisplayedBounds();
2467 if (!overrideDisplayedBounds.isEmpty()) {
2468 return overrideDisplayedBounds;
2469 }
2470 }
2471 return getBounds();
2472 }
2473
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002474 boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter,
2475 boolean isVoiceInteraction) {
2476
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002477 if (mWmService.mDisableTransitionAnimation || !shouldAnimate(transit)) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002478 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
Jorim Jaggic6976f02018-04-18 16:31:07 +02002479 Slog.v(TAG_WM, "applyAnimation: transition animation is disabled or skipped."
2480 + " atoken=" + this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002481 }
2482 cancelAnimation();
2483 return false;
2484 }
2485
2486 // Only apply an animation if the display isn't frozen. If it is frozen, there is no reason
2487 // to animate and it can cause strange artifacts when we unfreeze the display if some
2488 // different animation is running.
2489 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#applyAnimationLocked");
2490 if (okToAnimate()) {
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002491 final AnimationAdapter adapter;
Evan Rosky2289ba12018-11-19 18:28:18 -08002492 AnimationAdapter thumbnailAdapter = null;
Evan Rosky4fb1e912019-03-06 13:54:43 -08002493
2494 // Separate position and size for use in animators. Use task-bounds for now so
2495 // that activity-level letterbox (maxAspectRatio) is included in the animation.
2496 mTmpRect.set(getTask() != null ? getTask().getBounds() : getBounds());
2497 mTmpPoint.set(mTmpRect.left, mTmpRect.top);
2498 mTmpRect.offsetTo(0, 0);
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002499
Evan Roskyec9488c2019-03-01 19:32:12 -08002500 final boolean isChanging = AppTransition.isChangeTransit(transit) && enter
2501 && getDisplayContent().mChangingApps.contains(this);
Evan Rosky2289ba12018-11-19 18:28:18 -08002502
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002503 // Delaying animation start isn't compatible with remote animations at all.
lumark588a3e82018-07-20 18:53:54 +08002504 if (getDisplayContent().mAppTransition.getRemoteAnimationController() != null
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002505 && !mSurfaceAnimator.isAnimationStartDelayed()) {
Evan Rosky2289ba12018-11-19 18:28:18 -08002506 RemoteAnimationRecord adapters =
2507 getDisplayContent().mAppTransition.getRemoteAnimationController()
2508 .createRemoteAnimationRecord(this, mTmpPoint, mTmpRect,
2509 (isChanging ? mTransitStartRect : null));
2510 adapter = adapters.mAdapter;
2511 thumbnailAdapter = adapters.mThumbnailAdapter;
2512 } else if (isChanging) {
Evan Roskycf76bed2019-01-15 10:33:58 -08002513 final float durationScale = mWmService.getTransitionAnimationScaleLocked();
Evan Rosky2289ba12018-11-19 18:28:18 -08002514 mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y);
2515 adapter = new LocalAnimationAdapter(
2516 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
Evan Roskycf76bed2019-01-15 10:33:58 -08002517 getDisplayContent().getDisplayInfo(), durationScale,
Evan Rosky2289ba12018-11-19 18:28:18 -08002518 true /* isAppAnimation */, false /* isThumbnail */),
2519 mWmService.mSurfaceAnimationRunner);
Evan Rosky966759f2019-01-15 10:33:58 -08002520 if (mThumbnail != null) {
2521 thumbnailAdapter = new LocalAnimationAdapter(
2522 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
Evan Roskycf76bed2019-01-15 10:33:58 -08002523 getDisplayContent().getDisplayInfo(), durationScale,
Evan Rosky966759f2019-01-15 10:33:58 -08002524 true /* isAppAnimation */, true /* isThumbnail */),
2525 mWmService.mSurfaceAnimationRunner);
2526 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002527 mTransit = transit;
2528 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002529 } else {
lumark588a3e82018-07-20 18:53:54 +08002530 final int appStackClipMode =
2531 getDisplayContent().mAppTransition.getAppStackClipMode();
Vishnu Naira2977262018-07-26 13:31:26 -07002532 mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM);
2533
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002534 final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
2535 if (a != null) {
2536 adapter = new LocalAnimationAdapter(
2537 new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
lumark588a3e82018-07-20 18:53:54 +08002538 getDisplayContent().mAppTransition.canSkipFirstFrame(),
Vishnu Naira2977262018-07-26 13:31:26 -07002539 appStackClipMode,
Lucas Dupin3e1dc202018-12-02 15:14:20 -08002540 true /* isAppAnimation */,
2541 mWmService.mWindowCornerRadius),
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002542 mWmService.mSurfaceAnimationRunner);
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002543 if (a.getZAdjustment() == Animation.ZORDER_TOP) {
2544 mNeedsZBoost = true;
2545 }
2546 mTransit = transit;
lumark588a3e82018-07-20 18:53:54 +08002547 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002548 } else {
2549 adapter = null;
chaviw23ee71c2017-12-18 11:29:41 -08002550 }
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002551 }
2552 if (adapter != null) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002553 startAnimation(getPendingTransaction(), adapter, !isVisible());
Jorim Jaggi82c17862018-02-21 17:50:18 +01002554 if (adapter.getShowWallpaper()) {
2555 mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2556 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002557 if (thumbnailAdapter != null) {
2558 mThumbnail.startAnimation(
2559 getPendingTransaction(), thumbnailAdapter, !isVisible());
2560 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002561 }
2562 } else {
2563 cancelAnimation();
2564 }
2565 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2566
2567 return isReallyAnimating();
2568 }
2569
2570 private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
2571 boolean isVoiceInteraction) {
2572 final DisplayContent displayContent = getTask().getDisplayContent();
2573 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2574 final int width = displayInfo.appWidth;
2575 final int height = displayInfo.appHeight;
2576 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG_WM,
2577 "applyAnimation: atoken=" + this);
2578
2579 // Determine the visible rect to calculate the thumbnail clip
2580 final WindowState win = findMainWindow();
2581 final Rect frame = new Rect(0, 0, width, height);
2582 final Rect displayFrame = new Rect(0, 0,
2583 displayInfo.logicalWidth, displayInfo.logicalHeight);
2584 final Rect insets = new Rect();
2585 final Rect stableInsets = new Rect();
2586 Rect surfaceInsets = null;
2587 final boolean freeform = win != null && win.inFreeformWindowingMode();
2588 if (win != null) {
2589 // Containing frame will usually cover the whole screen, including dialog windows.
2590 // For freeform workspace windows it will not cover the whole screen and it also
2591 // won't exactly match the final freeform window frame (e.g. when overlapping with
2592 // the status bar). In that case we need to use the final frame.
2593 if (freeform) {
chaviw492139a2018-07-16 16:07:35 -07002594 frame.set(win.getFrameLw());
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002595 } else if (win.isLetterboxedAppWindow()) {
2596 frame.set(getTask().getBounds());
Winson Chungc1674272018-02-21 10:15:17 -08002597 } else if (win.isDockedResizing()) {
2598 // If we are animating while docked resizing, then use the stack bounds as the
2599 // animation target (which will be different than the task bounds)
2600 frame.set(getTask().getParent().getBounds());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002601 } else {
chaviw553b0212018-07-12 13:37:01 -07002602 frame.set(win.getContainingFrame());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002603 }
2604 surfaceInsets = win.getAttrs().surfaceInsets;
Adrian Roos20e07892018-02-23 19:12:01 +01002605 // XXX(b/72757033): These are insets relative to the window frame, but we're really
2606 // interested in the insets relative to the frame we chose in the if-blocks above.
chaviw9c81e632018-07-31 11:17:52 -07002607 win.getContentInsets(insets);
2608 win.getStableInsets(stableInsets);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002609 }
2610
2611 if (mLaunchTaskBehind) {
2612 // Differentiate the two animations. This one which is briefly on the screen
2613 // gets the !enter animation, and the other activity which remains on the
2614 // screen gets the enter animation. Both appear in the mOpeningApps set.
2615 enter = false;
2616 }
2617 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "Loading animation for app transition."
2618 + " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter
2619 + " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets);
2620 final Configuration displayConfig = displayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08002621 final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002622 displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
2623 surfaceInsets, stableInsets, isVoiceInteraction, freeform, getTask().mTaskId);
2624 if (a != null) {
2625 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
2626 final int containingWidth = frame.width();
2627 final int containingHeight = frame.height();
2628 a.initialize(containingWidth, containingHeight, width, height);
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002629 a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002630 }
2631 return a;
2632 }
2633
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002634 @Override
Jorim Jaggi6de61012018-03-19 14:53:23 +01002635 public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
2636 return mAnimatingAppWindowTokenRegistry != null
2637 && mAnimatingAppWindowTokenRegistry.notifyAboutToFinish(
2638 this, endDeferFinishCallback);
2639 }
2640
2641 @Override
2642 public void onAnimationLeashDestroyed(Transaction t) {
2643 super.onAnimationLeashDestroyed(t);
Vishnu Naira2977262018-07-26 13:31:26 -07002644 if (mAnimationBoundsLayer != null) {
Robert Carr71200f22019-02-05 09:44:53 -08002645 t.remove(mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002646 mAnimationBoundsLayer = null;
2647 }
2648
Jorim Jaggi6de61012018-03-19 14:53:23 +01002649 if (mAnimatingAppWindowTokenRegistry != null) {
2650 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
2651 }
2652 }
2653
2654 @Override
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002655 protected void setLayer(Transaction t, int layer) {
2656 if (!mSurfaceAnimator.hasLeash()) {
2657 t.setLayer(mSurfaceControl, layer);
2658 }
2659 }
2660
2661 @Override
2662 protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
2663 if (!mSurfaceAnimator.hasLeash()) {
2664 t.setRelativeLayer(mSurfaceControl, relativeTo, layer);
2665 }
2666 }
2667
2668 @Override
2669 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
2670 if (!mSurfaceAnimator.hasLeash()) {
Robert Carr10584fa2019-01-14 15:55:19 -08002671 t.reparent(mSurfaceControl, newParent);
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002672 }
2673 }
2674
2675 @Override
2676 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002677 // The leash is parented to the animation layer. We need to preserve the z-order by using
2678 // the prefix order index, but we boost if necessary.
Robert Carrb9506032018-02-13 13:54:00 -08002679 int layer = 0;
2680 if (!inPinnedWindowingMode()) {
2681 layer = getPrefixOrderIndex();
2682 } else {
2683 // Pinned stacks have animations take place within themselves rather than an animation
2684 // layer so we need to preserve the order relative to the stack (e.g. the order of our
2685 // task/parent).
2686 layer = getParent().getPrefixOrderIndex();
2687 }
2688
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002689 if (mNeedsZBoost) {
2690 layer += Z_BOOST_BASE;
2691 }
2692 leash.setLayer(layer);
Robert Carr2f8aa392018-01-31 14:46:51 -08002693
2694 final DisplayContent dc = getDisplayContent();
Jorim Jaggibe418292018-03-26 16:14:12 +02002695 dc.assignStackOrdering();
Evan Rosky2289ba12018-11-19 18:28:18 -08002696
2697 if (leash == mTransitChangeLeash) {
2698 // This is a temporary state so skip any animation notifications
2699 return;
2700 } else if (mTransitChangeLeash != null) {
2701 // unparent mTransitChangeLeash for clean-up
Evan Rosky25b56192019-02-06 16:10:56 -08002702 clearChangeLeash(t, false /* cancel */);
Evan Rosky2289ba12018-11-19 18:28:18 -08002703 }
2704
Jorim Jaggi6de61012018-03-19 14:53:23 +01002705 if (mAnimatingAppWindowTokenRegistry != null) {
2706 mAnimatingAppWindowTokenRegistry.notifyStarting(this);
2707 }
Vishnu Naira2977262018-07-26 13:31:26 -07002708
2709 // If the animation needs to be cropped then an animation bounds layer is created as a child
2710 // of the pinned stack or animation layer. The leash is then reparented to this new layer.
2711 if (mNeedsAnimationBoundsLayer) {
Evan Rosky7735d352019-03-18 17:27:27 -07002712 mTmpRect.setEmpty();
2713 final Task task = getTask();
2714 if (getDisplayContent().mAppTransitionController.isTransitWithinTask(
2715 getTransit(), task)) {
2716 task.getBounds(mTmpRect);
2717 } else {
2718 final TaskStack stack = getStack();
2719 if (stack == null) {
2720 return;
2721 }
2722 // Set clip rect to stack bounds.
2723 stack.getBounds(mTmpRect);
Vishnu Naira2977262018-07-26 13:31:26 -07002724 }
2725 mAnimationBoundsLayer = createAnimationBoundsLayer(t);
2726
Vishnu Naira2977262018-07-26 13:31:26 -07002727 // Crop to stack bounds.
2728 t.setWindowCrop(mAnimationBoundsLayer, mTmpRect);
2729
2730 // Reparent leash to animation bounds layer.
Robert Carr10584fa2019-01-14 15:55:19 -08002731 t.reparent(leash, mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002732 }
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002733 }
2734
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002735 /**
2736 * This must be called while inside a transaction.
2737 */
2738 void showAllWindowsLocked() {
2739 forAllWindows(windowState -> {
2740 if (DEBUG_VISIBILITY) Slog.v(TAG, "performing show on: " + windowState);
2741 windowState.performShowLocked();
2742 }, false /* traverseTopToBottom */);
Jorim Jaggia5e10572017-11-15 14:36:26 +01002743 }
2744
2745 @Override
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002746 protected void onAnimationFinished() {
2747 super.onAnimationFinished();
2748
2749 mTransit = TRANSIT_UNSET;
2750 mTransitFlags = 0;
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002751 mNeedsZBoost = false;
Vishnu Naira2977262018-07-26 13:31:26 -07002752 mNeedsAnimationBoundsLayer = false;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002753
2754 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER,
2755 "AppWindowToken");
2756
Jorim Jaggi988f6682017-11-17 17:46:43 +01002757 clearThumbnail();
Jorim Jaggi752cd822018-03-29 16:29:18 +02002758 setClientHidden(isHidden() && hiddenRequested);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002759
lumarkff0ab692018-11-05 20:32:30 +08002760 getDisplayContent().computeImeTargetIfNeeded(this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002761
2762 if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + this
2763 + ": reportedVisible=" + reportedVisible
2764 + " okToDisplay=" + okToDisplay()
2765 + " okToAnimate=" + okToAnimate()
2766 + " startingDisplayed=" + startingDisplayed);
2767
Evan Rosky2289ba12018-11-19 18:28:18 -08002768 // clean up thumbnail window
2769 if (mThumbnail != null) {
2770 mThumbnail.destroy();
2771 mThumbnail = null;
2772 }
2773
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002774 // WindowState.onExitAnimationDone might modify the children list, so make a copy and then
2775 // traverse the copy.
2776 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
2777 children.forEach(WindowState::onExitAnimationDone);
2778
lumark588a3e82018-07-20 18:53:54 +08002779 getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002780 scheduleAnimation();
Jorim Jaggi9b5e3312019-03-01 18:08:00 +01002781
2782 mActivityRecord.onAnimationFinished();
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002783 }
2784
2785 @Override
2786 boolean isAppAnimating() {
2787 return isSelfAnimating();
2788 }
2789
2790 @Override
2791 boolean isSelfAnimating() {
2792 // If we are about to start a transition, we also need to be considered animating.
2793 return isWaitingForTransitionStart() || isReallyAnimating();
2794 }
2795
2796 /**
2797 * @return True if and only if we are actually running an animation. Note that
2798 * {@link #isSelfAnimating} also returns true if we are waiting for an animation to
2799 * start.
2800 */
2801 private boolean isReallyAnimating() {
2802 return super.isSelfAnimating();
2803 }
2804
Evan Rosky25b56192019-02-06 16:10:56 -08002805 /**
2806 * @param cancel {@code true} if clearing the leash due to cancelling instead of transferring
2807 * to another leash.
2808 */
2809 private void clearChangeLeash(Transaction t, boolean cancel) {
2810 if (mTransitChangeLeash == null) {
2811 return;
2812 }
2813 if (cancel) {
2814 clearThumbnail();
2815 SurfaceControl sc = getSurfaceControl();
2816 SurfaceControl parentSc = getParentSurfaceControl();
2817 // Don't reparent if surface is getting destroyed
2818 if (parentSc != null && sc != null) {
2819 t.reparent(sc, getParentSurfaceControl());
2820 }
2821 }
2822 t.hide(mTransitChangeLeash);
2823 t.reparent(mTransitChangeLeash, null);
2824 mTransitChangeLeash = null;
2825 if (cancel) {
2826 onAnimationLeashDestroyed(t);
2827 }
2828 }
2829
Jorim Jaggi988f6682017-11-17 17:46:43 +01002830 @Override
2831 void cancelAnimation() {
Evan Rosky2289ba12018-11-19 18:28:18 -08002832 cancelAnimationOnly();
Jorim Jaggi988f6682017-11-17 17:46:43 +01002833 clearThumbnail();
Evan Rosky25b56192019-02-06 16:10:56 -08002834 clearChangeLeash(getPendingTransaction(), true /* cancel */);
Evan Rosky2289ba12018-11-19 18:28:18 -08002835 }
2836
2837 /**
2838 * This only cancels the animation. It doesn't do other teardown like cleaning-up thumbnail
2839 * or interim leashes.
2840 * <p>
2841 * Used when canceling in preparation for starting a new animation.
2842 */
2843 void cancelAnimationOnly() {
2844 super.cancelAnimation();
Jorim Jaggi988f6682017-11-17 17:46:43 +01002845 }
2846
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002847 boolean isWaitingForTransitionStart() {
lumark588a3e82018-07-20 18:53:54 +08002848 return getDisplayContent().mAppTransition.isTransitionSet()
2849 && (getDisplayContent().mOpeningApps.contains(this)
Evan Rosky2289ba12018-11-19 18:28:18 -08002850 || getDisplayContent().mClosingApps.contains(this)
2851 || getDisplayContent().mChangingApps.contains(this));
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002852 }
2853
2854 public int getTransit() {
2855 return mTransit;
2856 }
2857
2858 int getTransitFlags() {
2859 return mTransitFlags;
2860 }
2861
Jorim Jaggi988f6682017-11-17 17:46:43 +01002862 void attachThumbnailAnimation() {
2863 if (!isReallyAnimating()) {
2864 return;
2865 }
2866 final int taskId = getTask().mTaskId;
2867 final GraphicBuffer thumbnailHeader =
lumark588a3e82018-07-20 18:53:54 +08002868 getDisplayContent().mAppTransition.getAppTransitionThumbnailHeader(taskId);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002869 if (thumbnailHeader == null) {
2870 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG, "No thumbnail header bitmap for: " + taskId);
2871 return;
2872 }
2873 clearThumbnail();
2874 mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnailHeader);
2875 mThumbnail.startAnimation(getPendingTransaction(), loadThumbnailAnimation(thumbnailHeader));
2876 }
2877
Tony Mak64b8d562017-12-28 17:44:02 +00002878 /**
2879 * Attaches a surface with a thumbnail for the
2880 * {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation.
2881 */
2882 void attachCrossProfileAppsThumbnailAnimation() {
2883 if (!isReallyAnimating()) {
2884 return;
2885 }
2886 clearThumbnail();
2887
2888 final WindowState win = findMainWindow();
2889 if (win == null) {
2890 return;
2891 }
chaviw492139a2018-07-16 16:07:35 -07002892 final Rect frame = win.getFrameLw();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002893 final int thumbnailDrawableRes = getTask().mUserId == mWmService.mCurrentUserId
Tony Mak64b8d562017-12-28 17:44:02 +00002894 ? R.drawable.ic_account_circle
Tony Makda4af232018-04-27 11:01:10 +01002895 : R.drawable.ic_corp_badge;
Tony Mak64b8d562017-12-28 17:44:02 +00002896 final GraphicBuffer thumbnail =
lumark588a3e82018-07-20 18:53:54 +08002897 getDisplayContent().mAppTransition
Tony Mak64b8d562017-12-28 17:44:02 +00002898 .createCrossProfileAppsThumbnail(thumbnailDrawableRes, frame);
2899 if (thumbnail == null) {
2900 return;
2901 }
2902 mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnail);
2903 final Animation animation =
lumark588a3e82018-07-20 18:53:54 +08002904 getDisplayContent().mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(
chaviw492139a2018-07-16 16:07:35 -07002905 win.getFrameLw());
Tony Mak64b8d562017-12-28 17:44:02 +00002906 mThumbnail.startAnimation(getPendingTransaction(), animation, new Point(frame.left,
2907 frame.top));
2908 }
2909
Jorim Jaggi988f6682017-11-17 17:46:43 +01002910 private Animation loadThumbnailAnimation(GraphicBuffer thumbnailHeader) {
2911 final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
2912
2913 // If this is a multi-window scenario, we use the windows frame as
2914 // destination of the thumbnail header animation. If this is a full screen
2915 // window scenario, we use the whole display as the target.
2916 WindowState win = findMainWindow();
2917 Rect appRect = win != null ? win.getContentFrameLw() :
2918 new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
chaviw9c81e632018-07-31 11:17:52 -07002919 final Rect insets = win != null ? win.getContentInsets() : null;
Jorim Jaggi988f6682017-11-17 17:46:43 +01002920 final Configuration displayConfig = mDisplayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08002921 return getDisplayContent().mAppTransition.createThumbnailAspectScaleAnimationLocked(
Jorim Jaggi988f6682017-11-17 17:46:43 +01002922 appRect, insets, thumbnailHeader, getTask().mTaskId, displayConfig.uiMode,
2923 displayConfig.orientation);
2924 }
2925
2926 private void clearThumbnail() {
2927 if (mThumbnail == null) {
2928 return;
2929 }
2930 mThumbnail.destroy();
2931 mThumbnail = null;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002932 }
2933
Jorim Jaggif84e2f62018-01-16 14:17:59 +01002934 void registerRemoteAnimations(RemoteAnimationDefinition definition) {
2935 mRemoteAnimationDefinition = definition;
2936 }
2937
2938 RemoteAnimationDefinition getRemoteAnimationDefinition() {
2939 return mRemoteAnimationDefinition;
2940 }
2941
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002942 @Override
2943 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
2944 super.dump(pw, prefix, dumpAll);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002945 if (appToken != null) {
Wale Ogunwale72919d22016-12-08 18:58:50 -08002946 pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002947 }
Winson Chung48b25652018-10-22 14:04:30 -07002948 pw.println(prefix + "component=" + mActivityComponent.flattenToShortString());
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08002949 pw.print(prefix); pw.print("task="); pw.println(getTask());
Wale Ogunwale51362492016-09-08 17:49:17 -07002950 pw.print(prefix); pw.print(" mFillsParent="); pw.print(mFillsParent);
2951 pw.print(" mOrientation="); pw.println(mOrientation);
Wale Ogunwale89973222017-04-23 18:39:45 -07002952 pw.println(prefix + "hiddenRequested=" + hiddenRequested + " mClientHidden=" + mClientHidden
2953 + ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "")
2954 + " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible);
Craig Mautner59431632012-04-04 11:56:44 -07002955 if (paused) {
2956 pw.print(prefix); pw.print("paused="); pw.println(paused);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002957 }
Wale Ogunwale9017ec02016-02-25 08:55:25 -08002958 if (mAppStopped) {
2959 pw.print(prefix); pw.print("mAppStopped="); pw.println(mAppStopped);
2960 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002961 if (mNumInterestingWindows != 0 || mNumDrawnWindows != 0
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002962 || allDrawn || mLastAllDrawn) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002963 pw.print(prefix); pw.print("mNumInterestingWindows=");
2964 pw.print(mNumInterestingWindows);
2965 pw.print(" mNumDrawnWindows="); pw.print(mNumDrawnWindows);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002966 pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
Craig Mautner6fbda632012-07-03 09:26:39 -07002967 pw.print(" allDrawn="); pw.print(allDrawn);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002968 pw.print(" lastAllDrawn="); pw.print(mLastAllDrawn);
Craig Mautner6fbda632012-07-03 09:26:39 -07002969 pw.println(")");
2970 }
2971 if (inPendingTransaction) {
2972 pw.print(prefix); pw.print("inPendingTransaction=");
2973 pw.println(inPendingTransaction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002974 }
Craig Mautner799bc1d2015-01-14 10:33:48 -08002975 if (startingData != null || removed || firstWindowDrawn || mIsExiting) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002976 pw.print(prefix); pw.print("startingData="); pw.print(startingData);
2977 pw.print(" removed="); pw.print(removed);
Craig Mautner3d7ca312015-01-08 10:56:00 -08002978 pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
Craig Mautner799bc1d2015-01-14 10:33:48 -08002979 pw.print(" mIsExiting="); pw.println(mIsExiting);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002980 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08002981 if (startingWindow != null || startingSurface != null
Wale Ogunwale6c459212017-05-17 08:56:03 -07002982 || startingDisplayed || startingMoved || mHiddenSetFromTransferredStartingWindow) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002983 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08002984 pw.print(" startingSurface="); pw.print(startingSurface);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002985 pw.print(" startingDisplayed="); pw.print(startingDisplayed);
Wale Ogunwale6c459212017-05-17 08:56:03 -07002986 pw.print(" startingMoved="); pw.print(startingMoved);
2987 pw.println(" mHiddenSetFromTransferredStartingWindow="
2988 + mHiddenSetFromTransferredStartingWindow);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002989 }
Jorim Jaggi0429f352015-12-22 16:29:16 +01002990 if (!mFrozenBounds.isEmpty()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08002991 pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
Jorim Jaggi26c8c422016-05-09 19:57:25 -07002992 pw.print(prefix); pw.print("mFrozenMergedConfig="); pw.println(mFrozenMergedConfig);
Chong Zhangd78ddb42016-03-02 17:01:14 -08002993 }
2994 if (mPendingRelaunchCount != 0) {
2995 pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount);
Jorim Jaggi0429f352015-12-22 16:29:16 +01002996 }
Riddle Hsub398da32019-01-21 21:48:16 +08002997 if (mSizeCompatScale != 1f || mSizeCompatBounds != null) {
2998 pw.println(prefix + "mSizeCompatScale=" + mSizeCompatScale + " mSizeCompatBounds="
2999 + mSizeCompatBounds);
3000 }
Wale Ogunwalee287e192017-04-21 09:30:12 -07003001 if (mRemovingFromDisplay) {
3002 pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay);
3003 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003004 }
3005
3006 @Override
3007 void setHidden(boolean hidden) {
3008 super.setHidden(hidden);
Winson Chunge55c0192017-08-24 14:50:48 -07003009
3010 if (hidden) {
3011 // Once the app window is hidden, reset the last saved PiP snap fraction
3012 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(this);
3013 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003014 scheduleAnimation();
3015 }
3016
3017 @Override
3018 void prepareSurfaces() {
3019 // isSelfAnimating also returns true when we are about to start a transition, so we need
3020 // to check super here.
3021 final boolean reallyAnimating = super.isSelfAnimating();
3022 final boolean show = !isHidden() || reallyAnimating;
Robert Carrd8e4fb72019-01-31 11:14:30 -08003023
3024 if (mSurfaceControl != null) {
3025 if (show && !mLastSurfaceShowing) {
3026 mPendingTransaction.show(mSurfaceControl);
3027 } else if (!show && mLastSurfaceShowing) {
3028 mPendingTransaction.hide(mSurfaceControl);
3029 }
Jorim Jaggi4d1835d2017-08-31 17:28:27 +02003030 }
Jorim Jaggi988f6682017-11-17 17:46:43 +01003031 if (mThumbnail != null) {
3032 mThumbnail.setShowing(mPendingTransaction, show);
3033 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003034 mLastSurfaceShowing = show;
3035 super.prepareSurfaces();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003036 }
3037
Jorim Jaggi77d0f36c2018-03-16 17:49:49 +01003038 /**
3039 * @return Whether our {@link #getSurfaceControl} is currently showing.
3040 */
3041 boolean isSurfaceShowing() {
3042 return mLastSurfaceShowing;
3043 }
3044
Jorim Jaggib0fc8172017-11-23 17:04:08 +00003045 boolean isFreezingScreen() {
3046 return mFreezingScreen;
3047 }
3048
3049 @Override
3050 boolean needsZBoost() {
3051 return mNeedsZBoost || super.needsZBoost();
3052 }
3053
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07003054 @CallSuper
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003055 @Override
Nataniel Borges023ecb52019-01-16 14:15:43 -08003056 public void writeToProto(ProtoOutputStream proto, long fieldId,
3057 @WindowTraceLogLevel int logLevel) {
3058 // Critical log level logs only visible elements to mitigate performance overheard
3059 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
3060 return;
3061 }
3062
Steven Timotiusaf03df62017-07-18 16:56:43 -07003063 final long token = proto.start(fieldId);
3064 writeNameToProto(proto, NAME);
Nataniel Borges023ecb52019-01-16 14:15:43 -08003065 super.writeToProto(proto, WINDOW_TOKEN, logLevel);
Vishnu Nair04ab4392018-01-10 11:00:06 -08003066 proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing);
3067 proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart());
3068 proto.write(IS_REALLY_ANIMATING, isReallyAnimating());
3069 if (mThumbnail != null){
3070 mThumbnail.writeToProto(proto, THUMBNAIL);
3071 }
3072 proto.write(FILLS_PARENT, mFillsParent);
3073 proto.write(APP_STOPPED, mAppStopped);
3074 proto.write(HIDDEN_REQUESTED, hiddenRequested);
3075 proto.write(CLIENT_HIDDEN, mClientHidden);
3076 proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient);
3077 proto.write(REPORTED_DRAWN, reportedDrawn);
3078 proto.write(REPORTED_VISIBLE, reportedVisible);
3079 proto.write(NUM_INTERESTING_WINDOWS, mNumInterestingWindows);
3080 proto.write(NUM_DRAWN_WINDOWS, mNumDrawnWindows);
3081 proto.write(ALL_DRAWN, allDrawn);
3082 proto.write(LAST_ALL_DRAWN, mLastAllDrawn);
3083 proto.write(REMOVED, removed);
Nataniel Borges023ecb52019-01-16 14:15:43 -08003084 if (startingWindow != null) {
Vishnu Nair04ab4392018-01-10 11:00:06 -08003085 startingWindow.writeIdentifierToProto(proto, STARTING_WINDOW);
3086 }
3087 proto.write(STARTING_DISPLAYED, startingDisplayed);
3088 proto.write(STARTING_MOVED, startingMoved);
3089 proto.write(HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW,
3090 mHiddenSetFromTransferredStartingWindow);
3091 for (Rect bounds : mFrozenBounds) {
3092 bounds.writeToProto(proto, FROZEN_BOUNDS);
3093 }
Steven Timotiusaf03df62017-07-18 16:56:43 -07003094 proto.end(token);
3095 }
3096
3097 void writeNameToProto(ProtoOutputStream proto, long fieldId) {
3098 if (appToken == null) {
3099 return;
3100 }
3101 try {
3102 proto.write(fieldId, appToken.getName());
3103 } catch (RemoteException e) {
3104 // This shouldn't happen, but in this case fall back to outputting nothing
3105 Slog.e(TAG, e.toString());
3106 }
3107 }
3108
3109 @Override
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003110 public String toString() {
3111 if (stringName == null) {
3112 StringBuilder sb = new StringBuilder();
3113 sb.append("AppWindowToken{");
3114 sb.append(Integer.toHexString(System.identityHashCode(this)));
3115 sb.append(" token="); sb.append(token); sb.append('}');
3116 stringName = sb.toString();
3117 }
Wale Ogunwaleba51ca22016-09-23 06:06:54 -07003118 return stringName + ((mIsExiting) ? " mIsExiting=" : "");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003119 }
Adrian Roos20e07892018-02-23 19:12:01 +01003120
3121 Rect getLetterboxInsets() {
3122 if (mLetterbox != null) {
3123 return mLetterbox.getInsets();
3124 } else {
3125 return new Rect();
3126 }
3127 }
Adrian Roos23df3a32018-03-15 15:41:13 +01003128
Riddle Hsu69de5fb2019-02-23 01:19:50 +08003129 /** Gets the inner bounds of letterbox. The bounds will be empty if there is no letterbox. */
3130 void getLetterboxInnerBounds(Rect outBounds) {
3131 if (mLetterbox != null) {
3132 outBounds.set(mLetterbox.getInnerFrame());
3133 } else {
3134 outBounds.setEmpty();
3135 }
3136 }
3137
Adrian Roos23df3a32018-03-15 15:41:13 +01003138 /**
Riddle Hsu69de5fb2019-02-23 01:19:50 +08003139 * @return {@code true} if there is a letterbox and any part of that letterbox overlaps with
Adrian Roos23df3a32018-03-15 15:41:13 +01003140 * the given {@code rect}.
3141 */
3142 boolean isLetterboxOverlappingWith(Rect rect) {
3143 return mLetterbox != null && mLetterbox.isOverlappingWith(rect);
3144 }
chaviw4ad54912018-05-30 11:05:44 -07003145
3146 /**
3147 * Sets if this AWT is in the process of closing or entering PIP.
3148 * {@link #mWillCloseOrEnterPip}}
3149 */
3150 void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
3151 mWillCloseOrEnterPip = willCloseOrEnterPip;
3152 }
3153
3154 /**
3155 * Returns whether this AWT is considered closing. Conditions are either
3156 * 1. Is this app animating and was requested to be hidden
3157 * 2. App is delayed closing since it might enter PIP.
3158 */
3159 boolean isClosingOrEnteringPip() {
3160 return (isAnimating() && hiddenRequested) || mWillCloseOrEnterPip;
3161 }
Jorim Jaggiaf0d6d22018-06-08 15:25:35 +02003162
3163 /**
3164 * @return Whether we are allowed to show non-starting windows at the moment. We disallow
3165 * showing windows during transitions in case we have windows that have wide-color-gamut
3166 * color mode set to avoid jank in the middle of the transition.
3167 */
3168 boolean canShowWindows() {
3169 return allDrawn && !(isReallyAnimating() && hasNonDefaultColorWindow());
3170 }
3171
3172 /**
3173 * @return true if we have a window that has a non-default color mode set; false otherwise.
3174 */
3175 private boolean hasNonDefaultColorWindow() {
3176 return forAllWindows(ws -> ws.mAttrs.getColorMode() != COLOR_MODE_DEFAULT,
3177 true /* topToBottom */);
3178 }
lumark588a3e82018-07-20 18:53:54 +08003179
3180 void removeFromPendingTransition() {
3181 if (isWaitingForTransitionStart() && mDisplayContent != null) {
3182 mDisplayContent.mOpeningApps.remove(this);
Evan Rosky25b56192019-02-06 16:10:56 -08003183 if (mDisplayContent.mChangingApps.remove(this)) {
3184 clearChangeLeash(getPendingTransaction(), true /* cancel */);
3185 }
lumark588a3e82018-07-20 18:53:54 +08003186 mDisplayContent.mClosingApps.remove(this);
3187 }
3188 }
chaviwdcf76ec2019-01-11 16:48:46 -08003189
3190 private void updateColorTransform() {
3191 if (mSurfaceControl != null && mLastAppSaturationInfo != null) {
3192 mPendingTransaction.setColorTransform(mSurfaceControl, mLastAppSaturationInfo.mMatrix,
3193 mLastAppSaturationInfo.mTranslation);
3194 mWmService.scheduleAnimationLocked();
3195 }
3196 }
3197
3198 private static class AppSaturationInfo {
3199 float[] mMatrix = new float[9];
3200 float[] mTranslation = new float[3];
3201
3202 void setSaturation(@Size(9) float[] matrix, @Size(3) float[] translation) {
3203 System.arraycopy(matrix, 0, mMatrix, 0, mMatrix.length);
3204 System.arraycopy(translation, 0, mTranslation, 0, mTranslation.length);
3205 }
3206 }
Jeff Browne9bdb312012-04-05 15:30:10 -07003207}