blob: a3cef7f7219d5c84feb3e031aa871e3815116a6f [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;
Evan Rosky641daea2019-04-24 14:45:24 -070082import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080083
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070084import android.annotation.CallSuper;
chaviwdcf76ec2019-01-11 16:48:46 -080085import android.annotation.Size;
Jorim Jaggid635a4a2017-05-03 15:21:26 +020086import android.app.Activity;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080087import android.app.ActivityManager;
Winson Chung48b25652018-10-22 14:04:30 -070088import android.content.ComponentName;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080089import android.content.res.CompatibilityInfo;
Jorim Jaggi26c8c422016-05-09 19:57:25 -070090import android.content.res.Configuration;
Jorim Jaggi988f6682017-11-17 17:46:43 +010091import android.graphics.GraphicBuffer;
Jorim Jaggif5f9e122017-10-24 18:21:09 +020092import android.graphics.Point;
Jorim Jaggi0429f352015-12-22 16:29:16 +010093import android.graphics.Rect;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -070094import android.os.Binder;
Tiger Huang51c5a1d2018-12-11 20:24:51 +080095import android.os.Build;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -080096import android.os.Debug;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -070097import android.os.IBinder;
Steven Timotiusaf03df62017-07-18 16:56:43 -070098import android.os.RemoteException;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080099import android.os.SystemClock;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200100import android.os.Trace;
Evan Rosky2289ba12018-11-19 18:28:18 -0800101import android.util.ArraySet;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800102import android.util.Slog;
Steven Timotiusaf03df62017-07-18 16:56:43 -0700103import android.util.proto.ProtoOutputStream;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200104import android.view.DisplayInfo;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800105import android.view.IApplicationToken;
Robert Carr788f5742018-07-30 17:46:45 -0700106import android.view.InputApplicationHandle;
Evan Rosky966759f2019-01-15 10:33:58 -0800107import android.view.RemoteAnimationAdapter;
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100108import android.view.RemoteAnimationDefinition;
Robert Carr6914f082017-03-20 19:04:30 -0700109import android.view.SurfaceControl;
Tony Mak64b8d562017-12-28 17:44:02 +0000110import android.view.SurfaceControl.Transaction;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800111import android.view.WindowManager;
Jorim Jaggi87fdbcb2017-08-17 13:41:11 +0200112import android.view.WindowManager.LayoutParams;
Tony Mak64b8d562017-12-28 17:44:02 +0000113import android.view.animation.Animation;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800114
Tony Mak64b8d562017-12-28 17:44:02 +0000115import com.android.internal.R;
Riddle Hsua118b3a2018-10-11 22:05:06 +0800116import com.android.internal.annotations.VisibleForTesting;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800117import com.android.internal.util.ToBooleanFunction;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800118import com.android.server.AttributeCache;
chaviwdcf76ec2019-01-11 16:48:46 -0800119import com.android.server.LocalServices;
Christine Franks0ada2772019-02-25 13:54:57 -0800120import com.android.server.display.color.ColorDisplayService;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800121import com.android.server.policy.WindowManagerPolicy;
Adrian Roose99bc052017-11-20 17:55:31 +0100122import com.android.server.policy.WindowManagerPolicy.StartingSurface;
Evan Rosky2289ba12018-11-19 18:28:18 -0800123import com.android.server.wm.RemoteAnimationController.RemoteAnimationRecord;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800124import com.android.server.wm.WindowManagerService.H;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800125
126import java.io.PrintWriter;
chaviwdcf76ec2019-01-11 16:48:46 -0800127import java.lang.ref.WeakReference;
Jorim Jaggi0429f352015-12-22 16:29:16 +0100128import java.util.ArrayDeque;
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800129import java.util.ArrayList;
lumark588a3e82018-07-20 18:53:54 +0800130import java.util.function.Consumer;
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800131
132class AppTokenList extends ArrayList<AppWindowToken> {
133}
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800134
135/**
136 * Version of WindowToken that is specifically for a particular application (or
137 * really activity) that is displaying windows.
138 */
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800139class AppWindowToken extends WindowToken implements WindowManagerService.AppFreezeListener,
140 ConfigurationContainerListener {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800141 private static final String TAG = TAG_WITH_CLASS_NAME ? "AppWindowToken" : TAG_WM;
142
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100143 /**
144 * Value to increment the z-layer when boosting a layer during animations. BOOST in l33tsp34k.
145 */
Jorim Jaggi9cd99132019-04-24 17:41:35 +0200146 @VisibleForTesting static final int Z_BOOST_BASE = 800570000;
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100147
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800148 // Non-null only for application tokens.
149 final IApplicationToken appToken;
Winson Chung48b25652018-10-22 14:04:30 -0700150 final ComponentName mActivityComponent;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800151 final boolean mVoiceInteraction;
Dianne Hackborne30e02f2014-05-27 18:24:45 -0700152
Wale Ogunwale51362492016-09-08 17:49:17 -0700153 /** @see WindowContainer#fillsParent() */
154 private boolean mFillsParent;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800155 boolean mShowForAllUsers;
156 int mTargetSdk;
Craig Mautnera2c77052012-03-26 12:14:43 -0700157
Bryce Lee6d410262017-02-28 15:30:17 -0800158 // Flag set while reparenting to prevent actions normally triggered by an individual parent
159 // change.
160 private boolean mReparenting;
161
Wale Ogunwalee287e192017-04-21 09:30:12 -0700162 // True if we are current in the process of removing this app token from the display
163 private boolean mRemovingFromDisplay = false;
164
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800165 // The input dispatching timeout for this application token in nanoseconds.
Wale Ogunwale72919d22016-12-08 18:58:50 -0800166 long mInputDispatchingTimeoutNanos;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800167
168 // These are used for determining when all windows associated with
169 // an activity have been drawn, so they can be made visible together
170 // at the same time.
Craig Mautner764983d2012-03-22 11:37:36 -0700171 // initialize so that it doesn't match mTransactionSequence which is an int.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700172 private long mLastTransactionSequence = Long.MIN_VALUE;
173 private int mNumInterestingWindows;
174 private int mNumDrawnWindows;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800175 boolean inPendingTransaction;
176 boolean allDrawn;
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000177 private boolean mLastAllDrawn;
178
Craig Mautner7636dfb2012-11-16 15:24:11 -0800179 // Set to true when this app creates a surface while in the middle of an animation. In that
180 // case do not clear allDrawn until the animation completes.
181 boolean deferClearAllDrawn;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800182
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800183 // Is this window's surface needed? This is almost like hidden, except
184 // it will sometimes be true a little earlier: when the token has
185 // been shown, but is still waiting for its app transition to execute
186 // before making its windows shown.
187 boolean hiddenRequested;
188
189 // Have we told the window clients to hide themselves?
Wale Ogunwale89973222017-04-23 18:39:45 -0700190 private boolean mClientHidden;
191
192 // If true we will defer setting mClientHidden to true and reporting to the client that it is
193 // hidden.
194 boolean mDeferHidingClient;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800195
196 // Last visibility state we reported to the app token.
197 boolean reportedVisible;
198
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700199 // Last drawn state we reported to the app token.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700200 private boolean reportedDrawn;
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700201
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800202 // Set to true when the token has been removed from the window mgr.
203 boolean removed;
204
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800205 // Information about an application starting window if displayed.
206 StartingData startingData;
207 WindowState startingWindow;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800208 StartingSurface startingSurface;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800209 boolean startingDisplayed;
210 boolean startingMoved;
Jorim Jaggi60f9c972018-02-01 19:21:07 +0100211
Wale Ogunwale6c459212017-05-17 08:56:03 -0700212 // True if the hidden state of this token was forced to false due to a transferred starting
213 // window.
214 private boolean mHiddenSetFromTransferredStartingWindow;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800215 boolean firstWindowDrawn;
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700216 private final WindowState.UpdateReportedVisibilityResults mReportedVisibilityResults =
217 new WindowState.UpdateReportedVisibilityResults();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800218
219 // Input application handle used by the input dispatcher.
Jeff Brown9302c872011-07-13 22:51:29 -0700220 final InputApplicationHandle mInputApplicationHandle;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800221
Wale Ogunwale571771c2016-08-26 13:18:50 -0700222 // TODO: Have a WindowContainer state for tracking exiting/deferred removal.
Craig Mautner799bc1d2015-01-14 10:33:48 -0800223 boolean mIsExiting;
Craig Mautner9ef471f2014-02-07 13:11:47 -0800224
Craig Mautnerbb742462014-07-07 15:28:55 -0700225 boolean mLaunchTaskBehind;
Craig Mautner8746a472014-07-24 15:12:54 -0700226 boolean mEnteringAnimation;
Craig Mautnerbb742462014-07-07 15:28:55 -0700227
Wale Ogunwale72919d22016-12-08 18:58:50 -0800228 private boolean mAlwaysFocusable;
Wale Ogunwale6cae7652015-12-26 07:36:26 -0800229
Robert Carre12aece2016-02-02 22:43:27 -0800230 boolean mAppStopped;
Robert Carrfd10cd12016-06-29 16:41:50 -0700231 int mRotationAnimationHint;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700232 private int mPendingRelaunchCount;
Robert Carre12aece2016-02-02 22:43:27 -0800233
Jorim Jaggife762342016-10-13 14:33:27 +0200234 private boolean mLastContainsShowWhenLockedWindow;
235 private boolean mLastContainsDismissKeyguardWindow;
236
Jorim Jaggi0429f352015-12-22 16:29:16 +0100237 ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
Jorim Jaggi26c8c422016-05-09 19:57:25 -0700238 ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
Jorim Jaggi0429f352015-12-22 16:29:16 +0100239
Riddle Hsub398da32019-01-21 21:48:16 +0800240 /**
241 * The scale to fit at least one side of the activity to its parent. If the activity uses
242 * 1920x1080, and the actually size on the screen is 960x540, then the scale is 0.5.
243 */
244 private float mSizeCompatScale = 1f;
245 /**
246 * The bounds in global coordinates for activity in size compatibility mode.
247 * @see ActivityRecord#inSizeCompatMode
248 */
249 private Rect mSizeCompatBounds;
250
Wale Ogunwale6c459212017-05-17 08:56:03 -0700251 private boolean mDisablePreviewScreenshots;
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +0100252
Wale Ogunwale034a8ec2017-09-02 17:14:40 -0700253 private Task mLastParent;
Robert Carred3e83b2017-04-21 13:26:55 -0700254
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800255 // TODO: Remove after unification
256 ActivityRecord mActivityRecord;
257
chaviwd3bf08d2017-08-01 17:24:59 -0700258 /**
259 * See {@link #canTurnScreenOn()}
260 */
261 private boolean mCanTurnScreenOn = true;
262
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200263 /**
264 * If we are running an animation, this determines the transition type. Must be one of
265 * AppTransition.TRANSIT_* constants.
266 */
267 private int mTransit;
268
269 /**
270 * If we are running an animation, this determines the flags during this animation. Must be a
271 * bitwise combination of AppTransition.TRANSIT_FLAG_* constants.
272 */
273 private int mTransitFlags;
274
275 /** Whether our surface was set to be showing in the last call to {@link #prepareSurfaces} */
Jorim Jaggifd1891462017-12-29 15:41:36 +0100276 private boolean mLastSurfaceShowing = true;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200277
Evan Rosky2289ba12018-11-19 18:28:18 -0800278 /**
279 * This gets used during some open/close transitions as well as during a change transition
280 * where it represents the starting-state snapshot.
281 */
Jorim Jaggi988f6682017-11-17 17:46:43 +0100282 private AppWindowThumbnail mThumbnail;
Evan Rosky2289ba12018-11-19 18:28:18 -0800283 private final Rect mTransitStartRect = new Rect();
284
285 /**
286 * This leash is used to "freeze" the app surface in place after the state change, but before
287 * the animation is ready to start.
288 */
289 private SurfaceControl mTransitChangeLeash = null;
Jorim Jaggi988f6682017-11-17 17:46:43 +0100290
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000291 /** Have we been asked to have this token keep the screen frozen? */
292 private boolean mFreezingScreen;
293
294 /** Whether this token should be boosted at the top of all app window tokens. */
Jorim Jaggi9cd99132019-04-24 17:41:35 +0200295 @VisibleForTesting boolean mNeedsZBoost;
Adrian Roos4d18a2e2017-12-19 19:08:05 +0100296 private Letterbox mLetterbox;
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000297
chaviw23ee71c2017-12-18 11:29:41 -0800298 private final Point mTmpPoint = new Point();
chaviw23012112017-12-20 15:29:04 -0800299 private final Rect mTmpRect = new Rect();
Evan Rosky2289ba12018-11-19 18:28:18 -0800300 private final Rect mTmpPrevBounds = new Rect();
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100301 private RemoteAnimationDefinition mRemoteAnimationDefinition;
Jorim Jaggi6de61012018-03-19 14:53:23 +0100302 private AnimatingAppWindowTokenRegistry mAnimatingAppWindowTokenRegistry;
chaviw23ee71c2017-12-18 11:29:41 -0800303
chaviw4ad54912018-05-30 11:05:44 -0700304 /**
305 * A flag to determine if this AWT is in the process of closing or entering PIP. This is needed
306 * to help AWT know that the app is in the process of closing but hasn't yet started closing on
307 * the WM side.
308 */
309 private boolean mWillCloseOrEnterPip;
310
Vishnu Naira2977262018-07-26 13:31:26 -0700311 /** Layer used to constrain the animation to a token's stack bounds. */
312 SurfaceControl mAnimationBoundsLayer;
313
314 /** Whether this token needs to create mAnimationBoundsLayer for cropping animations. */
315 boolean mNeedsAnimationBoundsLayer;
316
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800317 private static final int STARTING_WINDOW_TYPE_NONE = 0;
318 private static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
319 private static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
320
chaviwdcf76ec2019-01-11 16:48:46 -0800321 private AppSaturationInfo mLastAppSaturationInfo;
322
323 private final ColorDisplayService.ColorTransformController mColorTransformController =
324 (matrix, translation) -> mWmService.mH.post(() -> {
325 synchronized (mWmService.mGlobalLock) {
326 if (mLastAppSaturationInfo == null) {
327 mLastAppSaturationInfo = new AppSaturationInfo();
328 }
329
330 mLastAppSaturationInfo.setSaturation(matrix, translation);
331 updateColorTransform();
332 }
333 });
334
Winson Chung48b25652018-10-22 14:04:30 -0700335 AppWindowToken(WindowManagerService service, IApplicationToken token,
336 ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
337 long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers,
Jorim Jaggi91d382a2019-03-27 17:00:48 +0100338 int targetSdk, int orientation, int rotationAnimationHint,
Winson Chung48b25652018-10-22 14:04:30 -0700339 boolean launchTaskBehind, boolean alwaysFocusable,
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800340 ActivityRecord activityRecord) {
Winson Chung48b25652018-10-22 14:04:30 -0700341 this(service, token, activityComponent, voiceInteraction, dc, fullscreen);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800342 // TODO: remove after unification
343 mActivityRecord = activityRecord;
344 mActivityRecord.registerConfigurationChangeListener(this);
Wale Ogunwale72919d22016-12-08 18:58:50 -0800345 mInputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800346 mShowForAllUsers = showForAllUsers;
347 mTargetSdk = targetSdk;
348 mOrientation = orientation;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800349 mLaunchTaskBehind = launchTaskBehind;
350 mAlwaysFocusable = alwaysFocusable;
351 mRotationAnimationHint = rotationAnimationHint;
352
353 // Application tokens start out hidden.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200354 setHidden(true);
Wale Ogunwale72919d22016-12-08 18:58:50 -0800355 hiddenRequested = true;
chaviwdcf76ec2019-01-11 16:48:46 -0800356
357 ColorDisplayService.ColorDisplayServiceInternal cds = LocalServices.getService(
358 ColorDisplayService.ColorDisplayServiceInternal.class);
359 cds.attachColorTransformController(activityRecord.packageName, activityRecord.mUserId,
360 new WeakReference<>(mColorTransformController));
Wale Ogunwale72919d22016-12-08 18:58:50 -0800361 }
362
Winson Chung48b25652018-10-22 14:04:30 -0700363 AppWindowToken(WindowManagerService service, IApplicationToken token,
364 ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
365 boolean fillsParent) {
Wale Ogunwale5cd907d2017-01-26 14:14:08 -0800366 super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true, dc,
367 false /* ownerCanManageAppTokens */);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700368 appToken = token;
Winson Chung48b25652018-10-22 14:04:30 -0700369 mActivityComponent = activityComponent;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800370 mVoiceInteraction = voiceInteraction;
Wale Ogunwale17f175c2017-02-07 16:54:10 -0800371 mFillsParent = fillsParent;
Robert Carr0bcbe642018-10-11 19:07:43 -0700372 mInputApplicationHandle = new InputApplicationHandle(appToken.asBinder());
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800373 }
374
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800375 void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
376 firstWindowDrawn = true;
377
378 // We now have a good window to show, remove dead placeholders
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700379 removeDeadWindows();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800380
Jorim Jaggi02886a82016-12-06 09:10:06 -0800381 if (startingWindow != null) {
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800382 if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Slog.v(TAG, "Finish starting "
383 + win.mToken + ": first real window is shown, no animation");
384 // If this initial window is animating, stop it -- we will do an animation to reveal
385 // it from behind the starting window, so there is no need for it to also be doing its
386 // own stuff.
Jorim Jaggia5e10572017-11-15 14:36:26 +0100387 win.cancelAnimation();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800388 removeStartingWindow();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800389 }
390 updateReportedVisibilityLocked();
391 }
392
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800393 void updateReportedVisibilityLocked() {
394 if (appToken == null) {
395 return;
396 }
397
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700398 if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700399 final int count = mChildren.size();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800400
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700401 mReportedVisibilityResults.reset();
402
403 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700404 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700405 win.updateReportedVisibility(mReportedVisibilityResults);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800406 }
407
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700408 int numInteresting = mReportedVisibilityResults.numInteresting;
409 int numVisible = mReportedVisibilityResults.numVisible;
410 int numDrawn = mReportedVisibilityResults.numDrawn;
411 boolean nowGone = mReportedVisibilityResults.nowGone;
412
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700413 boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200414 boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting && !isHidden();
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700415 if (!nowGone) {
416 // If the app is not yet gone, then it can only become visible/drawn.
417 if (!nowDrawn) {
418 nowDrawn = reportedDrawn;
419 }
420 if (!nowVisible) {
421 nowVisible = reportedVisible;
422 }
423 }
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800424 if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800425 + numInteresting + " visible=" + numVisible);
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700426 if (nowDrawn != reportedDrawn) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800427 if (mActivityRecord != null) {
428 mActivityRecord.onWindowsDrawn(nowDrawn, SystemClock.uptimeMillis());
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700429 }
430 reportedDrawn = nowDrawn;
431 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800432 if (nowVisible != reportedVisible) {
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700433 if (DEBUG_VISIBILITY) Slog.v(TAG,
434 "Visibility changed in " + this + ": vis=" + nowVisible);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800435 reportedVisible = nowVisible;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800436 if (mActivityRecord != null) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800437 if (nowVisible) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800438 onWindowsVisible();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800439 } else {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800440 onWindowsGone();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800441 }
442 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800443 }
444 }
445
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800446 private void onWindowsGone() {
447 if (mActivityRecord == null) {
448 return;
449 }
450 if (DEBUG_VISIBILITY) {
451 Slog.v(TAG_WM, "Reporting gone in " + mActivityRecord.appToken);
452 }
453 mActivityRecord.onWindowsGone();
454 }
455
456 private void onWindowsVisible() {
457 if (mActivityRecord == null) {
458 return;
459 }
460 if (DEBUG_VISIBILITY) {
461 Slog.v(TAG_WM, "Reporting visible in " + mActivityRecord.appToken);
462 }
463 mActivityRecord.onWindowsVisible();
464 }
465
Wale Ogunwale89973222017-04-23 18:39:45 -0700466 boolean isClientHidden() {
467 return mClientHidden;
468 }
469
470 void setClientHidden(boolean hideClient) {
471 if (mClientHidden == hideClient || (hideClient && mDeferHidingClient)) {
472 return;
473 }
Jorim Jaggi067b5bf2018-02-23 17:42:39 +0100474 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "setClientHidden: " + this
475 + " clientHidden=" + hideClient + " Callers=" + Debug.getCallers(5));
Wale Ogunwale89973222017-04-23 18:39:45 -0700476 mClientHidden = hideClient;
477 sendAppVisibilityToClients();
478 }
479
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800480 void setVisibility(boolean visible, boolean deferHidingClient) {
481 final AppTransition appTransition = getDisplayContent().mAppTransition;
482
483 // Don't set visibility to false if we were already not visible. This prevents WM from
484 // adding the app to the closing app list which doesn't make sense for something that is
485 // already not visible. However, set visibility to true even if we are already visible.
486 // This makes sure the app is added to the opening apps list so that the right
487 // transition can be selected.
488 // TODO: Probably a good idea to separate the concept of opening/closing apps from the
489 // concept of setting visibility...
490 if (!visible && hiddenRequested) {
491
492 if (!deferHidingClient && mDeferHidingClient) {
493 // We previously deferred telling the client to hide itself when visibility was
494 // initially set to false. Now we would like it to hide, so go ahead and set it.
495 mDeferHidingClient = deferHidingClient;
496 setClientHidden(true);
497 }
498 return;
499 }
500
501 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) {
502 Slog.v(TAG_WM, "setAppVisibility("
503 + appToken + ", visible=" + visible + "): " + appTransition
504 + " hidden=" + isHidden() + " hiddenRequested="
505 + hiddenRequested + " Callers=" + Debug.getCallers(6));
506 }
507
508 final DisplayContent displayContent = getDisplayContent();
509 displayContent.mOpeningApps.remove(this);
510 displayContent.mClosingApps.remove(this);
511 waitingToShow = false;
512 hiddenRequested = !visible;
513 mDeferHidingClient = deferHidingClient;
514
515 if (!visible) {
516 // If the app is dead while it was visible, we kept its dead window on screen.
517 // Now that the app is going invisible, we can remove it. It will be restarted
518 // if made visible again.
519 removeDeadWindows();
520 } else {
521 if (!appTransition.isTransitionSet()
522 && appTransition.isReady()) {
523 // Add the app mOpeningApps if transition is unset but ready. This means
524 // we're doing a screen freeze, and the unfreeze will wait for all opening
525 // apps to be ready.
526 displayContent.mOpeningApps.add(this);
527 }
528 startingMoved = false;
529 // If the token is currently hidden (should be the common case), or has been
530 // stopped, then we need to set up to wait for its windows to be ready.
531 if (isHidden() || mAppStopped) {
532 clearAllDrawn();
533
534 // If the app was already visible, don't reset the waitingToShow state.
535 if (isHidden()) {
536 waitingToShow = true;
537 }
538 }
539
540 // In the case where we are making an app visible but holding off for a transition,
541 // we still need to tell the client to make its windows visible so they get drawn.
542 // Otherwise, we will wait on performing the transition until all windows have been
543 // drawn, they never will be, and we are sad.
544 setClientHidden(false);
545
546 requestUpdateWallpaperIfNeeded();
547
548 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "No longer Stopped: " + this);
549 mAppStopped = false;
550
551 transferStartingWindowFromHiddenAboveTokenIfNeeded();
552 }
553
554 // If we are preparing an app transition, then delay changing
555 // the visibility of this token until we execute that transition.
556 if (okToAnimate() && appTransition.isTransitionSet()) {
557 inPendingTransaction = true;
558 if (visible) {
559 displayContent.mOpeningApps.add(this);
560 mEnteringAnimation = true;
561 } else {
562 displayContent.mClosingApps.add(this);
563 mEnteringAnimation = false;
564 }
565 if (appTransition.getAppTransition()
566 == WindowManager.TRANSIT_TASK_OPEN_BEHIND) {
567 // We're launchingBehind, add the launching activity to mOpeningApps.
568 final WindowState win = getDisplayContent().findFocusedWindow();
569 if (win != null) {
570 final AppWindowToken focusedToken = win.mAppToken;
571 if (focusedToken != null) {
572 if (DEBUG_APP_TRANSITIONS) {
573 Slog.d(TAG_WM, "TRANSIT_TASK_OPEN_BEHIND, "
574 + " adding " + focusedToken + " to mOpeningApps");
575 }
576 // Force animation to be loaded.
577 focusedToken.setHidden(true);
578 displayContent.mOpeningApps.add(focusedToken);
579 }
580 }
581 }
Garfield Tanb6776602019-02-20 14:44:26 -0800582 // Changes in opening apps and closing apps may cause orientation change.
583 reportDescendantOrientationChangeIfNeeded();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800584 return;
585 }
586
587 commitVisibility(null, visible, TRANSIT_UNSET, true, mVoiceInteraction);
588 updateReportedVisibilityLocked();
589 }
590
591 boolean commitVisibility(WindowManager.LayoutParams lp,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700592 boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
593
594 boolean delayed = false;
595 inPendingTransaction = false;
Wale Ogunwale9e4721f2017-05-23 19:37:30 -0700596 // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually
597 // been set by the app now.
598 mHiddenSetFromTransferredStartingWindow = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700599
600 // Allow for state changes and animation to be applied if:
601 // * token is transitioning visibility state
602 // * or the token was marked as hidden and is exiting before we had a chance to play the
603 // transition animation
604 // * or this is an opening app and windows are being replaced.
605 boolean visibilityChanged = false;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200606 if (isHidden() == visible || (isHidden() && mIsExiting) || (visible && waitingForReplacement())) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800607 final AccessibilityController accessibilityController =
608 mWmService.mAccessibilityController;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700609 boolean changed = false;
610 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM,
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200611 "Changing app " + this + " hidden=" + isHidden() + " performLayout=" + performLayout);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700612
613 boolean runningAppAnimation = false;
614
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100615 if (transit != WindowManager.TRANSIT_UNSET) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200616 if (applyAnimationLocked(lp, transit, visible, isVoiceInteraction)) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700617 delayed = runningAppAnimation = true;
618 }
619 final WindowState window = findMainWindow();
Rhed Jao02655dc2018-10-30 20:44:52 +0800620 if (window != null && accessibilityController != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700621 accessibilityController.onAppWindowTransitionLocked(window, transit);
622 }
623 changed = true;
624 }
625
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700626 final int windowsCount = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700627 for (int i = 0; i < windowsCount; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700628 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700629 changed |= win.onAppVisibilityChanged(visible, runningAppAnimation);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700630 }
631
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200632 setHidden(!visible);
633 hiddenRequested = !visible;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700634 visibilityChanged = true;
635 if (!visible) {
636 stopFreezingScreen(true, true);
637 } else {
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700638 // If we are being set visible, and the starting window is not yet displayed,
639 // then make sure it doesn't get displayed.
640 if (startingWindow != null && !startingWindow.isDrawnLw()) {
641 startingWindow.mPolicyVisibility = false;
642 startingWindow.mPolicyVisibilityAfterAnim = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700643 }
Jorim Jaggi38d44ec2017-06-14 16:04:59 -0700644
645 // We are becoming visible, so better freeze the screen with the windows that are
646 // getting visible so we also wait for them.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800647 forAllWindows(mWmService::makeWindowFreezingScreenIfNeededLocked, true);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700648 }
649
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800650 if (DEBUG_APP_TRANSITIONS) {
651 Slog.v(TAG_WM, "commitVisibility: " + this
652 + ": hidden=" + isHidden() + " hiddenRequested=" + hiddenRequested);
653 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700654
655 if (changed) {
Arthur Hung95b38a92018-07-20 18:56:12 +0800656 getDisplayContent().getInputMonitor().setUpdateInputWindowsNeededLw();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700657 if (performLayout) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800658 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700659 false /*updateInputWindows*/);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800660 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700661 }
Arthur Hung95b38a92018-07-20 18:56:12 +0800662 getDisplayContent().getInputMonitor().updateInputWindowsLw(false /*force*/);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700663 }
664 }
665
lumarkd14173e2019-03-27 19:14:33 +0800666 if (isReallyAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700667 delayed = true;
Jorim Jaggiab9fcb22018-03-15 23:46:12 +0100668 } else {
669
670 // We aren't animating anything, but exiting windows rely on the animation finished
671 // callback being called in case the AppWindowToken was pretending to be animating,
672 // which we might have done because we were in closing/opening apps list.
673 onAnimationFinished();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700674 }
675
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700676 for (int i = mChildren.size() - 1; i >= 0 && !delayed; i--) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100677 if ((mChildren.get(i)).isSelfOrChildAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700678 delayed = true;
679 }
680 }
681
682 if (visibilityChanged) {
683 if (visible && !delayed) {
684 // The token was made immediately visible, there will be no entrance animation.
685 // We need to inform the client the enter animation was finished.
686 mEnteringAnimation = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800687 mWmService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(
688 token);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700689 }
Robert Carr61b81112017-07-17 18:08:15 -0700690
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800691 // If we're becoming visible, immediately change client visibility as well. there seem
692 // to be some edge cases where we change our visibility but client visibility never gets
693 // updated.
Jorim Jaggi110839b2018-01-22 12:49:04 +0100694 // If we're becoming invisible, update the client visibility if we are not running an
695 // animation. Otherwise, we'll update client visibility in onAnimationFinished.
Jorim Jaggi3cad57f2018-02-20 18:32:01 +0100696 if (visible || !isReallyAnimating()) {
Jorim Jaggi110839b2018-01-22 12:49:04 +0100697 setClientHidden(!visible);
Jorim Jaggi4876b4a2018-01-11 15:43:49 +0100698 }
699
lumark588a3e82018-07-20 18:53:54 +0800700 if (!getDisplayContent().mClosingApps.contains(this)
701 && !getDisplayContent().mOpeningApps.contains(this)) {
chaviwa953fcf2018-03-01 12:00:39 -0800702 // The token is not closing nor opening, so even if there is an animation set, that
703 // doesn't mean that it goes through the normal app transition cycle so we have
704 // to inform the docked controller about visibility change.
705 // TODO(multi-display): notify docked divider on all displays where visibility was
706 // affected.
lumark588a3e82018-07-20 18:53:54 +0800707 getDisplayContent().getDockedDividerController().notifyAppVisibilityChanged();
chaviwa953fcf2018-03-01 12:00:39 -0800708
709 // Take the screenshot before possibly hiding the WSA, otherwise the screenshot
710 // will not be taken.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800711 mWmService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible);
chaviwa953fcf2018-03-01 12:00:39 -0800712 }
713
Robert Carre7cc44d2017-03-20 19:04:30 -0700714 // If we are hidden but there is no delay needed we immediately
715 // apply the Surface transaction so that the ActivityManager
Robert Carr61b81112017-07-17 18:08:15 -0700716 // can have some guarantee on the Surface state following
717 // setting the visibility. This captures cases like dismissing
718 // the docked or pinned stack where there is no app transition.
719 //
720 // In the case of a "Null" animation, there will be
721 // no animation but there will still be a transition set.
722 // We still need to delay hiding the surface such that it
723 // can be synchronized with showing the next surface in the transition.
lumark588a3e82018-07-20 18:53:54 +0800724 if (isHidden() && !delayed && !getDisplayContent().mAppTransition.isTransitionSet()) {
Robert Carr6914f082017-03-20 19:04:30 -0700725 SurfaceControl.openTransaction();
726 for (int i = mChildren.size() - 1; i >= 0; i--) {
727 mChildren.get(i).mWinAnimator.hide("immediately hidden");
728 }
729 SurfaceControl.closeTransaction();
730 }
Garfield Tanb6776602019-02-20 14:44:26 -0800731
732 // Visibility changes may cause orientation request change.
733 reportDescendantOrientationChangeIfNeeded();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700734 }
735
736 return delayed;
737 }
738
Garfield Tanb6776602019-02-20 14:44:26 -0800739 private void reportDescendantOrientationChangeIfNeeded() {
740 // Orientation request is exposed only when we're visible. Therefore visibility change
741 // will change requested orientation. Notify upward the hierarchy ladder to adjust
742 // configuration. This is important to cases where activities with incompatible
743 // orientations launch, or user goes back from an activity of bi-orientation to an
744 // activity with specified orientation.
745 if (mActivityRecord.getRequestedConfigurationOrientation() == getConfiguration().orientation
746 || getOrientationIgnoreVisibility() == SCREEN_ORIENTATION_UNSET) {
747 return;
748 }
749
750 final IBinder freezeToken =
751 mActivityRecord.mayFreezeScreenLocked(mActivityRecord.app)
752 ? mActivityRecord.appToken : null;
753 onDescendantOrientationChanged(freezeToken, mActivityRecord);
754 }
755
Jorim Jaggi87fdbcb2017-08-17 13:41:11 +0200756 /**
757 * @return The to top most child window for which {@link LayoutParams#isFullscreen()} returns
758 * true.
759 */
760 WindowState getTopFullscreenWindow() {
761 for (int i = mChildren.size() - 1; i >= 0; i--) {
762 final WindowState win = mChildren.get(i);
763 if (win != null && win.mAttrs.isFullscreen()) {
764 return win;
765 }
766 }
767 return null;
768 }
769
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800770 WindowState findMainWindow() {
Matthew Ng53e66b22018-01-12 17:13:13 -0800771 return findMainWindow(true);
772 }
773
774 /**
775 * Finds the main window that either has type base application or application starting if
776 * requested.
777 *
778 * @param includeStartingApp Allow to search application-starting windows to also be returned.
779 * @return The main window of type base application or application starting if requested.
780 */
781 WindowState findMainWindow(boolean includeStartingApp) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700782 WindowState candidate = null;
Matthew Ng53e66b22018-01-12 17:13:13 -0800783 for (int j = mChildren.size() - 1; j >= 0; --j) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700784 final WindowState win = mChildren.get(j);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700785 final int type = win.mAttrs.type;
786 // No need to loop through child window as base application and starting types can't be
787 // child windows.
Matthew Ng53e66b22018-01-12 17:13:13 -0800788 if (type == TYPE_BASE_APPLICATION
789 || (includeStartingApp && type == TYPE_APPLICATION_STARTING)) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700790 // In cases where there are multiple windows, we prefer the non-exiting window. This
Sungsoo Lim0d3d1f82015-12-02 14:47:59 +0900791 // happens for example when replacing windows during an activity relaunch. When
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700792 // constructing the animation, we want the new window, not the exiting one.
Wale Ogunwalec48a3542016-02-19 15:18:45 -0800793 if (win.mAnimatingExit) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700794 candidate = win;
795 } else {
796 return win;
797 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800798 }
799 }
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700800 return candidate;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800801 }
802
Wale Ogunwale6cae7652015-12-26 07:36:26 -0800803 boolean windowsAreFocusable() {
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800804 if (mTargetSdk < Build.VERSION_CODES.Q) {
805 final int pid = mActivityRecord != null
806 ? (mActivityRecord.app != null ? mActivityRecord.app.getPid() : 0) : 0;
807 final AppWindowToken topFocusedAppOfMyProcess =
808 mWmService.mRoot.mTopFocusedAppByProcess.get(pid);
809 if (topFocusedAppOfMyProcess != null && topFocusedAppOfMyProcess != this) {
810 // For the apps below Q, there can be only one app which has the focused window per
811 // process, because legacy apps may not be ready for a multi-focus system.
812 return false;
813 }
814 }
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700815 return getWindowConfiguration().canReceiveKeys() || mAlwaysFocusable;
Wale Ogunwaled045c822015-12-02 09:14:28 -0800816 }
817
Wale Ogunwale571771c2016-08-26 13:18:50 -0700818 @Override
Wale Ogunwale44f21802016-09-02 12:49:48 -0700819 boolean isVisible() {
Wale Ogunwalee471be62016-10-03 07:53:55 -0700820 // If the app token isn't hidden then it is considered visible and there is no need to check
821 // its children windows to see if they are visible.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200822 return !isHidden();
Wale Ogunwale44f21802016-09-02 12:49:48 -0700823 }
824
825 @Override
Wale Ogunwalee287e192017-04-21 09:30:12 -0700826 void removeImmediately() {
827 onRemovedFromDisplay();
Yunfan Chen3a77f282018-12-12 15:47:52 -0800828 if (mActivityRecord != null) {
829 mActivityRecord.unregisterConfigurationChangeListener(this);
830 }
Wale Ogunwalee287e192017-04-21 09:30:12 -0700831 super.removeImmediately();
832 }
833
834 @Override
Wale Ogunwale571771c2016-08-26 13:18:50 -0700835 void removeIfPossible() {
Craig Mautnere3119b72015-01-20 15:02:36 -0800836 mIsExiting = false;
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800837 removeAllWindowsIfPossible();
Bryce Lee6d410262017-02-28 15:30:17 -0800838 removeImmediately();
Craig Mautnere3119b72015-01-20 15:02:36 -0800839 }
840
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700841 @Override
842 boolean checkCompleteDeferredRemoval() {
843 if (mIsExiting) {
844 removeIfPossible();
845 }
846 return super.checkCompleteDeferredRemoval();
847 }
848
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700849 void onRemovedFromDisplay() {
Wale Ogunwalee287e192017-04-21 09:30:12 -0700850 if (mRemovingFromDisplay) {
851 return;
852 }
853 mRemovingFromDisplay = true;
854
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700855 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app token: " + this);
856
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800857 boolean delayed = commitVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700858
lumark588a3e82018-07-20 18:53:54 +0800859 getDisplayContent().mOpeningApps.remove(this);
Evan Rosky2289ba12018-11-19 18:28:18 -0800860 getDisplayContent().mChangingApps.remove(this);
lumark588a3e82018-07-20 18:53:54 +0800861 getDisplayContent().mUnknownAppVisibilityController.appRemovedOrHidden(this);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800862 mWmService.mTaskSnapshotController.onAppRemoved(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700863 waitingToShow = false;
lumark588a3e82018-07-20 18:53:54 +0800864 if (getDisplayContent().mClosingApps.contains(this)) {
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700865 delayed = true;
lumark588a3e82018-07-20 18:53:54 +0800866 } else if (getDisplayContent().mAppTransition.isTransitionSet()) {
867 getDisplayContent().mClosingApps.add(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700868 delayed = true;
869 }
870
871 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app " + this + " delayed=" + delayed
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200872 + " animation=" + getAnimation() + " animating=" + isSelfAnimating());
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700873
874 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: "
875 + this + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
876
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800877 if (startingData != null) {
878 removeStartingWindow();
Jorim Jaggi19be6052017-08-03 18:33:43 +0200879 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800880
Winson Chung87e5d552017-04-05 11:49:38 -0700881 // If this window was animating, then we need to ensure that the app transition notifies
lumark588a3e82018-07-20 18:53:54 +0800882 // that animations have completed in DisplayContent.handleAnimatingStoppedAndTransition(),
883 // so add to that list now
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200884 if (isSelfAnimating()) {
lumark588a3e82018-07-20 18:53:54 +0800885 getDisplayContent().mNoAnimationNotifyOnTransitionFinished.add(token);
Winson Chung87e5d552017-04-05 11:49:38 -0700886 }
887
Wale Ogunwalee287e192017-04-21 09:30:12 -0700888 final TaskStack stack = getStack();
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700889 if (delayed && !isEmpty()) {
890 // set the token aside because it has an active animation to be finished
891 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM,
892 "removeAppToken make exiting: " + this);
Wale Ogunwalee287e192017-04-21 09:30:12 -0700893 if (stack != null) {
894 stack.mExitingAppTokens.add(this);
895 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700896 mIsExiting = true;
897 } else {
898 // Make sure there is no animation running on this token, so any windows associated
899 // with it will be removed as soon as their animations are complete
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200900 cancelAnimation();
Wale Ogunwale3106ae012017-05-16 08:56:37 -0700901 if (stack != null) {
902 stack.mExitingAppTokens.remove(this);
903 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700904 removeIfPossible();
905 }
906
907 removed = true;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700908 stopFreezingScreen(true, true);
Bryce Lee6d410262017-02-28 15:30:17 -0800909
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800910 final DisplayContent dc = getDisplayContent();
911 if (dc.mFocusedApp == this) {
912 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + this
913 + " displayId=" + dc.getDisplayId());
914 dc.setFocusedApp(null);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800915 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700916 }
Riddle Hsu192fe762019-01-15 23:41:57 +0800917 if (mLetterbox != null) {
918 mLetterbox.destroy();
919 mLetterbox = null;
920 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700921
922 if (!delayed) {
923 updateReportedVisibilityLocked();
924 }
Wale Ogunwalee287e192017-04-21 09:30:12 -0700925
926 mRemovingFromDisplay = false;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700927 }
928
Chong Zhange05bcb12016-07-26 17:47:29 -0700929 void clearAnimatingFlags() {
Chong Zhangb0d26702016-08-12 16:03:29 -0700930 boolean wallpaperMightChange = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700931 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700932 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700933 wallpaperMightChange |= win.clearAnimatingFlags();
Chong Zhange05bcb12016-07-26 17:47:29 -0700934 }
Chong Zhangb0d26702016-08-12 16:03:29 -0700935 if (wallpaperMightChange) {
936 requestUpdateWallpaperIfNeeded();
937 }
Chong Zhange05bcb12016-07-26 17:47:29 -0700938 }
939
Robert Carre12aece2016-02-02 22:43:27 -0800940 void destroySurfaces() {
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700941 destroySurfaces(false /*cleanupOnResume*/);
942 }
943
944 /**
945 * Destroy surfaces which have been marked as eligible by the animator, taking care to ensure
946 * the client has finished with them.
947 *
948 * @param cleanupOnResume whether this is done when app is resumed without fully stopped. If
949 * set to true, destroy only surfaces of removed windows, and clear relevant flags of the
950 * others so that they are ready to be reused. If set to false (common case), destroy all
951 * surfaces that's eligible, if the app is already stopped.
952 */
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700953 private void destroySurfaces(boolean cleanupOnResume) {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700954 boolean destroyedSomething = false;
Jorim Jaggia5e10572017-11-15 14:36:26 +0100955
956 // Copying to a different list as multiple children can be removed.
Jorim Jaggi59f3e922018-01-05 15:40:32 +0100957 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
Jorim Jaggia5e10572017-11-15 14:36:26 +0100958 for (int i = children.size() - 1; i >= 0; i--) {
959 final WindowState win = children.get(i);
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700960 destroyedSomething |= win.destroySurface(cleanupOnResume, mAppStopped);
Robert Carre12aece2016-02-02 22:43:27 -0800961 }
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700962 if (destroyedSomething) {
963 final DisplayContent dc = getDisplayContent();
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700964 dc.assignWindowLayers(true /*setLayoutNeeded*/);
Adrian Roos23df3a32018-03-15 15:41:13 +0100965 updateLetterboxSurface(null);
Robert Carre12aece2016-02-02 22:43:27 -0800966 }
967 }
968
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800969 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700970 * Notify that the app is now resumed, and it was not stopped before, perform a clean
971 * up of the surfaces
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800972 */
Jorim Jaggibae01b12017-04-11 16:29:10 -0700973 void notifyAppResumed(boolean wasStopped) {
Chong Zhangad24f962016-08-25 12:12:33 -0700974 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppResumed: wasStopped=" + wasStopped
Jorim Jaggibae01b12017-04-11 16:29:10 -0700975 + " " + this);
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700976 mAppStopped = false;
chaviwd3bf08d2017-08-01 17:24:59 -0700977 // Allow the window to turn the screen on once the app is resumed again.
978 setCanTurnScreenOn(true);
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700979 if (!wasStopped) {
980 destroySurfaces(true /*cleanupOnResume*/);
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800981 }
Robert Carre12aece2016-02-02 22:43:27 -0800982 }
983
Chong Zhangbef461f2015-10-27 11:38:24 -0700984 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700985 * Notify that the app has stopped, and it is okay to destroy any surfaces which were
986 * keeping alive in case they were still being used.
987 */
988 void notifyAppStopped() {
989 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: " + this);
990 mAppStopped = true;
991 destroySurfaces();
992 // Remove any starting window that was added for this app if they are still around.
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800993 removeStartingWindow();
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700994 }
995
Chong Zhang92147042016-05-09 12:47:11 -0700996 void clearAllDrawn() {
997 allDrawn = false;
998 deferClearAllDrawn = false;
Chong Zhangbef461f2015-10-27 11:38:24 -0700999 }
1000
Bryce Lee6d410262017-02-28 15:30:17 -08001001 Task getTask() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001002 return (Task) getParent();
Bryce Lee6d410262017-02-28 15:30:17 -08001003 }
1004
Jorim Jaggi3878ca32017-02-02 17:13:05 -08001005 TaskStack getStack() {
1006 final Task task = getTask();
1007 if (task != null) {
1008 return task.mStack;
1009 } else {
1010 return null;
1011 }
1012 }
1013
Bryce Lee6d410262017-02-28 15:30:17 -08001014 @Override
Riddle Hsu3a4bb612019-01-31 00:02:22 +08001015 void onParentChanged() {
1016 super.onParentChanged();
Bryce Lee6d410262017-02-28 15:30:17 -08001017
Robert Carred3e83b2017-04-21 13:26:55 -07001018 final Task task = getTask();
1019
Bryce Lee6d410262017-02-28 15:30:17 -08001020 // When the associated task is {@code null}, the {@link AppWindowToken} can no longer
1021 // access visual elements like the {@link DisplayContent}. We must remove any associations
1022 // such as animations.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001023 if (!mReparenting) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001024 if (task == null) {
1025 // It is possible we have been marked as a closing app earlier. We must remove ourselves
1026 // from this list so we do not participate in any future animations.
lumark588a3e82018-07-20 18:53:54 +08001027 getDisplayContent().mClosingApps.remove(this);
Robert Carred3e83b2017-04-21 13:26:55 -07001028 } else if (mLastParent != null && mLastParent.mStack != null) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001029 task.mStack.mExitingAppTokens.remove(this);
1030 }
Bryce Lee6d410262017-02-28 15:30:17 -08001031 }
Jorim Jaggi6de61012018-03-19 14:53:23 +01001032 final TaskStack stack = getStack();
1033
1034 // If we reparent, make sure to remove ourselves from the old animation registry.
1035 if (mAnimatingAppWindowTokenRegistry != null) {
1036 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
1037 }
1038 mAnimatingAppWindowTokenRegistry = stack != null
1039 ? stack.getAnimatingAppWindowTokenRegistry()
1040 : null;
1041
Robert Carred3e83b2017-04-21 13:26:55 -07001042 mLastParent = task;
chaviwdcf76ec2019-01-11 16:48:46 -08001043
1044 updateColorTransform();
Bryce Lee6d410262017-02-28 15:30:17 -08001045 }
1046
Wale Ogunwalefa854eb2016-09-20 13:43:52 -07001047 void postWindowRemoveStartingWindowCleanup(WindowState win) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001048 // TODO: Something smells about the code below...Is there a better way?
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001049 if (startingWindow == win) {
1050 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Notify removed startingWindow " + win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001051 removeStartingWindow();
Wale Ogunwale6c459212017-05-17 08:56:03 -07001052 } else if (mChildren.size() == 0) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001053 // If this is the last window and we had requested a starting transition window,
1054 // well there is no point now.
Jorim Jaggi02886a82016-12-06 09:10:06 -08001055 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Nulling last startingData");
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001056 startingData = null;
Wale Ogunwale6c459212017-05-17 08:56:03 -07001057 if (mHiddenSetFromTransferredStartingWindow) {
1058 // We set the hidden state to false for the token from a transferred starting window.
1059 // We now reset it back to true since the starting window was the last window in the
1060 // token.
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001061 setHidden(true);
Wale Ogunwale6c459212017-05-17 08:56:03 -07001062 }
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01001063 } else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001064 // If this is the last window except for a starting transition window,
1065 // we need to get rid of the starting transition.
Jorim Jaggie4b0f282017-05-17 15:10:29 +02001066 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Last window, removing starting window "
1067 + win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001068 removeStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001069 }
1070 }
1071
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001072 void removeDeadWindows() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001073 for (int winNdx = mChildren.size() - 1; winNdx >= 0; --winNdx) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001074 WindowState win = mChildren.get(winNdx);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001075 if (win.mAppDied) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001076 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.w(TAG,
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001077 "removeDeadWindows: " + win);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001078 // Set mDestroying, we don't want any animation or delayed removal here.
1079 win.mDestroying = true;
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001080 // Also removes child windows.
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001081 win.removeIfPossible();
Chong Zhang112eb8c2015-11-02 11:17:00 -08001082 }
1083 }
1084 }
1085
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001086 boolean hasWindowsAlive() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001087 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001088 // No need to loop through child windows as the answer should be the same as that of the
1089 // parent window.
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001090 if (!(mChildren.get(i)).mAppDied) {
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001091 return true;
1092 }
1093 }
1094 return false;
1095 }
1096
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001097 void setWillReplaceWindows(boolean animate) {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001098 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
1099 "Marking app token " + this + " with replacing windows.");
Robert Carra1eb4392015-12-10 12:43:51 -08001100
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001101 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001102 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001103 w.setWillReplaceWindow(animate);
Robert Carra1eb4392015-12-10 12:43:51 -08001104 }
Robert Carra1eb4392015-12-10 12:43:51 -08001105 }
1106
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001107 void setWillReplaceChildWindows() {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001108 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Marking app token " + this
Robert Carr23fa16b2016-01-13 13:19:58 -08001109 + " with replacing child windows.");
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001110 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001111 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001112 w.setWillReplaceChildWindows();
Robert Carr23fa16b2016-01-13 13:19:58 -08001113 }
1114 }
1115
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001116 void clearWillReplaceWindows() {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001117 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
1118 "Resetting app token " + this + " of replacing window marks.");
Chong Zhangf596cd52016-01-05 13:42:44 -08001119
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001120 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001121 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001122 w.clearWillReplaceWindow();
Chong Zhangf596cd52016-01-05 13:42:44 -08001123 }
1124 }
1125
Chong Zhang4d7369a2016-04-25 16:09:14 -07001126 void requestUpdateWallpaperIfNeeded() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001127 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001128 final WindowState w = mChildren.get(i);
Chong Zhang4d7369a2016-04-25 16:09:14 -07001129 w.requestUpdateWallpaperIfNeeded();
1130 }
1131 }
1132
Chong Zhangd78ddb42016-03-02 17:01:14 -08001133 boolean isRelaunching() {
1134 return mPendingRelaunchCount > 0;
1135 }
1136
Robert Carr68375192017-06-13 12:41:53 -07001137 boolean shouldFreezeBounds() {
1138 final Task task = getTask();
1139
1140 // For freeform windows, we can't freeze the bounds at the moment because this would make
1141 // the resizing unresponsive.
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001142 if (task == null || task.inFreeformWindowingMode()) {
Robert Carr68375192017-06-13 12:41:53 -07001143 return false;
1144 }
1145
1146 // We freeze the bounds while drag resizing to deal with the time between
1147 // the divider/drag handle being released, and the handling it's new
1148 // configuration. If we are relaunched outside of the drag resizing state,
1149 // we need to be careful not to do this.
1150 return getTask().isDragResizing();
1151 }
1152
Chong Zhangd78ddb42016-03-02 17:01:14 -08001153 void startRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001154 if (shouldFreezeBounds()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08001155 freezeBounds();
1156 }
Robert Carrd5c7dd62017-03-08 10:39:30 -08001157
1158 // In the process of tearing down before relaunching, the app will
1159 // try and clean up it's child surfaces. We need to prevent this from
1160 // happening, so we sever the children, transfering their ownership
1161 // from the client it-self to the parent surface (owned by us).
Robert Carr29daa922018-04-27 11:56:48 -07001162 detachChildren();
1163
1164 mPendingRelaunchCount++;
1165 }
1166
1167 void detachChildren() {
Robert Carrfd8e93b2018-05-10 13:40:25 -07001168 SurfaceControl.openTransaction();
Robert Carrd5c7dd62017-03-08 10:39:30 -08001169 for (int i = mChildren.size() - 1; i >= 0; i--) {
1170 final WindowState w = mChildren.get(i);
1171 w.mWinAnimator.detachChildren();
1172 }
Robert Carrfd8e93b2018-05-10 13:40:25 -07001173 SurfaceControl.closeTransaction();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001174 }
1175
1176 void finishRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001177 unfreezeBounds();
1178
Chong Zhangd78ddb42016-03-02 17:01:14 -08001179 if (mPendingRelaunchCount > 0) {
1180 mPendingRelaunchCount--;
Bryce Lee081554b2017-05-25 07:52:12 -07001181 } else {
1182 // Update keyguard flags upon finishing relaunch.
1183 checkKeyguardFlagsChanged();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001184 }
1185 }
1186
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001187 void clearRelaunching() {
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001188 if (mPendingRelaunchCount == 0) {
1189 return;
1190 }
Robert Carr68375192017-06-13 12:41:53 -07001191 unfreezeBounds();
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001192 mPendingRelaunchCount = 0;
1193 }
1194
Wale Ogunwale07bcab72016-10-14 15:30:09 -07001195 /**
1196 * Returns true if the new child window we are adding to this token is considered greater than
1197 * the existing child window in this token in terms of z-order.
1198 */
1199 @Override
1200 protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
1201 WindowState existingWindow) {
1202 final int type1 = newWindow.mAttrs.type;
1203 final int type2 = existingWindow.mAttrs.type;
1204
1205 // Base application windows should be z-ordered BELOW all other windows in the app token.
1206 if (type1 == TYPE_BASE_APPLICATION && type2 != TYPE_BASE_APPLICATION) {
1207 return false;
1208 } else if (type1 != TYPE_BASE_APPLICATION && type2 == TYPE_BASE_APPLICATION) {
1209 return true;
1210 }
1211
1212 // Starting windows should be z-ordered ABOVE all other windows in the app token.
1213 if (type1 == TYPE_APPLICATION_STARTING && type2 != TYPE_APPLICATION_STARTING) {
1214 return true;
1215 } else if (type1 != TYPE_APPLICATION_STARTING && type2 == TYPE_APPLICATION_STARTING) {
1216 return false;
1217 }
1218
1219 // Otherwise the new window is greater than the existing window.
1220 return true;
1221 }
1222
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001223 @Override
Robert Carra1eb4392015-12-10 12:43:51 -08001224 void addWindow(WindowState w) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001225 super.addWindow(w);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001226
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001227 boolean gotReplacementWindow = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001228 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001229 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001230 gotReplacementWindow |= candidate.setReplacementWindowIfNeeded(w);
1231 }
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001232
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001233 // if we got a replacement window, reset the timeout to give drawing more time
1234 if (gotReplacementWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001235 mWmService.scheduleWindowReplacementTimeouts(this);
Robert Carra1eb4392015-12-10 12:43:51 -08001236 }
Jorim Jaggife762342016-10-13 14:33:27 +02001237 checkKeyguardFlagsChanged();
1238 }
1239
1240 @Override
1241 void removeChild(WindowState child) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001242 if (!mChildren.contains(child)) {
1243 // This can be true when testing.
1244 return;
1245 }
Jorim Jaggife762342016-10-13 14:33:27 +02001246 super.removeChild(child);
1247 checkKeyguardFlagsChanged();
Adrian Roos23df3a32018-03-15 15:41:13 +01001248 updateLetterboxSurface(child);
Robert Carra1eb4392015-12-10 12:43:51 -08001249 }
1250
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001251 private boolean waitingForReplacement() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001252 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001253 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001254 if (candidate.waitingForReplacement()) {
Robert Carra1eb4392015-12-10 12:43:51 -08001255 return true;
1256 }
1257 }
1258 return false;
1259 }
1260
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001261 void onWindowReplacementTimeout() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001262 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001263 (mChildren.get(i)).onWindowReplacementTimeout();
Robert Carra1eb4392015-12-10 12:43:51 -08001264 }
1265 }
1266
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001267 void reparent(Task task, int position) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001268 if (DEBUG_ADD_REMOVE) {
1269 Slog.i(TAG_WM, "reparent: moving app token=" + this
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001270 + " to task=" + task.mTaskId + " at " + position);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001271 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001272 if (task == null) {
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001273 throw new IllegalArgumentException("reparent: could not find task");
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001274 }
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001275 final Task currentTask = getTask();
1276 if (task == currentTask) {
Winson Chung30480042017-01-26 10:55:34 -08001277 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001278 "window token=" + this + " already child of task=" + currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001279 }
Bryce Lee6d410262017-02-28 15:30:17 -08001280
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001281 if (currentTask.mStack != task.mStack) {
Bryce Lee6d410262017-02-28 15:30:17 -08001282 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001283 "window token=" + this + " current task=" + currentTask
Bryce Lee6d410262017-02-28 15:30:17 -08001284 + " belongs to a different stack than " + task);
1285 }
1286
Winson Chung30480042017-01-26 10:55:34 -08001287 if (DEBUG_ADD_REMOVE) Slog.i(TAG, "reParentWindowToken: removing window token=" + this
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001288 + " from task=" + currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001289 final DisplayContent prevDisplayContent = getDisplayContent();
1290
Bryce Lee6d410262017-02-28 15:30:17 -08001291 mReparenting = true;
1292
Winson Chung30480042017-01-26 10:55:34 -08001293 getParent().removeChild(this);
1294 task.addChild(this, position);
1295
Bryce Lee6d410262017-02-28 15:30:17 -08001296 mReparenting = false;
1297
Winson Chung30480042017-01-26 10:55:34 -08001298 // Relayout display(s).
1299 final DisplayContent displayContent = task.getDisplayContent();
1300 displayContent.setLayoutNeeded();
1301 if (prevDisplayContent != displayContent) {
1302 onDisplayChanged(displayContent);
1303 prevDisplayContent.setLayoutNeeded();
1304 }
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001305 getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
Winson Chung30480042017-01-26 10:55:34 -08001306 }
1307
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001308 @Override
1309 void onDisplayChanged(DisplayContent dc) {
1310 DisplayContent prevDc = mDisplayContent;
1311 super.onDisplayChanged(dc);
Evan Rosky25b56192019-02-06 16:10:56 -08001312 if (prevDc == null) {
1313 return;
1314 }
1315 if (prevDc.mChangingApps.contains(this)) {
1316 // This gets called *after* the AppWindowToken has been reparented to the new display.
1317 // That reparenting resulted in this window changing modes (eg. FREEFORM -> FULLSCREEN),
1318 // so this token is now "frozen" while waiting for the animation to start on prevDc
1319 // (which will be cancelled since the window is no-longer a child). However, since this
1320 // is no longer a child of prevDc, this won't be notified of the cancelled animation,
1321 // so we need to cancel the change transition here.
1322 clearChangeLeash(getPendingTransaction(), true /* cancel */);
1323 }
1324 if (prevDc.mFocusedApp == this) {
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001325 prevDc.setFocusedApp(null);
lumarkbf844642018-11-23 17:11:36 +08001326 final TaskStack stack = dc.getTopStack();
1327 if (stack != null) {
1328 final Task task = stack.getTopChild();
1329 if (task != null && task.getTopChild() == this) {
1330 dc.setFocusedApp(this);
1331 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001332 }
1333 }
Riddle Hsu192fe762019-01-15 23:41:57 +08001334
1335 if (prevDc != mDisplayContent && mLetterbox != null) {
1336 mLetterbox.onMovedToDisplay(mDisplayContent.getDisplayId());
1337 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001338 }
1339
Jorim Jaggi0429f352015-12-22 16:29:16 +01001340 /**
1341 * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds
1342 * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even
1343 * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen
1344 * with a queue.
1345 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001346 private void freezeBounds() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001347 final Task task = getTask();
1348 mFrozenBounds.offer(new Rect(task.mPreparedFrozenBounds));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001349
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001350 if (task.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001351 // We didn't call prepareFreezingBounds on the task, so use the current value.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001352 mFrozenMergedConfig.offer(new Configuration(task.getConfiguration()));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001353 } else {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001354 mFrozenMergedConfig.offer(new Configuration(task.mPreparedFrozenMergedConfig));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001355 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001356 // Calling unset() to make it equal to Configuration.EMPTY.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001357 task.mPreparedFrozenMergedConfig.unset();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001358 }
1359
1360 /**
1361 * Unfreezes the previously frozen bounds. See {@link #freezeBounds}.
1362 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001363 private void unfreezeBounds() {
Robert Carr68375192017-06-13 12:41:53 -07001364 if (mFrozenBounds.isEmpty()) {
1365 return;
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001366 }
Robert Carr68375192017-06-13 12:41:53 -07001367 mFrozenBounds.remove();
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001368 if (!mFrozenMergedConfig.isEmpty()) {
1369 mFrozenMergedConfig.remove();
1370 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001371 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001372 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001373 win.onUnfreezeBounds();
Jorim Jaggi4846ee32016-01-07 17:39:12 +01001374 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001375 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001376 }
1377
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001378 void setAppLayoutChanges(int changes, String reason) {
1379 if (!mChildren.isEmpty()) {
1380 final DisplayContent dc = getDisplayContent();
1381 dc.pendingLayoutChanges |= changes;
1382 if (DEBUG_LAYOUT_REPEATS) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001383 mWmService.mWindowPlacerLocked.debugLayoutRepeats(reason, dc.pendingLayoutChanges);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001384 }
1385 }
1386 }
1387
1388 void removeReplacedWindowIfNeeded(WindowState replacement) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001389 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001390 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001391 if (win.removeReplacedWindowIfNeeded(replacement)) {
1392 return;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001393 }
1394 }
1395 }
1396
1397 void startFreezingScreen() {
1398 if (DEBUG_ORIENTATION) logWithStack(TAG, "Set freezing of " + appToken + ": hidden="
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001399 + isHidden() + " freezing=" + mFreezingScreen + " hiddenRequested="
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001400 + hiddenRequested);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001401 if (!hiddenRequested) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001402 if (!mFreezingScreen) {
1403 mFreezingScreen = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001404 mWmService.registerAppFreezeListener(this);
1405 mWmService.mAppsFreezingScreen++;
1406 if (mWmService.mAppsFreezingScreen == 1) {
1407 mWmService.startFreezingDisplayLocked(0, 0, getDisplayContent());
1408 mWmService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
1409 mWmService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001410 }
1411 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001412 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001413 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001414 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001415 w.onStartFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001416 }
1417 }
1418 }
1419
1420 void stopFreezingScreen(boolean unfreezeSurfaceNow, boolean force) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001421 if (!mFreezingScreen) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001422 return;
1423 }
1424 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + this + " force=" + force);
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001425 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001426 boolean unfrozeWindows = false;
1427 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001428 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001429 unfrozeWindows |= w.onStopFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001430 }
1431 if (force || unfrozeWindows) {
1432 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "No longer freezing: " + this);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001433 mFreezingScreen = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001434 mWmService.unregisterAppFreezeListener(this);
1435 mWmService.mAppsFreezingScreen--;
1436 mWmService.mLastFinishedFreezeSource = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001437 }
1438 if (unfreezeSurfaceNow) {
1439 if (unfrozeWindows) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001440 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001441 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001442 mWmService.stopFreezingDisplayLocked();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001443 }
1444 }
1445
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001446 @Override
1447 public void onAppFreezeTimeout() {
1448 Slog.w(TAG_WM, "Force clearing freeze: " + this);
1449 stopFreezingScreen(true, true);
1450 }
1451
Jorim Jaggi60f9c972018-02-01 19:21:07 +01001452 /**
1453 * Tries to transfer the starting window from a token that's above ourselves in the task but
1454 * not visible anymore. This is a common scenario apps use: Trampoline activity T start main
1455 * activity M in the same task. Now, when reopening the task, T starts on top of M but then
1456 * immediately finishes after, so we have to transfer T to M.
1457 */
1458 void transferStartingWindowFromHiddenAboveTokenIfNeeded() {
1459 final Task task = getTask();
1460 for (int i = task.mChildren.size() - 1; i >= 0; i--) {
1461 final AppWindowToken fromToken = task.mChildren.get(i);
1462 if (fromToken == this) {
1463 return;
1464 }
1465 if (fromToken.hiddenRequested && transferStartingWindow(fromToken.token)) {
1466 return;
1467 }
1468 }
1469 }
1470
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001471 boolean transferStartingWindow(IBinder transferFrom) {
Wale Ogunwale02319a62016-09-26 15:21:22 -07001472 final AppWindowToken fromToken = getDisplayContent().getAppWindowToken(transferFrom);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001473 if (fromToken == null) {
1474 return false;
1475 }
1476
1477 final WindowState tStartingWindow = fromToken.startingWindow;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08001478 if (tStartingWindow != null && fromToken.startingSurface != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001479 // In this case, the starting icon has already been displayed, so start
1480 // letting windows get shown immediately without any more transitions.
lumark588a3e82018-07-20 18:53:54 +08001481 getDisplayContent().mSkipAppTransitionAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001482
1483 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Moving existing starting " + tStartingWindow
1484 + " from " + fromToken + " to " + this);
1485
1486 final long origId = Binder.clearCallingIdentity();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001487 try {
1488 // Transfer the starting window over to the new token.
1489 startingData = fromToken.startingData;
1490 startingSurface = fromToken.startingSurface;
1491 startingDisplayed = fromToken.startingDisplayed;
1492 fromToken.startingDisplayed = false;
1493 startingWindow = tStartingWindow;
1494 reportedVisible = fromToken.reportedVisible;
1495 fromToken.startingData = null;
1496 fromToken.startingSurface = null;
1497 fromToken.startingWindow = null;
1498 fromToken.startingMoved = true;
1499 tStartingWindow.mToken = this;
1500 tStartingWindow.mAppToken = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001501
Peter Visontay3556a3b2017-11-01 17:23:17 +00001502 if (DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
1503 "Removing starting " + tStartingWindow + " from " + fromToken);
1504 fromToken.removeChild(tStartingWindow);
1505 fromToken.postWindowRemoveStartingWindowCleanup(tStartingWindow);
1506 fromToken.mHiddenSetFromTransferredStartingWindow = false;
1507 addWindow(tStartingWindow);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001508
Peter Visontay3556a3b2017-11-01 17:23:17 +00001509 // Propagate other interesting state between the tokens. If the old token is displayed,
1510 // we should immediately force the new one to be displayed. If it is animating, we need
1511 // to move that animation to the new one.
1512 if (fromToken.allDrawn) {
1513 allDrawn = true;
1514 deferClearAllDrawn = fromToken.deferClearAllDrawn;
1515 }
1516 if (fromToken.firstWindowDrawn) {
1517 firstWindowDrawn = true;
1518 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001519 if (!fromToken.isHidden()) {
1520 setHidden(false);
Peter Visontay3556a3b2017-11-01 17:23:17 +00001521 hiddenRequested = false;
1522 mHiddenSetFromTransferredStartingWindow = true;
1523 }
1524 setClientHidden(fromToken.mClientHidden);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001525
Jorim Jaggi980c9de2017-11-17 01:41:37 +01001526 transferAnimation(fromToken);
1527
1528 // When transferring an animation, we no longer need to apply an animation to the
1529 // the token we transfer the animation over. Thus, remove the animation from
1530 // pending opening apps.
lumark588a3e82018-07-20 18:53:54 +08001531 getDisplayContent().mOpeningApps.remove(this);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001532
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001533 mWmService.updateFocusedWindowLocked(
Peter Visontay3556a3b2017-11-01 17:23:17 +00001534 UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/);
1535 getDisplayContent().setLayoutNeeded();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001536 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001537 } finally {
1538 Binder.restoreCallingIdentity(origId);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001539 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001540 return true;
1541 } else if (fromToken.startingData != null) {
1542 // The previous app was getting ready to show a
1543 // starting window, but hasn't yet done so. Steal it!
1544 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
1545 "Moving pending starting from " + fromToken + " to " + this);
1546 startingData = fromToken.startingData;
1547 fromToken.startingData = null;
1548 fromToken.startingMoved = true;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001549 scheduleAddStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001550 return true;
1551 }
1552
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001553 // TODO: Transfer thumbnail
1554
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001555 return false;
1556 }
1557
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001558 boolean isLastWindow(WindowState win) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001559 return mChildren.size() == 1 && mChildren.get(0) == win;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001560 }
1561
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001562 @Override
1563 void onAppTransitionDone() {
1564 sendingToBottom = false;
1565 }
1566
Wale Ogunwale51362492016-09-08 17:49:17 -07001567 /**
1568 * We override because this class doesn't want its children affecting its reported orientation
1569 * in anyway.
1570 */
1571 @Override
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001572 int getOrientation(int candidate) {
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001573 if (candidate == SCREEN_ORIENTATION_BEHIND) {
1574 // Allow app to specify orientation regardless of its visibility state if the current
1575 // candidate want us to use orientation behind. I.e. the visible app on-top of this one
1576 // wants us to use the orientation of the app behind it.
1577 return mOrientation;
1578 }
1579
Bryce Lee61fbcbc2017-03-10 14:14:03 -08001580 // The {@link AppWindowToken} should only specify an orientation when it is not closing or
1581 // going to the bottom. Allowing closing {@link AppWindowToken} to participate can lead to
1582 // an Activity in another task being started in the wrong orientation during the transition.
lumark588a3e82018-07-20 18:53:54 +08001583 if (!(sendingToBottom || getDisplayContent().mClosingApps.contains(this))
1584 && (isVisible() || getDisplayContent().mOpeningApps.contains(this))) {
Bryce Leea163b762017-01-24 11:05:01 -08001585 return mOrientation;
Wale Ogunwale51362492016-09-08 17:49:17 -07001586 }
Bryce Leea163b762017-01-24 11:05:01 -08001587
1588 return SCREEN_ORIENTATION_UNSET;
Wale Ogunwale51362492016-09-08 17:49:17 -07001589 }
1590
Wale Ogunwaleb198b742016-12-01 08:44:09 -08001591 /** Returns the app's preferred orientation regardless of its currently visibility state. */
1592 int getOrientationIgnoreVisibility() {
1593 return mOrientation;
1594 }
1595
Riddle Hsub398da32019-01-21 21:48:16 +08001596 /** @return {@code true} if the compatibility bounds is taking effect. */
1597 boolean inSizeCompatMode() {
1598 return mSizeCompatBounds != null;
1599 }
1600
1601 @Override
1602 float getSizeCompatScale() {
1603 return inSizeCompatMode() ? mSizeCompatScale : super.getSizeCompatScale();
1604 }
1605
1606 /**
1607 * @return Non-empty bounds if the activity has override bounds.
1608 * @see ActivityRecord#resolveOverrideConfiguration(Configuration)
1609 */
1610 Rect getResolvedOverrideBounds() {
1611 // Get bounds from resolved override configuration because it is computed with orientation.
1612 return getResolvedOverrideConfiguration().windowConfiguration.getBounds();
1613 }
1614
Craig Mautnerdbb79912012-03-01 18:59:14 -08001615 @Override
Winson Chunge55c0192017-08-24 14:50:48 -07001616 public void onConfigurationChanged(Configuration newParentConfig) {
1617 final int prevWinMode = getWindowingMode();
Evan Rosky2289ba12018-11-19 18:28:18 -08001618 mTmpPrevBounds.set(getBounds());
Winson Chunge55c0192017-08-24 14:50:48 -07001619 super.onConfigurationChanged(newParentConfig);
Riddle Hsub398da32019-01-21 21:48:16 +08001620
1621 final Task task = getTask();
1622 final Rect overrideBounds = getResolvedOverrideBounds();
1623 if (task != null && !overrideBounds.isEmpty()
1624 // If the changes come from change-listener, the incoming parent configuration is
1625 // still the old one. Make sure their orientations are the same to reduce computing
1626 // the compatibility bounds for the intermediate state.
Riddle Hsu04164182019-03-07 18:03:27 +08001627 && (task.mTaskRecord == null || task.mTaskRecord
1628 .getConfiguration().orientation == newParentConfig.orientation)) {
Riddle Hsub398da32019-01-21 21:48:16 +08001629 final Rect taskBounds = task.getBounds();
1630 // Since we only center the activity horizontally, if only the fixed height is smaller
1631 // than its container, the override bounds don't need to take effect.
1632 if ((overrideBounds.width() != taskBounds.width()
1633 || overrideBounds.height() > taskBounds.height())) {
1634 calculateCompatBoundsTransformation(newParentConfig);
1635 updateSurfacePosition();
1636 } else if (mSizeCompatBounds != null) {
1637 mSizeCompatBounds = null;
1638 mSizeCompatScale = 1f;
1639 updateSurfacePosition();
1640 }
1641 }
1642
Winson Chunge55c0192017-08-24 14:50:48 -07001643 final int winMode = getWindowingMode();
1644
1645 if (prevWinMode == winMode) {
1646 return;
1647 }
1648
1649 if (prevWinMode != WINDOWING_MODE_UNDEFINED && winMode == WINDOWING_MODE_PINNED) {
1650 // Entering PiP from fullscreen, reset the snap fraction
1651 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(this);
Winson Chung82267ce2018-04-06 16:38:26 -07001652 } else if (prevWinMode == WINDOWING_MODE_PINNED && winMode != WINDOWING_MODE_UNDEFINED
1653 && !isHidden()) {
Winson Chunge55c0192017-08-24 14:50:48 -07001654 // Leaving PiP to fullscreen, save the snap fraction based on the pre-animation bounds
1655 // for the next re-entry into PiP (assuming the activity is not hidden or destroyed)
1656 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
1657 if (pinnedStack != null) {
Winson Chung8efa1652018-06-06 09:34:23 -07001658 final Rect stackBounds;
1659 if (pinnedStack.lastAnimatingBoundsWasToFullscreen()) {
1660 // We are animating the bounds, use the pre-animation bounds to save the snap
1661 // fraction
1662 stackBounds = pinnedStack.mPreAnimationBounds;
1663 } else {
1664 // We skip the animation if the fullscreen configuration is not compatible, so
1665 // use the current bounds to calculate the saved snap fraction instead
1666 // (see PinnedActivityStack.skipResizeAnimation())
1667 stackBounds = mTmpRect;
1668 pinnedStack.getBounds(stackBounds);
1669 }
Winson Chunge55c0192017-08-24 14:50:48 -07001670 mDisplayContent.mPinnedStackControllerLocked.saveReentrySnapFraction(this,
Winson Chung8efa1652018-06-06 09:34:23 -07001671 stackBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001672 }
Evan Rosky2289ba12018-11-19 18:28:18 -08001673 } else if (shouldStartChangeTransition(prevWinMode, winMode)) {
1674 initializeChangeTransition(mTmpPrevBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001675 }
1676 }
1677
Evan Rosky2289ba12018-11-19 18:28:18 -08001678 private boolean shouldStartChangeTransition(int prevWinMode, int newWinMode) {
Evan Rosky25b56192019-02-06 16:10:56 -08001679 if (mWmService.mDisableTransitionAnimation
1680 || !isVisible()
1681 || getDisplayContent().mAppTransition.isTransitionSet()
1682 || getSurfaceControl() == null) {
Evan Rosky2289ba12018-11-19 18:28:18 -08001683 return false;
1684 }
1685 // Only do an animation into and out-of freeform mode for now. Other mode
1686 // transition animations are currently handled by system-ui.
1687 return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
1688 }
1689
1690 /**
1691 * Initializes a change transition. Because the app is visible already, there is a small period
1692 * of time where the user can see the app content/window update before the transition starts.
1693 * To prevent this, we immediately take a snapshot and place the app/snapshot into a leash which
1694 * "freezes" the location/crop until the transition starts.
1695 * <p>
1696 * Here's a walk-through of the process:
1697 * 1. Create a temporary leash ("interim-change-leash") and reparent the app to it.
1698 * 2. Set the temporary leash's position/crop to the current state.
1699 * 3. Create a snapshot and place that at the top of the leash to cover up content changes.
1700 * 4. Once the transition is ready, it will reparent the app to the animation leash.
1701 * 5. Detach the interim-change-leash.
1702 */
1703 private void initializeChangeTransition(Rect startBounds) {
1704 mDisplayContent.prepareAppTransition(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
1705 false /* alwaysKeepCurrent */, 0, false /* forceOverride */);
1706 mDisplayContent.mChangingApps.add(this);
1707 mTransitStartRect.set(startBounds);
1708
1709 final SurfaceControl.Builder builder = makeAnimationLeash()
1710 .setParent(getAnimationLeashParent())
1711 .setName(getSurfaceControl() + " - interim-change-leash");
1712 mTransitChangeLeash = builder.build();
1713 Transaction t = getPendingTransaction();
1714 t.setWindowCrop(mTransitChangeLeash, startBounds.width(), startBounds.height());
1715 t.setPosition(mTransitChangeLeash, startBounds.left, startBounds.top);
1716 t.show(mTransitChangeLeash);
1717 t.reparent(getSurfaceControl(), mTransitChangeLeash);
1718 onAnimationLeashCreated(t, mTransitChangeLeash);
1719
Evan Rosky966759f2019-01-15 10:33:58 -08001720 // Skip creating snapshot if this transition is controlled by a remote animator which
1721 // doesn't need it.
1722 ArraySet<Integer> activityTypes = new ArraySet<>();
1723 activityTypes.add(getActivityType());
1724 RemoteAnimationAdapter adapter =
1725 mDisplayContent.mAppTransitionController.getRemoteAnimationOverride(
1726 this, TRANSIT_TASK_CHANGE_WINDOWING_MODE, activityTypes);
1727 if (adapter != null && !adapter.getChangeNeedsSnapshot()) {
1728 return;
1729 }
1730
Evan Rosky2289ba12018-11-19 18:28:18 -08001731 if (mThumbnail == null && getTask() != null) {
1732 final TaskSnapshotController snapshotCtrl = mWmService.mTaskSnapshotController;
1733 final ArraySet<Task> tasks = new ArraySet<>();
1734 tasks.add(getTask());
1735 snapshotCtrl.snapshotTasks(tasks);
1736 snapshotCtrl.addSkipClosingAppSnapshotTasks(tasks);
1737 final ActivityManager.TaskSnapshot snapshot = snapshotCtrl.getSnapshot(
1738 getTask().mTaskId, getTask().mUserId, false /* restoreFromDisk */,
1739 false /* reducedResolution */);
Yunfan Chendcb1fcf2019-02-07 19:08:41 +09001740 if (snapshot != null) {
1741 mThumbnail = new AppWindowThumbnail(t, this, snapshot.getSnapshot(),
1742 true /* relative */);
1743 }
Evan Rosky2289ba12018-11-19 18:28:18 -08001744 }
1745 }
1746
1747 boolean isInChangeTransition() {
Evan Roskyec9488c2019-03-01 19:32:12 -08001748 return mTransitChangeLeash != null || AppTransition.isChangeTransit(mTransit);
Evan Rosky2289ba12018-11-19 18:28:18 -08001749 }
1750
Evan Rosky966759f2019-01-15 10:33:58 -08001751 @VisibleForTesting
1752 AppWindowThumbnail getThumbnail() {
1753 return mThumbnail;
1754 }
1755
Riddle Hsub398da32019-01-21 21:48:16 +08001756 /**
1757 * Calculates the scale and offset to horizontal center the size compatibility bounds into the
1758 * region which is available to application.
1759 */
1760 private void calculateCompatBoundsTransformation(Configuration newParentConfig) {
1761 final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds();
Riddle Hsu74826262019-04-17 14:57:42 +08001762 final Rect parentBounds = newParentConfig.windowConfiguration.getBounds();
1763 final Rect viewportBounds = parentAppBounds != null ? parentAppBounds : parentBounds;
Riddle Hsu04164182019-03-07 18:03:27 +08001764 final Rect appBounds = getWindowConfiguration().getAppBounds();
1765 final Rect contentBounds = appBounds != null ? appBounds : getResolvedOverrideBounds();
Riddle Hsub398da32019-01-21 21:48:16 +08001766 final float contentW = contentBounds.width();
1767 final float contentH = contentBounds.height();
1768 final float viewportW = viewportBounds.width();
1769 final float viewportH = viewportBounds.height();
1770 // Only allow to scale down.
1771 mSizeCompatScale = (contentW <= viewportW && contentH <= viewportH)
1772 ? 1 : Math.min(viewportW / contentW, viewportH / contentH);
1773 final int offsetX = (int) ((viewportW - contentW * mSizeCompatScale + 1) * 0.5f)
1774 + viewportBounds.left;
1775
1776 if (mSizeCompatBounds == null) {
1777 mSizeCompatBounds = new Rect();
1778 }
1779 mSizeCompatBounds.set(contentBounds);
1780 mSizeCompatBounds.offsetTo(0, 0);
1781 mSizeCompatBounds.scale(mSizeCompatScale);
Riddle Hsu74826262019-04-17 14:57:42 +08001782 // Ensure to align the top with the parent.
1783 mSizeCompatBounds.top = parentBounds.top;
Riddle Hsu04164182019-03-07 18:03:27 +08001784 // The decor inset is included in height.
1785 mSizeCompatBounds.bottom += viewportBounds.top;
Riddle Hsub398da32019-01-21 21:48:16 +08001786 mSizeCompatBounds.left += offsetX;
1787 mSizeCompatBounds.right += offsetX;
1788 }
1789
1790 @Override
1791 public Rect getBounds() {
1792 if (mSizeCompatBounds != null) {
1793 return mSizeCompatBounds;
1794 }
1795 return super.getBounds();
1796 }
1797
1798 @Override
1799 public boolean matchParentBounds() {
1800 if (super.matchParentBounds()) {
1801 return true;
1802 }
1803 // An activity in size compatibility mode may have override bounds which equals to its
1804 // parent bounds, so the exact bounds should also be checked.
1805 final WindowContainer parent = getParent();
1806 return parent == null || parent.getBounds().equals(getResolvedOverrideBounds());
1807 }
1808
Winson Chunge55c0192017-08-24 14:50:48 -07001809 @Override
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001810 void checkAppWindowsReadyToShow() {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001811 if (allDrawn == mLastAllDrawn) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001812 return;
1813 }
1814
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001815 mLastAllDrawn = allDrawn;
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001816 if (!allDrawn) {
1817 return;
1818 }
1819
1820 // The token has now changed state to having all windows shown... what to do, what to do?
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001821 if (mFreezingScreen) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001822 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001823 stopFreezingScreen(false, true);
1824 if (DEBUG_ORIENTATION) Slog.i(TAG,
1825 "Setting mOrientationChangeComplete=true because wtoken " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001826 + " numInteresting=" + mNumInterestingWindows + " numDrawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001827 // This will set mOrientationChangeComplete and cause a pass through layout.
1828 setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001829 "checkAppWindowsReadyToShow: freezingScreen");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001830 } else {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001831 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001832
1833 // We can now show all of the drawn windows!
lumark588a3e82018-07-20 18:53:54 +08001834 if (!getDisplayContent().mOpeningApps.contains(this) && canShowWindows()) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001835 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001836 }
1837 }
1838 }
1839
Matthew Ng5d23afa2017-06-21 16:16:24 -07001840 /**
Bryce Leed390deb2017-06-22 13:14:28 -07001841 * Returns whether the drawn window states of this {@link AppWindowToken} has considered every
1842 * child {@link WindowState}. A child is considered if it has been passed into
1843 * {@link #updateDrawnWindowStates(WindowState)} after being added. This is used to determine
1844 * whether states, such as {@code allDrawn}, can be set, which relies on state variables such as
1845 * {@code mNumInterestingWindows}, which depend on all {@link WindowState}s being considered.
1846 *
1847 * @return {@code true} If all children have been considered, {@code false}.
1848 */
1849 private boolean allDrawnStatesConsidered() {
Bryce Lee6311c4b2017-07-06 14:09:29 -07001850 for (int i = mChildren.size() - 1; i >= 0; --i) {
1851 final WindowState child = mChildren.get(i);
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001852 if (child.mightAffectAllDrawn() && !child.getDrawnStateEvaluated()) {
Bryce Leed390deb2017-06-22 13:14:28 -07001853 return false;
1854 }
1855 }
1856 return true;
1857 }
1858
1859 /**
Matthew Ng5d23afa2017-06-21 16:16:24 -07001860 * Determines if the token has finished drawing. This should only be called from
1861 * {@link DisplayContent#applySurfaceChangesTransaction}
1862 */
Matthew Ng498c71d2017-04-18 13:55:45 -07001863 void updateAllDrawn() {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001864 if (!allDrawn) {
Matthew Ng498c71d2017-04-18 13:55:45 -07001865 // Number of drawn windows can be less when a window is being relaunched, wait for
Bryce Leed390deb2017-06-22 13:14:28 -07001866 // all windows to be launched and drawn for this token be considered all drawn.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001867 final int numInteresting = mNumInterestingWindows;
Bryce Leed390deb2017-06-22 13:14:28 -07001868
1869 // We must make sure that all present children have been considered (determined by
1870 // {@link #allDrawnStatesConsidered}) before evaluating whether everything has been
1871 // drawn.
1872 if (numInteresting > 0 && allDrawnStatesConsidered()
1873 && mNumDrawnWindows >= numInteresting && !isRelaunching()) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001874 if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawn: " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001875 + " interesting=" + numInteresting + " drawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001876 allDrawn = true;
1877 // Force an additional layout pass where
1878 // WindowStateAnimator#commitFinishDrawingLocked() will call performShowLocked().
Matthew Ng498c71d2017-04-18 13:55:45 -07001879 if (mDisplayContent != null) {
1880 mDisplayContent.setLayoutNeeded();
1881 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001882 mWmService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
Robert Carrecc06b32017-04-18 14:25:10 -07001883
Winson Chunge7ba6862017-05-24 12:13:33 -07001884 // Notify the pinned stack upon all windows drawn. If there was an animation in
1885 // progress then this signal will resume that animation.
Wale Ogunwale61911492017-10-11 08:50:50 -07001886 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
Winson Chunge7ba6862017-05-24 12:13:33 -07001887 if (pinnedStack != null) {
1888 pinnedStack.onAllWindowsDrawn();
Robert Carrecc06b32017-04-18 14:25:10 -07001889 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001890 }
1891 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001892 }
1893
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001894 boolean keyDispatchingTimedOut(String reason, int windowPid) {
1895 return mActivityRecord != null && mActivityRecord.keyDispatchingTimedOut(reason, windowPid);
1896 }
1897
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001898 /**
1899 * Updated this app token tracking states for interesting and drawn windows based on the window.
1900 *
1901 * @return Returns true if the input window is considered interesting and drawn while all the
1902 * windows in this app token where not considered drawn as of the last pass.
1903 */
1904 boolean updateDrawnWindowStates(WindowState w) {
Bryce Leed390deb2017-06-22 13:14:28 -07001905 w.setDrawnStateEvaluated(true /*evaluated*/);
1906
Jorim Jaggie4b0f282017-05-17 15:10:29 +02001907 if (DEBUG_STARTING_WINDOW_VERBOSE && w == startingWindow) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001908 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + w.isOnScreen()
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001909 + " allDrawn=" + allDrawn + " freezingScreen=" + mFreezingScreen);
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001910 }
1911
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001912 if (allDrawn && !mFreezingScreen) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001913 return false;
1914 }
1915
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001916 if (mLastTransactionSequence != mWmService.mTransactionSequence) {
1917 mLastTransactionSequence = mWmService.mTransactionSequence;
Matthew Ng53e66b22018-01-12 17:13:13 -08001918 mNumDrawnWindows = 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001919 startingDisplayed = false;
Matthew Ng53e66b22018-01-12 17:13:13 -08001920
1921 // There is the main base application window, even if it is exiting, wait for it
1922 mNumInterestingWindows = findMainWindow(false /* includeStartingApp */) != null ? 1 : 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001923 }
1924
1925 final WindowStateAnimator winAnimator = w.mWinAnimator;
1926
1927 boolean isInterestingAndDrawn = false;
1928
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001929 if (!allDrawn && w.mightAffectAllDrawn()) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001930 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
1931 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001932 + ", isAnimationSet=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001933 if (!w.isDrawnLw()) {
1934 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController
1935 + " pv=" + w.mPolicyVisibility
1936 + " mDrawState=" + winAnimator.drawStateToString()
1937 + " ph=" + w.isParentWindowHidden() + " th=" + hiddenRequested
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001938 + " a=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001939 }
1940 }
1941
1942 if (w != startingWindow) {
1943 if (w.isInteresting()) {
Matthew Ng53e66b22018-01-12 17:13:13 -08001944 // Add non-main window as interesting since the main app has already been added
1945 if (findMainWindow(false /* includeStartingApp */) != w) {
1946 mNumInterestingWindows++;
1947 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001948 if (w.isDrawnLw()) {
1949 mNumDrawnWindows++;
1950
1951 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, "tokenMayBeDrawn: "
1952 + this + " w=" + w + " numInteresting=" + mNumInterestingWindows
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001953 + " freezingScreen=" + mFreezingScreen
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001954 + " mAppFreezing=" + w.mAppFreezing);
1955
1956 isInterestingAndDrawn = true;
1957 }
1958 }
1959 } else if (w.isDrawnLw()) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001960 if (mActivityRecord != null) {
1961 mActivityRecord.onStartingWindowDrawn(SystemClock.uptimeMillis());
Jorim Jaggi3878ca32017-02-02 17:13:05 -08001962 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001963 startingDisplayed = true;
1964 }
1965 }
1966
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001967 return isInterestingAndDrawn;
1968 }
1969
Adrian Roos23df3a32018-03-15 15:41:13 +01001970 void layoutLetterbox(WindowState winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001971 final WindowState w = findMainWindow();
Adrian Roosf93b6d22018-03-21 13:48:26 +01001972 if (w == null || winHint != null && w != winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001973 return;
1974 }
Jorim Jaggia32da382018-03-28 18:01:22 +02001975 final boolean surfaceReady = w.isDrawnLw() // Regular case
Adrian Roosf93b6d22018-03-21 13:48:26 +01001976 || w.mWinAnimator.mSurfaceDestroyDeferred // The preserved surface is still ready.
1977 || w.isDragResizeChanged(); // Waiting for relayoutWindow to call preserveSurface.
Jorim Jaggi4981f152019-03-26 18:58:45 +01001978 final boolean needsLetterbox = surfaceReady && w.isLetterboxedAppWindow() && fillsParent();
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001979 if (needsLetterbox) {
1980 if (mLetterbox == null) {
1981 mLetterbox = new Letterbox(() -> makeChildSurface(null));
Riddle Hsu192fe762019-01-15 23:41:57 +08001982 mLetterbox.attachInput(w);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001983 }
Adrian Roos7af9d972018-11-30 15:26:27 +01001984 getPosition(mTmpPoint);
Evan Rosky67c15642019-04-24 13:17:28 -07001985 // Get the bounds of the "space-to-fill". In multi-window mode, the task-level
1986 // represents this. In fullscreen-mode, the stack does (since the orientation letterbox
1987 // is also applied to the task).
1988 Rect spaceToFill = (inMultiWindowMode() || getStack() == null)
1989 ? getTask().getDisplayedBounds() : getStack().getDisplayedBounds();
Evan Rosky4fb1e912019-03-06 13:54:43 -08001990 mLetterbox.layout(spaceToFill, w.getFrameLw(), mTmpPoint);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001991 } else if (mLetterbox != null) {
Adrian Roos23df3a32018-03-15 15:41:13 +01001992 mLetterbox.hide();
1993 }
1994 }
1995
1996 void updateLetterboxSurface(WindowState winHint) {
1997 final WindowState w = findMainWindow();
1998 if (w != winHint && winHint != null && w != null) {
1999 return;
2000 }
2001 layoutLetterbox(winHint);
2002 if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) {
2003 mLetterbox.applySurfaceChanges(mPendingTransaction);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002004 }
2005 }
2006
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07002007 @Override
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002008 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002009 // For legacy reasons we process the TaskStack.mExitingAppTokens first in DisplayContent
2010 // before the non-exiting app tokens. So, we skip the exiting app tokens here.
2011 // TODO: Investigate if we need to continue to do this or if we can just process them
2012 // in-order.
2013 if (mIsExiting && !waitingForReplacement()) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002014 return false;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002015 }
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002016 return forAllWindowsUnchecked(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002017 }
2018
lumark588a3e82018-07-20 18:53:54 +08002019 @Override
2020 void forAllAppWindows(Consumer<AppWindowToken> callback) {
2021 callback.accept(this);
2022 }
2023
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002024 boolean forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback,
2025 boolean traverseTopToBottom) {
2026 return super.forAllWindows(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002027 }
2028
2029 @Override
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002030 AppWindowToken asAppWindowToken() {
2031 // I am an app window token!
2032 return this;
2033 }
2034
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002035 boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
2036 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
2037 IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
2038 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
2039 // If the display is frozen, we won't do anything until the actual window is
2040 // displayed so there is no reason to put in the starting window.
2041 if (!okToDisplay()) {
2042 return false;
2043 }
2044
2045 if (startingData != null) {
2046 return false;
2047 }
2048
2049 final WindowState mainWin = findMainWindow();
2050 if (mainWin != null && mainWin.mWinAnimator.getShown()) {
2051 // App already has a visible window...why would you want a starting window?
2052 return false;
2053 }
2054
2055 final ActivityManager.TaskSnapshot snapshot =
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002056 mWmService.mTaskSnapshotController.getSnapshot(
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002057 getTask().mTaskId, getTask().mUserId,
2058 false /* restoreFromDisk */, false /* reducedResolution */);
2059 final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
2060 allowTaskSnapshot, activityCreated, fromRecents, snapshot);
2061
2062 if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
2063 return createSnapshot(snapshot);
2064 }
2065
2066 // If this is a translucent window, then don't show a starting window -- the current
2067 // effect (a full-screen opaque starting window that fades away to the real contents
2068 // when it is ready) does not work for this.
2069 if (DEBUG_STARTING_WINDOW) {
2070 Slog.v(TAG, "Checking theme of starting window: 0x" + Integer.toHexString(theme));
2071 }
2072 if (theme != 0) {
2073 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
2074 com.android.internal.R.styleable.Window,
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002075 mWmService.mCurrentUserId);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002076 if (ent == null) {
2077 // Whoops! App doesn't exist. Um. Okay. We'll just pretend like we didn't
2078 // see that.
2079 return false;
2080 }
2081 final boolean windowIsTranslucent = ent.array.getBoolean(
2082 com.android.internal.R.styleable.Window_windowIsTranslucent, false);
2083 final boolean windowIsFloating = ent.array.getBoolean(
2084 com.android.internal.R.styleable.Window_windowIsFloating, false);
2085 final boolean windowShowWallpaper = ent.array.getBoolean(
2086 com.android.internal.R.styleable.Window_windowShowWallpaper, false);
2087 final boolean windowDisableStarting = ent.array.getBoolean(
2088 com.android.internal.R.styleable.Window_windowDisablePreview, false);
2089 if (DEBUG_STARTING_WINDOW) {
2090 Slog.v(TAG, "Translucent=" + windowIsTranslucent
2091 + " Floating=" + windowIsFloating
2092 + " ShowWallpaper=" + windowShowWallpaper);
2093 }
2094 if (windowIsTranslucent) {
2095 return false;
2096 }
2097 if (windowIsFloating || windowDisableStarting) {
2098 return false;
2099 }
2100 if (windowShowWallpaper) {
2101 if (getDisplayContent().mWallpaperController
2102 .getWallpaperTarget() == null) {
2103 // If this theme is requesting a wallpaper, and the wallpaper
2104 // is not currently visible, then this effectively serves as
2105 // an opaque window and our starting window transition animation
2106 // can still work. We just need to make sure the starting window
2107 // is also showing the wallpaper.
2108 windowFlags |= FLAG_SHOW_WALLPAPER;
2109 } else {
2110 return false;
2111 }
2112 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002113 }
Yunfan Chen8a8c0ed2018-12-18 16:46:32 -08002114
2115 if (transferStartingWindow(transferFrom)) {
2116 return true;
2117 }
2118
2119 // There is no existing starting window, and we don't want to create a splash screen, so
2120 // that's it!
2121 if (type != STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
2122 return false;
2123 }
2124
2125 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SplashScreenStartingData");
2126 startingData = new SplashScreenStartingData(mWmService, pkg,
2127 theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
2128 getMergedOverrideConfiguration());
2129 scheduleAddStartingWindow();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002130 return true;
2131 }
2132
2133
2134 private boolean createSnapshot(ActivityManager.TaskSnapshot snapshot) {
2135 if (snapshot == null) {
2136 return false;
2137 }
2138
2139 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SnapshotStartingData");
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002140 startingData = new SnapshotStartingData(mWmService, snapshot);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002141 scheduleAddStartingWindow();
2142 return true;
2143 }
2144
2145 void scheduleAddStartingWindow() {
2146 // Note: we really want to do sendMessageAtFrontOfQueue() because we
2147 // want to process the message ASAP, before any other queued
2148 // messages.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002149 if (!mWmService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002150 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING");
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002151 mWmService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002152 }
2153 }
2154
2155 private final Runnable mAddStartingWindow = new Runnable() {
2156
2157 @Override
2158 public void run() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002159 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002160 // There can only be one adding request, silly caller!
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002161 mWmService.mAnimationHandler.removeCallbacks(this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002162 }
2163
2164 if (startingData == null) {
2165 // Animation has been canceled... do nothing.
2166 if (DEBUG_STARTING_WINDOW) {
2167 Slog.v(TAG, "startingData was nulled out before handling"
2168 + " mAddStartingWindow: " + AppWindowToken.this);
2169 }
2170 return;
2171 }
2172
2173 if (DEBUG_STARTING_WINDOW) {
2174 Slog.v(TAG, "Add starting " + this + ": startingData=" + startingData);
2175 }
2176
2177 WindowManagerPolicy.StartingSurface surface = null;
2178 try {
2179 surface = startingData.createStartingSurface(AppWindowToken.this);
2180 } catch (Exception e) {
2181 Slog.w(TAG, "Exception when adding starting window", e);
2182 }
2183 if (surface != null) {
2184 boolean abort = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002185 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002186 // If the window was successfully added, then
2187 // we need to remove it.
2188 if (removed || startingData == null) {
2189 if (DEBUG_STARTING_WINDOW) {
2190 Slog.v(TAG, "Aborted starting " + AppWindowToken.this
2191 + ": removed=" + removed + " startingData=" + startingData);
2192 }
2193 startingWindow = null;
2194 startingData = null;
2195 abort = true;
2196 } else {
2197 startingSurface = surface;
2198 }
2199 if (DEBUG_STARTING_WINDOW && !abort) {
2200 Slog.v(TAG, "Added starting " + AppWindowToken.this + ": startingWindow="
2201 + startingWindow + " startingView=" + startingSurface);
2202 }
2203 }
2204 if (abort) {
2205 surface.remove();
2206 }
2207 } else if (DEBUG_STARTING_WINDOW) {
2208 Slog.v(TAG, "Surface returned was null: " + AppWindowToken.this);
2209 }
2210 }
2211 };
2212
2213 private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
2214 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents,
2215 ActivityManager.TaskSnapshot snapshot) {
2216 if (getDisplayContent().mAppTransition.getAppTransition()
2217 == TRANSIT_DOCK_TASK_FROM_RECENTS) {
2218 // TODO(b/34099271): Remove this statement to add back the starting window and figure
2219 // out why it causes flickering, the starting window appears over the thumbnail while
2220 // the docked from recents transition occurs
2221 return STARTING_WINDOW_TYPE_NONE;
2222 } else if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
2223 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2224 } else if (taskSwitch && allowTaskSnapshot) {
Kevin716a9db2018-12-18 16:53:39 -08002225 if (mWmService.mLowRamTaskSnapshotsAndRecents) {
Kevin58b47f12018-12-17 14:09:01 -08002226 // For low RAM devices, we use the splash screen starting window instead of the
2227 // task snapshot starting window.
2228 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2229 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002230 return snapshot == null ? STARTING_WINDOW_TYPE_NONE
2231 : snapshotOrientationSameAsTask(snapshot) || fromRecents
2232 ? STARTING_WINDOW_TYPE_SNAPSHOT : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2233 } else {
2234 return STARTING_WINDOW_TYPE_NONE;
2235 }
2236 }
2237
2238
2239 private boolean snapshotOrientationSameAsTask(ActivityManager.TaskSnapshot snapshot) {
2240 if (snapshot == null) {
2241 return false;
2242 }
2243 return getTask().getConfiguration().orientation == snapshot.getOrientation();
2244 }
2245
2246 void removeStartingWindow() {
2247 if (startingWindow == null) {
2248 if (startingData != null) {
2249 // Starting window has not been added yet, but it is scheduled to be added.
2250 // Go ahead and cancel the request.
2251 if (DEBUG_STARTING_WINDOW) {
2252 Slog.v(TAG_WM, "Clearing startingData for token=" + this);
2253 }
2254 startingData = null;
2255 }
2256 return;
2257 }
2258
2259 final WindowManagerPolicy.StartingSurface surface;
2260 if (startingData != null) {
2261 surface = startingSurface;
2262 startingData = null;
2263 startingSurface = null;
2264 startingWindow = null;
2265 startingDisplayed = false;
2266 if (surface == null) {
2267 if (DEBUG_STARTING_WINDOW) {
2268 Slog.v(TAG_WM, "startingWindow was set but startingSurface==null, couldn't "
2269 + "remove");
2270 }
2271 return;
2272 }
2273 } else {
2274 if (DEBUG_STARTING_WINDOW) {
2275 Slog.v(TAG_WM, "Tried to remove starting window but startingWindow was null:"
2276 + this);
2277 }
2278 return;
2279 }
2280
2281 if (DEBUG_STARTING_WINDOW) {
2282 Slog.v(TAG_WM, "Schedule remove starting " + this
2283 + " startingWindow=" + startingWindow
2284 + " startingView=" + startingSurface
2285 + " Callers=" + Debug.getCallers(5));
2286 }
2287
2288 // Use the same thread to remove the window as we used to add it, as otherwise we end up
2289 // with things in the view hierarchy being called from different threads.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002290 mWmService.mAnimationHandler.post(() -> {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002291 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Removing startingView=" + surface);
2292 try {
2293 surface.remove();
2294 } catch (Exception e) {
2295 Slog.w(TAG_WM, "Exception when removing starting window", e);
2296 }
2297 });
2298 }
2299
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002300 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -07002301 boolean fillsParent() {
2302 return mFillsParent;
2303 }
2304
2305 void setFillsParent(boolean fillsParent) {
2306 mFillsParent = fillsParent;
2307 }
2308
Jorim Jaggife762342016-10-13 14:33:27 +02002309 boolean containsDismissKeyguardWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002310 // Window state is transient during relaunch. We are not guaranteed to be frozen during the
2311 // entirety of the relaunch.
2312 if (isRelaunching()) {
2313 return mLastContainsDismissKeyguardWindow;
2314 }
2315
Jorim Jaggife762342016-10-13 14:33:27 +02002316 for (int i = mChildren.size() - 1; i >= 0; i--) {
2317 if ((mChildren.get(i).mAttrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
2318 return true;
2319 }
2320 }
2321 return false;
2322 }
2323
2324 boolean containsShowWhenLockedWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002325 // When we are relaunching, it is possible for us to be unfrozen before our previous
2326 // windows have been added back. Using the cached value ensures that our previous
2327 // showWhenLocked preference is honored until relaunching is complete.
2328 if (isRelaunching()) {
2329 return mLastContainsShowWhenLockedWindow;
2330 }
2331
Jorim Jaggife762342016-10-13 14:33:27 +02002332 for (int i = mChildren.size() - 1; i >= 0; i--) {
2333 if ((mChildren.get(i).mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
2334 return true;
2335 }
2336 }
Bryce Lee081554b2017-05-25 07:52:12 -07002337
Jorim Jaggife762342016-10-13 14:33:27 +02002338 return false;
2339 }
2340
2341 void checkKeyguardFlagsChanged() {
2342 final boolean containsDismissKeyguard = containsDismissKeyguardWindow();
2343 final boolean containsShowWhenLocked = containsShowWhenLockedWindow();
2344 if (containsDismissKeyguard != mLastContainsDismissKeyguardWindow
2345 || containsShowWhenLocked != mLastContainsShowWhenLockedWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002346 mWmService.notifyKeyguardFlagsChanged(null /* callback */,
lumark588a3e82018-07-20 18:53:54 +08002347 getDisplayContent().getDisplayId());
Jorim Jaggife762342016-10-13 14:33:27 +02002348 }
2349 mLastContainsDismissKeyguardWindow = containsDismissKeyguard;
2350 mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
2351 }
2352
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002353 WindowState getImeTargetBelowWindow(WindowState w) {
2354 final int index = mChildren.indexOf(w);
2355 if (index > 0) {
2356 final WindowState target = mChildren.get(index - 1);
2357 if (target.canBeImeTarget()) {
2358 return target;
2359 }
2360 }
2361 return null;
2362 }
2363
2364 WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
2365 WindowState candidate = null;
2366 for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
2367 final WindowState w = mChildren.get(i);
2368 if (w.mRemoved) {
2369 continue;
2370 }
Jorim Jaggi35d328a2018-08-14 17:00:20 +02002371 if (candidate == null) {
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002372 candidate = w;
2373 }
2374 }
2375 return candidate;
2376 }
2377
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002378 /**
2379 * See {@link Activity#setDisablePreviewScreenshots}.
2380 */
2381 void setDisablePreviewScreenshots(boolean disable) {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002382 mDisablePreviewScreenshots = disable;
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002383 }
2384
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002385 /**
chaviwd3bf08d2017-08-01 17:24:59 -07002386 * Sets whether the current launch can turn the screen on. See {@link #canTurnScreenOn()}
2387 */
2388 void setCanTurnScreenOn(boolean canTurnScreenOn) {
2389 mCanTurnScreenOn = canTurnScreenOn;
2390 }
2391
2392 /**
2393 * Indicates whether the current launch can turn the screen on. This is to prevent multiple
2394 * relayouts from turning the screen back on. The screen should only turn on at most
2395 * once per activity resume.
2396 *
2397 * @return true if the screen can be turned on.
2398 */
2399 boolean canTurnScreenOn() {
2400 return mCanTurnScreenOn;
2401 }
2402
2403 /**
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002404 * Retrieves whether we'd like to generate a snapshot that's based solely on the theme. This is
2405 * the case when preview screenshots are disabled {@link #setDisablePreviewScreenshots} or when
2406 * we can't take a snapshot for other reasons, for example, if we have a secure window.
2407 *
2408 * @return True if we need to generate an app theme snapshot, false if we'd like to take a real
2409 * screenshot.
2410 */
2411 boolean shouldUseAppThemeSnapshot() {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002412 return mDisablePreviewScreenshots || forAllWindows(w -> (w.mAttrs.flags & FLAG_SECURE) != 0,
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002413 true /* topToBottom */);
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002414 }
2415
Jorim Jaggibe418292018-03-26 16:14:12 +02002416 SurfaceControl getAppAnimationLayer() {
Jorim Jaggi391790622018-04-18 15:30:44 +02002417 return getAppAnimationLayer(isActivityTypeHome() ? ANIMATION_LAYER_HOME
2418 : needsZBoost() ? ANIMATION_LAYER_BOOSTED
2419 : ANIMATION_LAYER_STANDARD);
Jorim Jaggibe418292018-03-26 16:14:12 +02002420 }
2421
chaviw23ee71c2017-12-18 11:29:41 -08002422 @Override
Jorim Jaggi596a1992017-12-29 14:48:02 +01002423 public SurfaceControl getAnimationLeashParent() {
Robert Carrb9506032018-02-13 13:54:00 -08002424 // All normal app transitions take place in an animation layer which is below the pinned
2425 // stack but may be above the parent stacks of the given animating apps.
2426 // For transitions in the pinned stack (menu activity) we just let them occur as a child
2427 // of the pinned stack.
2428 if (!inPinnedWindowingMode()) {
2429 return getAppAnimationLayer();
2430 } else {
2431 return getStack().getSurfaceControl();
2432 }
chaviw23ee71c2017-12-18 11:29:41 -08002433 }
2434
lumarkb5a78b32019-04-25 20:31:30 +08002435
2436 @VisibleForTesting
2437 boolean shouldAnimate(int transit) {
Jorim Jaggic6976f02018-04-18 16:31:07 +02002438 final boolean isSplitScreenPrimary =
2439 getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
2440 final boolean allowSplitScreenPrimaryAnimation = transit != TRANSIT_WALLPAPER_OPEN;
2441
lumarkb5a78b32019-04-25 20:31:30 +08002442 // Don't animate while the task runs recents animation but only if we are in the mode
2443 // where we cancel with deferred screenshot, which means that the controller has
2444 // transformed the task.
lumark54284462019-03-05 20:44:27 +08002445 final RecentsAnimationController controller = mWmService.getRecentsAnimationController();
lumarkb5a78b32019-04-25 20:31:30 +08002446 if (controller != null && controller.isAnimatingTask(getTask())
2447 && controller.shouldCancelWithDeferredScreenshot()) {
lumark54284462019-03-05 20:44:27 +08002448 return false;
2449 }
2450
Jorim Jaggic6976f02018-04-18 16:31:07 +02002451 // We animate always if it's not split screen primary, and only some special cases in split
2452 // screen primary because it causes issues with stack clipping when we run an un-minimize
2453 // animation at the same time.
2454 return !isSplitScreenPrimary || allowSplitScreenPrimaryAnimation;
2455 }
2456
Vishnu Naira2977262018-07-26 13:31:26 -07002457 /**
2458 * Creates a layer to apply crop to an animation.
2459 */
2460 private SurfaceControl createAnimationBoundsLayer(Transaction t) {
2461 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.i(TAG, "Creating animation bounds layer");
2462 final SurfaceControl.Builder builder = makeAnimationLeash()
2463 .setParent(getAnimationLeashParent())
Vishnu Naire86bd982018-11-28 13:23:17 -08002464 .setName(getSurfaceControl() + " - animation-bounds");
Vishnu Naira2977262018-07-26 13:31:26 -07002465 final SurfaceControl boundsLayer = builder.build();
2466 t.show(boundsLayer);
2467 return boundsLayer;
2468 }
2469
Evan Roskyed6767f2018-10-26 17:21:06 -07002470 @Override
2471 Rect getDisplayedBounds() {
2472 final Task task = getTask();
2473 if (task != null) {
2474 final Rect overrideDisplayedBounds = task.getOverrideDisplayedBounds();
2475 if (!overrideDisplayedBounds.isEmpty()) {
2476 return overrideDisplayedBounds;
2477 }
2478 }
2479 return getBounds();
2480 }
2481
Evan Rosky641daea2019-04-24 14:45:24 -07002482 @VisibleForTesting
2483 Rect getAnimationBounds(int appStackClipMode) {
2484 if (appStackClipMode == STACK_CLIP_BEFORE_ANIM && getStack() != null) {
2485 // Using the stack bounds here effectively applies the clipping before animation.
2486 return getStack().getBounds();
2487 }
2488 // Use task-bounds if available so that activity-level letterbox (maxAspectRatio) is
2489 // included in the animation.
2490 return getTask() != null ? getTask().getBounds() : getBounds();
2491 }
2492
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002493 boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter,
2494 boolean isVoiceInteraction) {
2495
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002496 if (mWmService.mDisableTransitionAnimation || !shouldAnimate(transit)) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002497 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
Jorim Jaggic6976f02018-04-18 16:31:07 +02002498 Slog.v(TAG_WM, "applyAnimation: transition animation is disabled or skipped."
2499 + " atoken=" + this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002500 }
2501 cancelAnimation();
2502 return false;
2503 }
2504
2505 // Only apply an animation if the display isn't frozen. If it is frozen, there is no reason
2506 // to animate and it can cause strange artifacts when we unfreeze the display if some
2507 // different animation is running.
2508 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#applyAnimationLocked");
2509 if (okToAnimate()) {
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002510 final AnimationAdapter adapter;
Evan Rosky2289ba12018-11-19 18:28:18 -08002511 AnimationAdapter thumbnailAdapter = null;
Evan Rosky4fb1e912019-03-06 13:54:43 -08002512
Evan Rosky641daea2019-04-24 14:45:24 -07002513 final int appStackClipMode =
2514 getDisplayContent().mAppTransition.getAppStackClipMode();
2515
2516 // Separate position and size for use in animators.
2517 mTmpRect.set(getAnimationBounds(appStackClipMode));
Evan Rosky4fb1e912019-03-06 13:54:43 -08002518 mTmpPoint.set(mTmpRect.left, mTmpRect.top);
2519 mTmpRect.offsetTo(0, 0);
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002520
Evan Roskyec9488c2019-03-01 19:32:12 -08002521 final boolean isChanging = AppTransition.isChangeTransit(transit) && enter
2522 && getDisplayContent().mChangingApps.contains(this);
Evan Rosky2289ba12018-11-19 18:28:18 -08002523
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002524 // Delaying animation start isn't compatible with remote animations at all.
lumark588a3e82018-07-20 18:53:54 +08002525 if (getDisplayContent().mAppTransition.getRemoteAnimationController() != null
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002526 && !mSurfaceAnimator.isAnimationStartDelayed()) {
Evan Rosky2289ba12018-11-19 18:28:18 -08002527 RemoteAnimationRecord adapters =
2528 getDisplayContent().mAppTransition.getRemoteAnimationController()
2529 .createRemoteAnimationRecord(this, mTmpPoint, mTmpRect,
2530 (isChanging ? mTransitStartRect : null));
2531 adapter = adapters.mAdapter;
2532 thumbnailAdapter = adapters.mThumbnailAdapter;
2533 } else if (isChanging) {
Evan Roskycf76bed2019-01-15 10:33:58 -08002534 final float durationScale = mWmService.getTransitionAnimationScaleLocked();
Evan Rosky2289ba12018-11-19 18:28:18 -08002535 mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y);
2536 adapter = new LocalAnimationAdapter(
2537 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
Evan Roskycf76bed2019-01-15 10:33:58 -08002538 getDisplayContent().getDisplayInfo(), durationScale,
Evan Rosky2289ba12018-11-19 18:28:18 -08002539 true /* isAppAnimation */, false /* isThumbnail */),
2540 mWmService.mSurfaceAnimationRunner);
Evan Rosky966759f2019-01-15 10:33:58 -08002541 if (mThumbnail != null) {
2542 thumbnailAdapter = new LocalAnimationAdapter(
2543 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
Evan Roskycf76bed2019-01-15 10:33:58 -08002544 getDisplayContent().getDisplayInfo(), durationScale,
Evan Rosky966759f2019-01-15 10:33:58 -08002545 true /* isAppAnimation */, true /* isThumbnail */),
2546 mWmService.mSurfaceAnimationRunner);
2547 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002548 mTransit = transit;
2549 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002550 } else {
Vishnu Naira2977262018-07-26 13:31:26 -07002551 mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM);
2552
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002553 final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
2554 if (a != null) {
2555 adapter = new LocalAnimationAdapter(
2556 new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
lumark588a3e82018-07-20 18:53:54 +08002557 getDisplayContent().mAppTransition.canSkipFirstFrame(),
Vishnu Naira2977262018-07-26 13:31:26 -07002558 appStackClipMode,
Lucas Dupin3e1dc202018-12-02 15:14:20 -08002559 true /* isAppAnimation */,
Tiger Huangdc50bb52019-04-24 18:39:53 +08002560 getWindowCornerRadiusForAnimation()),
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002561 mWmService.mSurfaceAnimationRunner);
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002562 if (a.getZAdjustment() == Animation.ZORDER_TOP) {
2563 mNeedsZBoost = true;
2564 }
2565 mTransit = transit;
lumark588a3e82018-07-20 18:53:54 +08002566 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002567 } else {
2568 adapter = null;
chaviw23ee71c2017-12-18 11:29:41 -08002569 }
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002570 }
2571 if (adapter != null) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002572 startAnimation(getPendingTransaction(), adapter, !isVisible());
Jorim Jaggi82c17862018-02-21 17:50:18 +01002573 if (adapter.getShowWallpaper()) {
2574 mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2575 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002576 if (thumbnailAdapter != null) {
2577 mThumbnail.startAnimation(
2578 getPendingTransaction(), thumbnailAdapter, !isVisible());
2579 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002580 }
2581 } else {
2582 cancelAnimation();
2583 }
2584 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2585
2586 return isReallyAnimating();
2587 }
2588
2589 private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
2590 boolean isVoiceInteraction) {
2591 final DisplayContent displayContent = getTask().getDisplayContent();
2592 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2593 final int width = displayInfo.appWidth;
2594 final int height = displayInfo.appHeight;
2595 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG_WM,
2596 "applyAnimation: atoken=" + this);
2597
2598 // Determine the visible rect to calculate the thumbnail clip
2599 final WindowState win = findMainWindow();
2600 final Rect frame = new Rect(0, 0, width, height);
2601 final Rect displayFrame = new Rect(0, 0,
2602 displayInfo.logicalWidth, displayInfo.logicalHeight);
2603 final Rect insets = new Rect();
2604 final Rect stableInsets = new Rect();
2605 Rect surfaceInsets = null;
2606 final boolean freeform = win != null && win.inFreeformWindowingMode();
2607 if (win != null) {
2608 // Containing frame will usually cover the whole screen, including dialog windows.
2609 // For freeform workspace windows it will not cover the whole screen and it also
2610 // won't exactly match the final freeform window frame (e.g. when overlapping with
2611 // the status bar). In that case we need to use the final frame.
2612 if (freeform) {
chaviw492139a2018-07-16 16:07:35 -07002613 frame.set(win.getFrameLw());
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002614 } else if (win.isLetterboxedAppWindow()) {
2615 frame.set(getTask().getBounds());
Winson Chungc1674272018-02-21 10:15:17 -08002616 } else if (win.isDockedResizing()) {
2617 // If we are animating while docked resizing, then use the stack bounds as the
2618 // animation target (which will be different than the task bounds)
2619 frame.set(getTask().getParent().getBounds());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002620 } else {
chaviw553b0212018-07-12 13:37:01 -07002621 frame.set(win.getContainingFrame());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002622 }
2623 surfaceInsets = win.getAttrs().surfaceInsets;
Adrian Roos20e07892018-02-23 19:12:01 +01002624 // XXX(b/72757033): These are insets relative to the window frame, but we're really
2625 // interested in the insets relative to the frame we chose in the if-blocks above.
chaviw9c81e632018-07-31 11:17:52 -07002626 win.getContentInsets(insets);
2627 win.getStableInsets(stableInsets);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002628 }
2629
2630 if (mLaunchTaskBehind) {
2631 // Differentiate the two animations. This one which is briefly on the screen
2632 // gets the !enter animation, and the other activity which remains on the
2633 // screen gets the enter animation. Both appear in the mOpeningApps set.
2634 enter = false;
2635 }
2636 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "Loading animation for app transition."
2637 + " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter
2638 + " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets);
2639 final Configuration displayConfig = displayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08002640 final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002641 displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
2642 surfaceInsets, stableInsets, isVoiceInteraction, freeform, getTask().mTaskId);
2643 if (a != null) {
2644 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
2645 final int containingWidth = frame.width();
2646 final int containingHeight = frame.height();
2647 a.initialize(containingWidth, containingHeight, width, height);
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002648 a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002649 }
2650 return a;
2651 }
2652
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002653 @Override
Jorim Jaggi6de61012018-03-19 14:53:23 +01002654 public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
2655 return mAnimatingAppWindowTokenRegistry != null
2656 && mAnimatingAppWindowTokenRegistry.notifyAboutToFinish(
2657 this, endDeferFinishCallback);
2658 }
2659
2660 @Override
2661 public void onAnimationLeashDestroyed(Transaction t) {
2662 super.onAnimationLeashDestroyed(t);
Vishnu Naira2977262018-07-26 13:31:26 -07002663 if (mAnimationBoundsLayer != null) {
Robert Carr71200f22019-02-05 09:44:53 -08002664 t.remove(mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002665 mAnimationBoundsLayer = null;
2666 }
2667
Jorim Jaggi6de61012018-03-19 14:53:23 +01002668 if (mAnimatingAppWindowTokenRegistry != null) {
2669 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
2670 }
2671 }
2672
2673 @Override
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002674 protected void setLayer(Transaction t, int layer) {
2675 if (!mSurfaceAnimator.hasLeash()) {
2676 t.setLayer(mSurfaceControl, layer);
2677 }
2678 }
2679
2680 @Override
2681 protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
2682 if (!mSurfaceAnimator.hasLeash()) {
2683 t.setRelativeLayer(mSurfaceControl, relativeTo, layer);
2684 }
2685 }
2686
2687 @Override
2688 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
2689 if (!mSurfaceAnimator.hasLeash()) {
Robert Carr10584fa2019-01-14 15:55:19 -08002690 t.reparent(mSurfaceControl, newParent);
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002691 }
2692 }
2693
2694 @Override
2695 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002696 // The leash is parented to the animation layer. We need to preserve the z-order by using
2697 // the prefix order index, but we boost if necessary.
Robert Carrb9506032018-02-13 13:54:00 -08002698 int layer = 0;
2699 if (!inPinnedWindowingMode()) {
2700 layer = getPrefixOrderIndex();
2701 } else {
2702 // Pinned stacks have animations take place within themselves rather than an animation
2703 // layer so we need to preserve the order relative to the stack (e.g. the order of our
2704 // task/parent).
2705 layer = getParent().getPrefixOrderIndex();
2706 }
2707
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002708 if (mNeedsZBoost) {
2709 layer += Z_BOOST_BASE;
2710 }
Jorim Jaggi9cd99132019-04-24 17:41:35 +02002711 if (!mNeedsAnimationBoundsLayer) {
2712 leash.setLayer(layer);
2713 }
Robert Carr2f8aa392018-01-31 14:46:51 -08002714
2715 final DisplayContent dc = getDisplayContent();
Jorim Jaggibe418292018-03-26 16:14:12 +02002716 dc.assignStackOrdering();
Evan Rosky2289ba12018-11-19 18:28:18 -08002717
2718 if (leash == mTransitChangeLeash) {
2719 // This is a temporary state so skip any animation notifications
2720 return;
2721 } else if (mTransitChangeLeash != null) {
2722 // unparent mTransitChangeLeash for clean-up
Evan Rosky25b56192019-02-06 16:10:56 -08002723 clearChangeLeash(t, false /* cancel */);
Evan Rosky2289ba12018-11-19 18:28:18 -08002724 }
2725
Jorim Jaggi6de61012018-03-19 14:53:23 +01002726 if (mAnimatingAppWindowTokenRegistry != null) {
2727 mAnimatingAppWindowTokenRegistry.notifyStarting(this);
2728 }
Vishnu Naira2977262018-07-26 13:31:26 -07002729
2730 // If the animation needs to be cropped then an animation bounds layer is created as a child
2731 // of the pinned stack or animation layer. The leash is then reparented to this new layer.
2732 if (mNeedsAnimationBoundsLayer) {
Evan Rosky7735d352019-03-18 17:27:27 -07002733 mTmpRect.setEmpty();
2734 final Task task = getTask();
2735 if (getDisplayContent().mAppTransitionController.isTransitWithinTask(
2736 getTransit(), task)) {
2737 task.getBounds(mTmpRect);
2738 } else {
2739 final TaskStack stack = getStack();
2740 if (stack == null) {
2741 return;
2742 }
2743 // Set clip rect to stack bounds.
2744 stack.getBounds(mTmpRect);
Vishnu Naira2977262018-07-26 13:31:26 -07002745 }
2746 mAnimationBoundsLayer = createAnimationBoundsLayer(t);
2747
Vishnu Naira2977262018-07-26 13:31:26 -07002748 // Crop to stack bounds.
2749 t.setWindowCrop(mAnimationBoundsLayer, mTmpRect);
Jorim Jaggi9cd99132019-04-24 17:41:35 +02002750 t.setLayer(mAnimationBoundsLayer, layer);
Vishnu Naira2977262018-07-26 13:31:26 -07002751
2752 // Reparent leash to animation bounds layer.
Robert Carr10584fa2019-01-14 15:55:19 -08002753 t.reparent(leash, mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002754 }
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002755 }
2756
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002757 /**
2758 * This must be called while inside a transaction.
2759 */
2760 void showAllWindowsLocked() {
2761 forAllWindows(windowState -> {
2762 if (DEBUG_VISIBILITY) Slog.v(TAG, "performing show on: " + windowState);
2763 windowState.performShowLocked();
2764 }, false /* traverseTopToBottom */);
Jorim Jaggia5e10572017-11-15 14:36:26 +01002765 }
2766
2767 @Override
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002768 protected void onAnimationFinished() {
2769 super.onAnimationFinished();
2770
2771 mTransit = TRANSIT_UNSET;
2772 mTransitFlags = 0;
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002773 mNeedsZBoost = false;
Vishnu Naira2977262018-07-26 13:31:26 -07002774 mNeedsAnimationBoundsLayer = false;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002775
2776 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER,
2777 "AppWindowToken");
2778
Jorim Jaggi988f6682017-11-17 17:46:43 +01002779 clearThumbnail();
Jorim Jaggi752cd822018-03-29 16:29:18 +02002780 setClientHidden(isHidden() && hiddenRequested);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002781
lumarkff0ab692018-11-05 20:32:30 +08002782 getDisplayContent().computeImeTargetIfNeeded(this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002783
2784 if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + this
2785 + ": reportedVisible=" + reportedVisible
2786 + " okToDisplay=" + okToDisplay()
2787 + " okToAnimate=" + okToAnimate()
2788 + " startingDisplayed=" + startingDisplayed);
2789
Evan Rosky2289ba12018-11-19 18:28:18 -08002790 // clean up thumbnail window
2791 if (mThumbnail != null) {
2792 mThumbnail.destroy();
2793 mThumbnail = null;
2794 }
2795
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002796 // WindowState.onExitAnimationDone might modify the children list, so make a copy and then
2797 // traverse the copy.
2798 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
2799 children.forEach(WindowState::onExitAnimationDone);
2800
lumark588a3e82018-07-20 18:53:54 +08002801 getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002802 scheduleAnimation();
Jorim Jaggi9b5e3312019-03-01 18:08:00 +01002803
2804 mActivityRecord.onAnimationFinished();
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002805 }
2806
2807 @Override
2808 boolean isAppAnimating() {
2809 return isSelfAnimating();
2810 }
2811
2812 @Override
2813 boolean isSelfAnimating() {
2814 // If we are about to start a transition, we also need to be considered animating.
2815 return isWaitingForTransitionStart() || isReallyAnimating();
2816 }
2817
2818 /**
2819 * @return True if and only if we are actually running an animation. Note that
2820 * {@link #isSelfAnimating} also returns true if we are waiting for an animation to
2821 * start.
2822 */
2823 private boolean isReallyAnimating() {
2824 return super.isSelfAnimating();
2825 }
2826
Evan Rosky25b56192019-02-06 16:10:56 -08002827 /**
2828 * @param cancel {@code true} if clearing the leash due to cancelling instead of transferring
2829 * to another leash.
2830 */
2831 private void clearChangeLeash(Transaction t, boolean cancel) {
2832 if (mTransitChangeLeash == null) {
2833 return;
2834 }
2835 if (cancel) {
2836 clearThumbnail();
2837 SurfaceControl sc = getSurfaceControl();
2838 SurfaceControl parentSc = getParentSurfaceControl();
2839 // Don't reparent if surface is getting destroyed
2840 if (parentSc != null && sc != null) {
2841 t.reparent(sc, getParentSurfaceControl());
2842 }
2843 }
2844 t.hide(mTransitChangeLeash);
2845 t.reparent(mTransitChangeLeash, null);
2846 mTransitChangeLeash = null;
2847 if (cancel) {
2848 onAnimationLeashDestroyed(t);
2849 }
2850 }
2851
Jorim Jaggi988f6682017-11-17 17:46:43 +01002852 @Override
2853 void cancelAnimation() {
Evan Rosky2289ba12018-11-19 18:28:18 -08002854 cancelAnimationOnly();
Jorim Jaggi988f6682017-11-17 17:46:43 +01002855 clearThumbnail();
Evan Rosky25b56192019-02-06 16:10:56 -08002856 clearChangeLeash(getPendingTransaction(), true /* cancel */);
Evan Rosky2289ba12018-11-19 18:28:18 -08002857 }
2858
2859 /**
2860 * This only cancels the animation. It doesn't do other teardown like cleaning-up thumbnail
2861 * or interim leashes.
2862 * <p>
2863 * Used when canceling in preparation for starting a new animation.
2864 */
2865 void cancelAnimationOnly() {
2866 super.cancelAnimation();
Jorim Jaggi988f6682017-11-17 17:46:43 +01002867 }
2868
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002869 boolean isWaitingForTransitionStart() {
lumark588a3e82018-07-20 18:53:54 +08002870 return getDisplayContent().mAppTransition.isTransitionSet()
2871 && (getDisplayContent().mOpeningApps.contains(this)
Evan Rosky2289ba12018-11-19 18:28:18 -08002872 || getDisplayContent().mClosingApps.contains(this)
2873 || getDisplayContent().mChangingApps.contains(this));
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002874 }
2875
2876 public int getTransit() {
2877 return mTransit;
2878 }
2879
2880 int getTransitFlags() {
2881 return mTransitFlags;
2882 }
2883
Jorim Jaggi988f6682017-11-17 17:46:43 +01002884 void attachThumbnailAnimation() {
2885 if (!isReallyAnimating()) {
2886 return;
2887 }
2888 final int taskId = getTask().mTaskId;
2889 final GraphicBuffer thumbnailHeader =
lumark588a3e82018-07-20 18:53:54 +08002890 getDisplayContent().mAppTransition.getAppTransitionThumbnailHeader(taskId);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002891 if (thumbnailHeader == null) {
2892 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG, "No thumbnail header bitmap for: " + taskId);
2893 return;
2894 }
2895 clearThumbnail();
2896 mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnailHeader);
2897 mThumbnail.startAnimation(getPendingTransaction(), loadThumbnailAnimation(thumbnailHeader));
2898 }
2899
Tony Mak64b8d562017-12-28 17:44:02 +00002900 /**
2901 * Attaches a surface with a thumbnail for the
2902 * {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation.
2903 */
2904 void attachCrossProfileAppsThumbnailAnimation() {
2905 if (!isReallyAnimating()) {
2906 return;
2907 }
2908 clearThumbnail();
2909
2910 final WindowState win = findMainWindow();
2911 if (win == null) {
2912 return;
2913 }
chaviw492139a2018-07-16 16:07:35 -07002914 final Rect frame = win.getFrameLw();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002915 final int thumbnailDrawableRes = getTask().mUserId == mWmService.mCurrentUserId
Tony Mak64b8d562017-12-28 17:44:02 +00002916 ? R.drawable.ic_account_circle
Tony Makda4af232018-04-27 11:01:10 +01002917 : R.drawable.ic_corp_badge;
Tony Mak64b8d562017-12-28 17:44:02 +00002918 final GraphicBuffer thumbnail =
lumark588a3e82018-07-20 18:53:54 +08002919 getDisplayContent().mAppTransition
Tony Mak64b8d562017-12-28 17:44:02 +00002920 .createCrossProfileAppsThumbnail(thumbnailDrawableRes, frame);
2921 if (thumbnail == null) {
2922 return;
2923 }
2924 mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnail);
2925 final Animation animation =
lumark588a3e82018-07-20 18:53:54 +08002926 getDisplayContent().mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(
chaviw492139a2018-07-16 16:07:35 -07002927 win.getFrameLw());
Tony Mak64b8d562017-12-28 17:44:02 +00002928 mThumbnail.startAnimation(getPendingTransaction(), animation, new Point(frame.left,
2929 frame.top));
2930 }
2931
Jorim Jaggi988f6682017-11-17 17:46:43 +01002932 private Animation loadThumbnailAnimation(GraphicBuffer thumbnailHeader) {
2933 final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
2934
2935 // If this is a multi-window scenario, we use the windows frame as
2936 // destination of the thumbnail header animation. If this is a full screen
2937 // window scenario, we use the whole display as the target.
2938 WindowState win = findMainWindow();
2939 Rect appRect = win != null ? win.getContentFrameLw() :
2940 new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
chaviw9c81e632018-07-31 11:17:52 -07002941 final Rect insets = win != null ? win.getContentInsets() : null;
Jorim Jaggi988f6682017-11-17 17:46:43 +01002942 final Configuration displayConfig = mDisplayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08002943 return getDisplayContent().mAppTransition.createThumbnailAspectScaleAnimationLocked(
Jorim Jaggi988f6682017-11-17 17:46:43 +01002944 appRect, insets, thumbnailHeader, getTask().mTaskId, displayConfig.uiMode,
2945 displayConfig.orientation);
2946 }
2947
2948 private void clearThumbnail() {
2949 if (mThumbnail == null) {
2950 return;
2951 }
2952 mThumbnail.destroy();
2953 mThumbnail = null;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002954 }
2955
Jorim Jaggif84e2f62018-01-16 14:17:59 +01002956 void registerRemoteAnimations(RemoteAnimationDefinition definition) {
2957 mRemoteAnimationDefinition = definition;
2958 }
2959
2960 RemoteAnimationDefinition getRemoteAnimationDefinition() {
2961 return mRemoteAnimationDefinition;
2962 }
2963
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002964 @Override
2965 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
2966 super.dump(pw, prefix, dumpAll);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002967 if (appToken != null) {
Wale Ogunwale72919d22016-12-08 18:58:50 -08002968 pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002969 }
Winson Chung48b25652018-10-22 14:04:30 -07002970 pw.println(prefix + "component=" + mActivityComponent.flattenToShortString());
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08002971 pw.print(prefix); pw.print("task="); pw.println(getTask());
Wale Ogunwale51362492016-09-08 17:49:17 -07002972 pw.print(prefix); pw.print(" mFillsParent="); pw.print(mFillsParent);
2973 pw.print(" mOrientation="); pw.println(mOrientation);
Wale Ogunwale89973222017-04-23 18:39:45 -07002974 pw.println(prefix + "hiddenRequested=" + hiddenRequested + " mClientHidden=" + mClientHidden
2975 + ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "")
2976 + " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible);
Craig Mautner59431632012-04-04 11:56:44 -07002977 if (paused) {
2978 pw.print(prefix); pw.print("paused="); pw.println(paused);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002979 }
Wale Ogunwale9017ec02016-02-25 08:55:25 -08002980 if (mAppStopped) {
2981 pw.print(prefix); pw.print("mAppStopped="); pw.println(mAppStopped);
2982 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002983 if (mNumInterestingWindows != 0 || mNumDrawnWindows != 0
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002984 || allDrawn || mLastAllDrawn) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002985 pw.print(prefix); pw.print("mNumInterestingWindows=");
2986 pw.print(mNumInterestingWindows);
2987 pw.print(" mNumDrawnWindows="); pw.print(mNumDrawnWindows);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002988 pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
Craig Mautner6fbda632012-07-03 09:26:39 -07002989 pw.print(" allDrawn="); pw.print(allDrawn);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002990 pw.print(" lastAllDrawn="); pw.print(mLastAllDrawn);
Craig Mautner6fbda632012-07-03 09:26:39 -07002991 pw.println(")");
2992 }
2993 if (inPendingTransaction) {
2994 pw.print(prefix); pw.print("inPendingTransaction=");
2995 pw.println(inPendingTransaction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002996 }
Craig Mautner799bc1d2015-01-14 10:33:48 -08002997 if (startingData != null || removed || firstWindowDrawn || mIsExiting) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002998 pw.print(prefix); pw.print("startingData="); pw.print(startingData);
2999 pw.print(" removed="); pw.print(removed);
Craig Mautner3d7ca312015-01-08 10:56:00 -08003000 pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
Craig Mautner799bc1d2015-01-14 10:33:48 -08003001 pw.print(" mIsExiting="); pw.println(mIsExiting);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003002 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08003003 if (startingWindow != null || startingSurface != null
Wale Ogunwale6c459212017-05-17 08:56:03 -07003004 || startingDisplayed || startingMoved || mHiddenSetFromTransferredStartingWindow) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003005 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08003006 pw.print(" startingSurface="); pw.print(startingSurface);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003007 pw.print(" startingDisplayed="); pw.print(startingDisplayed);
Wale Ogunwale6c459212017-05-17 08:56:03 -07003008 pw.print(" startingMoved="); pw.print(startingMoved);
3009 pw.println(" mHiddenSetFromTransferredStartingWindow="
3010 + mHiddenSetFromTransferredStartingWindow);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003011 }
Jorim Jaggi0429f352015-12-22 16:29:16 +01003012 if (!mFrozenBounds.isEmpty()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08003013 pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
Jorim Jaggi26c8c422016-05-09 19:57:25 -07003014 pw.print(prefix); pw.print("mFrozenMergedConfig="); pw.println(mFrozenMergedConfig);
Chong Zhangd78ddb42016-03-02 17:01:14 -08003015 }
3016 if (mPendingRelaunchCount != 0) {
3017 pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount);
Jorim Jaggi0429f352015-12-22 16:29:16 +01003018 }
Riddle Hsub398da32019-01-21 21:48:16 +08003019 if (mSizeCompatScale != 1f || mSizeCompatBounds != null) {
3020 pw.println(prefix + "mSizeCompatScale=" + mSizeCompatScale + " mSizeCompatBounds="
3021 + mSizeCompatBounds);
3022 }
Wale Ogunwalee287e192017-04-21 09:30:12 -07003023 if (mRemovingFromDisplay) {
3024 pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay);
3025 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003026 }
3027
3028 @Override
3029 void setHidden(boolean hidden) {
3030 super.setHidden(hidden);
Winson Chunge55c0192017-08-24 14:50:48 -07003031
3032 if (hidden) {
3033 // Once the app window is hidden, reset the last saved PiP snap fraction
3034 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(this);
3035 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003036 scheduleAnimation();
3037 }
3038
3039 @Override
3040 void prepareSurfaces() {
3041 // isSelfAnimating also returns true when we are about to start a transition, so we need
3042 // to check super here.
3043 final boolean reallyAnimating = super.isSelfAnimating();
3044 final boolean show = !isHidden() || reallyAnimating;
Robert Carrd8e4fb72019-01-31 11:14:30 -08003045
3046 if (mSurfaceControl != null) {
3047 if (show && !mLastSurfaceShowing) {
3048 mPendingTransaction.show(mSurfaceControl);
3049 } else if (!show && mLastSurfaceShowing) {
3050 mPendingTransaction.hide(mSurfaceControl);
3051 }
Jorim Jaggi4d1835d2017-08-31 17:28:27 +02003052 }
Jorim Jaggi988f6682017-11-17 17:46:43 +01003053 if (mThumbnail != null) {
3054 mThumbnail.setShowing(mPendingTransaction, show);
3055 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003056 mLastSurfaceShowing = show;
3057 super.prepareSurfaces();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003058 }
3059
Jorim Jaggi77d0f36c2018-03-16 17:49:49 +01003060 /**
3061 * @return Whether our {@link #getSurfaceControl} is currently showing.
3062 */
3063 boolean isSurfaceShowing() {
3064 return mLastSurfaceShowing;
3065 }
3066
Jorim Jaggib0fc8172017-11-23 17:04:08 +00003067 boolean isFreezingScreen() {
3068 return mFreezingScreen;
3069 }
3070
3071 @Override
3072 boolean needsZBoost() {
3073 return mNeedsZBoost || super.needsZBoost();
3074 }
3075
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07003076 @CallSuper
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003077 @Override
Nataniel Borges023ecb52019-01-16 14:15:43 -08003078 public void writeToProto(ProtoOutputStream proto, long fieldId,
3079 @WindowTraceLogLevel int logLevel) {
3080 // Critical log level logs only visible elements to mitigate performance overheard
3081 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
3082 return;
3083 }
3084
Steven Timotiusaf03df62017-07-18 16:56:43 -07003085 final long token = proto.start(fieldId);
3086 writeNameToProto(proto, NAME);
Nataniel Borges023ecb52019-01-16 14:15:43 -08003087 super.writeToProto(proto, WINDOW_TOKEN, logLevel);
Vishnu Nair04ab4392018-01-10 11:00:06 -08003088 proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing);
3089 proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart());
3090 proto.write(IS_REALLY_ANIMATING, isReallyAnimating());
3091 if (mThumbnail != null){
3092 mThumbnail.writeToProto(proto, THUMBNAIL);
3093 }
3094 proto.write(FILLS_PARENT, mFillsParent);
3095 proto.write(APP_STOPPED, mAppStopped);
3096 proto.write(HIDDEN_REQUESTED, hiddenRequested);
3097 proto.write(CLIENT_HIDDEN, mClientHidden);
3098 proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient);
3099 proto.write(REPORTED_DRAWN, reportedDrawn);
3100 proto.write(REPORTED_VISIBLE, reportedVisible);
3101 proto.write(NUM_INTERESTING_WINDOWS, mNumInterestingWindows);
3102 proto.write(NUM_DRAWN_WINDOWS, mNumDrawnWindows);
3103 proto.write(ALL_DRAWN, allDrawn);
3104 proto.write(LAST_ALL_DRAWN, mLastAllDrawn);
3105 proto.write(REMOVED, removed);
Nataniel Borges023ecb52019-01-16 14:15:43 -08003106 if (startingWindow != null) {
Vishnu Nair04ab4392018-01-10 11:00:06 -08003107 startingWindow.writeIdentifierToProto(proto, STARTING_WINDOW);
3108 }
3109 proto.write(STARTING_DISPLAYED, startingDisplayed);
3110 proto.write(STARTING_MOVED, startingMoved);
3111 proto.write(HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW,
3112 mHiddenSetFromTransferredStartingWindow);
3113 for (Rect bounds : mFrozenBounds) {
3114 bounds.writeToProto(proto, FROZEN_BOUNDS);
3115 }
Steven Timotiusaf03df62017-07-18 16:56:43 -07003116 proto.end(token);
3117 }
3118
3119 void writeNameToProto(ProtoOutputStream proto, long fieldId) {
3120 if (appToken == null) {
3121 return;
3122 }
3123 try {
3124 proto.write(fieldId, appToken.getName());
3125 } catch (RemoteException e) {
3126 // This shouldn't happen, but in this case fall back to outputting nothing
3127 Slog.e(TAG, e.toString());
3128 }
3129 }
3130
3131 @Override
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003132 public String toString() {
3133 if (stringName == null) {
3134 StringBuilder sb = new StringBuilder();
3135 sb.append("AppWindowToken{");
3136 sb.append(Integer.toHexString(System.identityHashCode(this)));
3137 sb.append(" token="); sb.append(token); sb.append('}');
3138 stringName = sb.toString();
3139 }
Wale Ogunwaleba51ca22016-09-23 06:06:54 -07003140 return stringName + ((mIsExiting) ? " mIsExiting=" : "");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003141 }
Adrian Roos20e07892018-02-23 19:12:01 +01003142
3143 Rect getLetterboxInsets() {
3144 if (mLetterbox != null) {
3145 return mLetterbox.getInsets();
3146 } else {
3147 return new Rect();
3148 }
3149 }
Adrian Roos23df3a32018-03-15 15:41:13 +01003150
Riddle Hsu69de5fb2019-02-23 01:19:50 +08003151 /** Gets the inner bounds of letterbox. The bounds will be empty if there is no letterbox. */
3152 void getLetterboxInnerBounds(Rect outBounds) {
3153 if (mLetterbox != null) {
3154 outBounds.set(mLetterbox.getInnerFrame());
3155 } else {
3156 outBounds.setEmpty();
3157 }
3158 }
3159
Adrian Roos23df3a32018-03-15 15:41:13 +01003160 /**
Riddle Hsu69de5fb2019-02-23 01:19:50 +08003161 * @return {@code true} if there is a letterbox and any part of that letterbox overlaps with
Adrian Roos23df3a32018-03-15 15:41:13 +01003162 * the given {@code rect}.
3163 */
3164 boolean isLetterboxOverlappingWith(Rect rect) {
3165 return mLetterbox != null && mLetterbox.isOverlappingWith(rect);
3166 }
chaviw4ad54912018-05-30 11:05:44 -07003167
3168 /**
3169 * Sets if this AWT is in the process of closing or entering PIP.
3170 * {@link #mWillCloseOrEnterPip}}
3171 */
3172 void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
3173 mWillCloseOrEnterPip = willCloseOrEnterPip;
3174 }
3175
3176 /**
3177 * Returns whether this AWT is considered closing. Conditions are either
3178 * 1. Is this app animating and was requested to be hidden
3179 * 2. App is delayed closing since it might enter PIP.
3180 */
3181 boolean isClosingOrEnteringPip() {
3182 return (isAnimating() && hiddenRequested) || mWillCloseOrEnterPip;
3183 }
Jorim Jaggiaf0d6d22018-06-08 15:25:35 +02003184
3185 /**
3186 * @return Whether we are allowed to show non-starting windows at the moment. We disallow
3187 * showing windows during transitions in case we have windows that have wide-color-gamut
3188 * color mode set to avoid jank in the middle of the transition.
3189 */
3190 boolean canShowWindows() {
3191 return allDrawn && !(isReallyAnimating() && hasNonDefaultColorWindow());
3192 }
3193
3194 /**
3195 * @return true if we have a window that has a non-default color mode set; false otherwise.
3196 */
3197 private boolean hasNonDefaultColorWindow() {
3198 return forAllWindows(ws -> ws.mAttrs.getColorMode() != COLOR_MODE_DEFAULT,
3199 true /* topToBottom */);
3200 }
lumark588a3e82018-07-20 18:53:54 +08003201
3202 void removeFromPendingTransition() {
3203 if (isWaitingForTransitionStart() && mDisplayContent != null) {
3204 mDisplayContent.mOpeningApps.remove(this);
Evan Rosky25b56192019-02-06 16:10:56 -08003205 if (mDisplayContent.mChangingApps.remove(this)) {
3206 clearChangeLeash(getPendingTransaction(), true /* cancel */);
3207 }
lumark588a3e82018-07-20 18:53:54 +08003208 mDisplayContent.mClosingApps.remove(this);
3209 }
3210 }
chaviwdcf76ec2019-01-11 16:48:46 -08003211
3212 private void updateColorTransform() {
3213 if (mSurfaceControl != null && mLastAppSaturationInfo != null) {
3214 mPendingTransaction.setColorTransform(mSurfaceControl, mLastAppSaturationInfo.mMatrix,
3215 mLastAppSaturationInfo.mTranslation);
3216 mWmService.scheduleAnimationLocked();
3217 }
3218 }
3219
3220 private static class AppSaturationInfo {
3221 float[] mMatrix = new float[9];
3222 float[] mTranslation = new float[3];
3223
3224 void setSaturation(@Size(9) float[] matrix, @Size(3) float[] translation) {
3225 System.arraycopy(matrix, 0, mMatrix, 0, mMatrix.length);
3226 System.arraycopy(translation, 0, mTranslation, 0, mTranslation.length);
3227 }
3228 }
Jeff Browne9bdb312012-04-05 15:30:10 -07003229}