blob: ecbecbafd3d56ecb5664e44824c6254dfba7fa8e [file] [log] [blame]
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.wm;
18
Evan Rosky2289ba12018-11-19 18:28:18 -080019import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
Winson Chunge55c0192017-08-24 14:50:48 -070020import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
Jorim Jaggic6976f02018-04-18 16:31:07 +020021import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
Winson Chunge55c0192017-08-24 14:50:48 -070022import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
Jorim Jaggiaf0d6d22018-06-08 15:25:35 +020023import static android.content.pm.ActivityInfo.COLOR_MODE_DEFAULT;
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -070024import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
Wale Ogunwale51362492016-09-08 17:49:17 -070025import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
Jorim Jaggif5f9e122017-10-24 18:21:09 +020026import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
Jorim Jaggife762342016-10-13 14:33:27 +020027import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
Jorim Jaggid635a4a2017-05-03 15:21:26 +020028import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080029import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
Jorim Jaggife762342016-10-13 14:33:27 +020030import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
Wale Ogunwaled1c37912016-08-16 03:19:39 -070031import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080032import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -070033import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080034import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
Evan Rosky2289ba12018-11-19 18:28:18 -080035import static android.view.WindowManager.TRANSIT_TASK_CHANGE_WINDOWING_MODE;
chaviw9c81e632018-07-31 11:17:52 -070036import static android.view.WindowManager.TRANSIT_UNSET;
Jorim Jaggic6976f02018-04-18 16:31:07 +020037import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
chaviw9c81e632018-07-31 11:17:52 -070038
Adrian Roose99bc052017-11-20 17:55:31 +010039import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
40import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070041import static com.android.server.wm.AppWindowTokenProto.ALL_DRAWN;
42import static com.android.server.wm.AppWindowTokenProto.APP_STOPPED;
43import static com.android.server.wm.AppWindowTokenProto.CLIENT_HIDDEN;
44import static com.android.server.wm.AppWindowTokenProto.DEFER_HIDING_CLIENT;
45import static com.android.server.wm.AppWindowTokenProto.FILLS_PARENT;
46import static com.android.server.wm.AppWindowTokenProto.FROZEN_BOUNDS;
47import static com.android.server.wm.AppWindowTokenProto.HIDDEN_REQUESTED;
48import static com.android.server.wm.AppWindowTokenProto.HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW;
49import static com.android.server.wm.AppWindowTokenProto.IS_REALLY_ANIMATING;
50import static com.android.server.wm.AppWindowTokenProto.IS_WAITING_FOR_TRANSITION_START;
51import static com.android.server.wm.AppWindowTokenProto.LAST_ALL_DRAWN;
52import static com.android.server.wm.AppWindowTokenProto.LAST_SURFACE_SHOWING;
53import static com.android.server.wm.AppWindowTokenProto.NAME;
54import static com.android.server.wm.AppWindowTokenProto.NUM_DRAWN_WINDOWS;
55import static com.android.server.wm.AppWindowTokenProto.NUM_INTERESTING_WINDOWS;
56import static com.android.server.wm.AppWindowTokenProto.REMOVED;
57import static com.android.server.wm.AppWindowTokenProto.REPORTED_DRAWN;
58import static com.android.server.wm.AppWindowTokenProto.REPORTED_VISIBLE;
59import static com.android.server.wm.AppWindowTokenProto.STARTING_DISPLAYED;
60import static com.android.server.wm.AppWindowTokenProto.STARTING_MOVED;
61import static com.android.server.wm.AppWindowTokenProto.STARTING_WINDOW;
62import static com.android.server.wm.AppWindowTokenProto.THUMBNAIL;
63import static com.android.server.wm.AppWindowTokenProto.WINDOW_TOKEN;
chaviw9c81e632018-07-31 11:17:52 -070064import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
65import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
66import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
67import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
68import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
69import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
70import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
71import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
72import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
73import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
74import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
75import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
76import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
77import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN;
78import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
79import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
80import static com.android.server.wm.WindowManagerService.logWithStack;
chaviw15ad49f2019-04-24 15:05:39 -070081import static com.android.server.wm.WindowState.LEGACY_POLICY_VISIBILITY;
Vishnu Naira2977262018-07-26 13:31:26 -070082import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
Evan Rosky641daea2019-04-24 14:45:24 -070083import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080084
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070085import android.annotation.CallSuper;
chaviwdcf76ec2019-01-11 16:48:46 -080086import android.annotation.Size;
Jorim Jaggid635a4a2017-05-03 15:21:26 +020087import android.app.Activity;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080088import android.app.ActivityManager;
Winson Chung48b25652018-10-22 14:04:30 -070089import android.content.ComponentName;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080090import android.content.res.CompatibilityInfo;
Jorim Jaggi26c8c422016-05-09 19:57:25 -070091import android.content.res.Configuration;
Jorim Jaggi988f6682017-11-17 17:46:43 +010092import android.graphics.GraphicBuffer;
Jorim Jaggif5f9e122017-10-24 18:21:09 +020093import android.graphics.Point;
Jorim Jaggi0429f352015-12-22 16:29:16 +010094import android.graphics.Rect;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -070095import android.os.Binder;
Tiger Huang51c5a1d2018-12-11 20:24:51 +080096import android.os.Build;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -080097import android.os.Debug;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -070098import android.os.IBinder;
Steven Timotiusaf03df62017-07-18 16:56:43 -070099import android.os.RemoteException;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800100import android.os.SystemClock;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200101import android.os.Trace;
Evan Rosky2289ba12018-11-19 18:28:18 -0800102import android.util.ArraySet;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800103import android.util.Slog;
Steven Timotiusaf03df62017-07-18 16:56:43 -0700104import android.util.proto.ProtoOutputStream;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200105import android.view.DisplayInfo;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800106import android.view.IApplicationToken;
Robert Carr788f5742018-07-30 17:46:45 -0700107import android.view.InputApplicationHandle;
Evan Rosky966759f2019-01-15 10:33:58 -0800108import android.view.RemoteAnimationAdapter;
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100109import android.view.RemoteAnimationDefinition;
Robert Carr6914f082017-03-20 19:04:30 -0700110import android.view.SurfaceControl;
Tony Mak64b8d562017-12-28 17:44:02 +0000111import android.view.SurfaceControl.Transaction;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800112import android.view.WindowManager;
Jorim Jaggi87fdbcb2017-08-17 13:41:11 +0200113import android.view.WindowManager.LayoutParams;
Tony Mak64b8d562017-12-28 17:44:02 +0000114import android.view.animation.Animation;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800115
Tony Mak64b8d562017-12-28 17:44:02 +0000116import com.android.internal.R;
Riddle Hsua118b3a2018-10-11 22:05:06 +0800117import com.android.internal.annotations.VisibleForTesting;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800118import com.android.internal.util.ToBooleanFunction;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800119import com.android.server.AttributeCache;
chaviwdcf76ec2019-01-11 16:48:46 -0800120import com.android.server.LocalServices;
Christine Franks0ada2772019-02-25 13:54:57 -0800121import com.android.server.display.color.ColorDisplayService;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800122import com.android.server.policy.WindowManagerPolicy;
Adrian Roose99bc052017-11-20 17:55:31 +0100123import com.android.server.policy.WindowManagerPolicy.StartingSurface;
Evan Rosky2289ba12018-11-19 18:28:18 -0800124import com.android.server.wm.RemoteAnimationController.RemoteAnimationRecord;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800125import com.android.server.wm.WindowManagerService.H;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800126
127import java.io.PrintWriter;
chaviwdcf76ec2019-01-11 16:48:46 -0800128import java.lang.ref.WeakReference;
Jorim Jaggi0429f352015-12-22 16:29:16 +0100129import java.util.ArrayDeque;
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800130import java.util.ArrayList;
lumark588a3e82018-07-20 18:53:54 +0800131import java.util.function.Consumer;
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800132
133class AppTokenList extends ArrayList<AppWindowToken> {
134}
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800135
136/**
137 * Version of WindowToken that is specifically for a particular application (or
138 * really activity) that is displaying windows.
139 */
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800140class AppWindowToken extends WindowToken implements WindowManagerService.AppFreezeListener,
141 ConfigurationContainerListener {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800142 private static final String TAG = TAG_WITH_CLASS_NAME ? "AppWindowToken" : TAG_WM;
143
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100144 /**
145 * Value to increment the z-layer when boosting a layer during animations. BOOST in l33tsp34k.
146 */
Jorim Jaggi9cd99132019-04-24 17:41:35 +0200147 @VisibleForTesting static final int Z_BOOST_BASE = 800570000;
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100148
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800149 // Non-null only for application tokens.
150 final IApplicationToken appToken;
Winson Chung48b25652018-10-22 14:04:30 -0700151 final ComponentName mActivityComponent;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800152 final boolean mVoiceInteraction;
Dianne Hackborne30e02f2014-05-27 18:24:45 -0700153
Wale Ogunwale51362492016-09-08 17:49:17 -0700154 /** @see WindowContainer#fillsParent() */
155 private boolean mFillsParent;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800156 boolean mShowForAllUsers;
157 int mTargetSdk;
Craig Mautnera2c77052012-03-26 12:14:43 -0700158
Bryce Lee6d410262017-02-28 15:30:17 -0800159 // Flag set while reparenting to prevent actions normally triggered by an individual parent
160 // change.
161 private boolean mReparenting;
162
Wale Ogunwalee287e192017-04-21 09:30:12 -0700163 // True if we are current in the process of removing this app token from the display
164 private boolean mRemovingFromDisplay = false;
165
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800166 // The input dispatching timeout for this application token in nanoseconds.
Wale Ogunwale72919d22016-12-08 18:58:50 -0800167 long mInputDispatchingTimeoutNanos;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800168
169 // These are used for determining when all windows associated with
170 // an activity have been drawn, so they can be made visible together
171 // at the same time.
Craig Mautner764983d2012-03-22 11:37:36 -0700172 // initialize so that it doesn't match mTransactionSequence which is an int.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700173 private long mLastTransactionSequence = Long.MIN_VALUE;
174 private int mNumInterestingWindows;
175 private int mNumDrawnWindows;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800176 boolean inPendingTransaction;
177 boolean allDrawn;
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000178 private boolean mLastAllDrawn;
179
Craig Mautner7636dfb2012-11-16 15:24:11 -0800180 // Set to true when this app creates a surface while in the middle of an animation. In that
181 // case do not clear allDrawn until the animation completes.
182 boolean deferClearAllDrawn;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800183
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800184 // Is this window's surface needed? This is almost like hidden, except
185 // it will sometimes be true a little earlier: when the token has
186 // been shown, but is still waiting for its app transition to execute
187 // before making its windows shown.
188 boolean hiddenRequested;
189
190 // Have we told the window clients to hide themselves?
Wale Ogunwale89973222017-04-23 18:39:45 -0700191 private boolean mClientHidden;
192
193 // If true we will defer setting mClientHidden to true and reporting to the client that it is
194 // hidden.
195 boolean mDeferHidingClient;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800196
197 // Last visibility state we reported to the app token.
198 boolean reportedVisible;
199
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700200 // Last drawn state we reported to the app token.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700201 private boolean reportedDrawn;
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700202
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800203 // Set to true when the token has been removed from the window mgr.
204 boolean removed;
205
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800206 // Information about an application starting window if displayed.
chaviwa8f07a72019-05-01 16:25:39 -0700207 StartingData mStartingData;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800208 WindowState startingWindow;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800209 StartingSurface startingSurface;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800210 boolean startingDisplayed;
211 boolean startingMoved;
Jorim Jaggi60f9c972018-02-01 19:21:07 +0100212
Wale Ogunwale6c459212017-05-17 08:56:03 -0700213 // True if the hidden state of this token was forced to false due to a transferred starting
214 // window.
215 private boolean mHiddenSetFromTransferredStartingWindow;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800216 boolean firstWindowDrawn;
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700217 private final WindowState.UpdateReportedVisibilityResults mReportedVisibilityResults =
218 new WindowState.UpdateReportedVisibilityResults();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800219
220 // Input application handle used by the input dispatcher.
Jeff Brown9302c872011-07-13 22:51:29 -0700221 final InputApplicationHandle mInputApplicationHandle;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800222
Wale Ogunwale571771c2016-08-26 13:18:50 -0700223 // TODO: Have a WindowContainer state for tracking exiting/deferred removal.
Craig Mautner799bc1d2015-01-14 10:33:48 -0800224 boolean mIsExiting;
Craig Mautner9ef471f2014-02-07 13:11:47 -0800225
Craig Mautnerbb742462014-07-07 15:28:55 -0700226 boolean mLaunchTaskBehind;
Craig Mautner8746a472014-07-24 15:12:54 -0700227 boolean mEnteringAnimation;
Craig Mautnerbb742462014-07-07 15:28:55 -0700228
Wale Ogunwale72919d22016-12-08 18:58:50 -0800229 private boolean mAlwaysFocusable;
Wale Ogunwale6cae7652015-12-26 07:36:26 -0800230
Robert Carre12aece2016-02-02 22:43:27 -0800231 boolean mAppStopped;
Robert Carrfd10cd12016-06-29 16:41:50 -0700232 int mRotationAnimationHint;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700233 private int mPendingRelaunchCount;
Robert Carre12aece2016-02-02 22:43:27 -0800234
Jorim Jaggife762342016-10-13 14:33:27 +0200235 private boolean mLastContainsShowWhenLockedWindow;
236 private boolean mLastContainsDismissKeyguardWindow;
237
Jorim Jaggi0429f352015-12-22 16:29:16 +0100238 ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
Jorim Jaggi26c8c422016-05-09 19:57:25 -0700239 ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
Jorim Jaggi0429f352015-12-22 16:29:16 +0100240
Riddle Hsub398da32019-01-21 21:48:16 +0800241 /**
242 * The scale to fit at least one side of the activity to its parent. If the activity uses
243 * 1920x1080, and the actually size on the screen is 960x540, then the scale is 0.5.
244 */
245 private float mSizeCompatScale = 1f;
246 /**
247 * The bounds in global coordinates for activity in size compatibility mode.
248 * @see ActivityRecord#inSizeCompatMode
249 */
250 private Rect mSizeCompatBounds;
251
Wale Ogunwale6c459212017-05-17 08:56:03 -0700252 private boolean mDisablePreviewScreenshots;
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +0100253
Wale Ogunwale034a8ec2017-09-02 17:14:40 -0700254 private Task mLastParent;
Robert Carred3e83b2017-04-21 13:26:55 -0700255
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800256 // TODO: Remove after unification
257 ActivityRecord mActivityRecord;
258
chaviwd3bf08d2017-08-01 17:24:59 -0700259 /**
260 * See {@link #canTurnScreenOn()}
261 */
262 private boolean mCanTurnScreenOn = true;
263
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200264 /**
265 * If we are running an animation, this determines the transition type. Must be one of
266 * AppTransition.TRANSIT_* constants.
267 */
268 private int mTransit;
269
270 /**
271 * If we are running an animation, this determines the flags during this animation. Must be a
272 * bitwise combination of AppTransition.TRANSIT_FLAG_* constants.
273 */
274 private int mTransitFlags;
275
276 /** Whether our surface was set to be showing in the last call to {@link #prepareSurfaces} */
Jorim Jaggifd1891462017-12-29 15:41:36 +0100277 private boolean mLastSurfaceShowing = true;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200278
Evan Rosky2289ba12018-11-19 18:28:18 -0800279 /**
280 * This gets used during some open/close transitions as well as during a change transition
281 * where it represents the starting-state snapshot.
282 */
Jorim Jaggi988f6682017-11-17 17:46:43 +0100283 private AppWindowThumbnail mThumbnail;
Evan Rosky2289ba12018-11-19 18:28:18 -0800284 private final Rect mTransitStartRect = new Rect();
285
286 /**
287 * This leash is used to "freeze" the app surface in place after the state change, but before
288 * the animation is ready to start.
289 */
290 private SurfaceControl mTransitChangeLeash = null;
Jorim Jaggi988f6682017-11-17 17:46:43 +0100291
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000292 /** Have we been asked to have this token keep the screen frozen? */
293 private boolean mFreezingScreen;
294
295 /** Whether this token should be boosted at the top of all app window tokens. */
Jorim Jaggi9cd99132019-04-24 17:41:35 +0200296 @VisibleForTesting boolean mNeedsZBoost;
Adrian Roos4d18a2e2017-12-19 19:08:05 +0100297 private Letterbox mLetterbox;
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000298
chaviw23ee71c2017-12-18 11:29:41 -0800299 private final Point mTmpPoint = new Point();
chaviw23012112017-12-20 15:29:04 -0800300 private final Rect mTmpRect = new Rect();
Evan Rosky2289ba12018-11-19 18:28:18 -0800301 private final Rect mTmpPrevBounds = new Rect();
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100302 private RemoteAnimationDefinition mRemoteAnimationDefinition;
Jorim Jaggi6de61012018-03-19 14:53:23 +0100303 private AnimatingAppWindowTokenRegistry mAnimatingAppWindowTokenRegistry;
chaviw23ee71c2017-12-18 11:29:41 -0800304
chaviw4ad54912018-05-30 11:05:44 -0700305 /**
306 * A flag to determine if this AWT is in the process of closing or entering PIP. This is needed
307 * to help AWT know that the app is in the process of closing but hasn't yet started closing on
308 * the WM side.
309 */
310 private boolean mWillCloseOrEnterPip;
311
Vishnu Naira2977262018-07-26 13:31:26 -0700312 /** Layer used to constrain the animation to a token's stack bounds. */
313 SurfaceControl mAnimationBoundsLayer;
314
315 /** Whether this token needs to create mAnimationBoundsLayer for cropping animations. */
316 boolean mNeedsAnimationBoundsLayer;
317
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800318 private static final int STARTING_WINDOW_TYPE_NONE = 0;
319 private static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
320 private static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
321
chaviwdcf76ec2019-01-11 16:48:46 -0800322 private AppSaturationInfo mLastAppSaturationInfo;
323
324 private final ColorDisplayService.ColorTransformController mColorTransformController =
325 (matrix, translation) -> mWmService.mH.post(() -> {
326 synchronized (mWmService.mGlobalLock) {
327 if (mLastAppSaturationInfo == null) {
328 mLastAppSaturationInfo = new AppSaturationInfo();
329 }
330
331 mLastAppSaturationInfo.setSaturation(matrix, translation);
332 updateColorTransform();
333 }
334 });
335
Winson Chung48b25652018-10-22 14:04:30 -0700336 AppWindowToken(WindowManagerService service, IApplicationToken token,
337 ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
338 long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers,
Jorim Jaggi91d382a2019-03-27 17:00:48 +0100339 int targetSdk, int orientation, int rotationAnimationHint,
Winson Chung48b25652018-10-22 14:04:30 -0700340 boolean launchTaskBehind, boolean alwaysFocusable,
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800341 ActivityRecord activityRecord) {
Winson Chung48b25652018-10-22 14:04:30 -0700342 this(service, token, activityComponent, voiceInteraction, dc, fullscreen);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800343 // TODO: remove after unification
344 mActivityRecord = activityRecord;
345 mActivityRecord.registerConfigurationChangeListener(this);
Wale Ogunwale72919d22016-12-08 18:58:50 -0800346 mInputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800347 mShowForAllUsers = showForAllUsers;
348 mTargetSdk = targetSdk;
349 mOrientation = orientation;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800350 mLaunchTaskBehind = launchTaskBehind;
351 mAlwaysFocusable = alwaysFocusable;
352 mRotationAnimationHint = rotationAnimationHint;
353
354 // Application tokens start out hidden.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200355 setHidden(true);
Wale Ogunwale72919d22016-12-08 18:58:50 -0800356 hiddenRequested = true;
chaviwdcf76ec2019-01-11 16:48:46 -0800357
358 ColorDisplayService.ColorDisplayServiceInternal cds = LocalServices.getService(
359 ColorDisplayService.ColorDisplayServiceInternal.class);
360 cds.attachColorTransformController(activityRecord.packageName, activityRecord.mUserId,
361 new WeakReference<>(mColorTransformController));
Wale Ogunwale72919d22016-12-08 18:58:50 -0800362 }
363
Winson Chung48b25652018-10-22 14:04:30 -0700364 AppWindowToken(WindowManagerService service, IApplicationToken token,
365 ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
366 boolean fillsParent) {
Wale Ogunwale5cd907d2017-01-26 14:14:08 -0800367 super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true, dc,
368 false /* ownerCanManageAppTokens */);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700369 appToken = token;
Winson Chung48b25652018-10-22 14:04:30 -0700370 mActivityComponent = activityComponent;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800371 mVoiceInteraction = voiceInteraction;
Wale Ogunwale17f175c2017-02-07 16:54:10 -0800372 mFillsParent = fillsParent;
Robert Carr0bcbe642018-10-11 19:07:43 -0700373 mInputApplicationHandle = new InputApplicationHandle(appToken.asBinder());
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800374 }
375
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800376 void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
377 firstWindowDrawn = true;
378
379 // We now have a good window to show, remove dead placeholders
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700380 removeDeadWindows();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800381
Jorim Jaggi02886a82016-12-06 09:10:06 -0800382 if (startingWindow != null) {
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800383 if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Slog.v(TAG, "Finish starting "
384 + win.mToken + ": first real window is shown, no animation");
385 // If this initial window is animating, stop it -- we will do an animation to reveal
386 // it from behind the starting window, so there is no need for it to also be doing its
387 // own stuff.
Jorim Jaggia5e10572017-11-15 14:36:26 +0100388 win.cancelAnimation();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800389 }
chaviwa8f07a72019-05-01 16:25:39 -0700390 removeStartingWindow();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800391 updateReportedVisibilityLocked();
392 }
393
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800394 void updateReportedVisibilityLocked() {
395 if (appToken == null) {
396 return;
397 }
398
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700399 if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700400 final int count = mChildren.size();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800401
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700402 mReportedVisibilityResults.reset();
403
404 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700405 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700406 win.updateReportedVisibility(mReportedVisibilityResults);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800407 }
408
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700409 int numInteresting = mReportedVisibilityResults.numInteresting;
410 int numVisible = mReportedVisibilityResults.numVisible;
411 int numDrawn = mReportedVisibilityResults.numDrawn;
412 boolean nowGone = mReportedVisibilityResults.nowGone;
413
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700414 boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200415 boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting && !isHidden();
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700416 if (!nowGone) {
417 // If the app is not yet gone, then it can only become visible/drawn.
418 if (!nowDrawn) {
419 nowDrawn = reportedDrawn;
420 }
421 if (!nowVisible) {
422 nowVisible = reportedVisible;
423 }
424 }
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800425 if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800426 + numInteresting + " visible=" + numVisible);
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700427 if (nowDrawn != reportedDrawn) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800428 if (mActivityRecord != null) {
429 mActivityRecord.onWindowsDrawn(nowDrawn, SystemClock.uptimeMillis());
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700430 }
431 reportedDrawn = nowDrawn;
432 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800433 if (nowVisible != reportedVisible) {
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700434 if (DEBUG_VISIBILITY) Slog.v(TAG,
435 "Visibility changed in " + this + ": vis=" + nowVisible);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800436 reportedVisible = nowVisible;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800437 if (mActivityRecord != null) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800438 if (nowVisible) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800439 onWindowsVisible();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800440 } else {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800441 onWindowsGone();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800442 }
443 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800444 }
445 }
446
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800447 private void onWindowsGone() {
448 if (mActivityRecord == null) {
449 return;
450 }
451 if (DEBUG_VISIBILITY) {
452 Slog.v(TAG_WM, "Reporting gone in " + mActivityRecord.appToken);
453 }
454 mActivityRecord.onWindowsGone();
455 }
456
457 private void onWindowsVisible() {
458 if (mActivityRecord == null) {
459 return;
460 }
461 if (DEBUG_VISIBILITY) {
462 Slog.v(TAG_WM, "Reporting visible in " + mActivityRecord.appToken);
463 }
464 mActivityRecord.onWindowsVisible();
465 }
466
Wale Ogunwale89973222017-04-23 18:39:45 -0700467 boolean isClientHidden() {
468 return mClientHidden;
469 }
470
471 void setClientHidden(boolean hideClient) {
472 if (mClientHidden == hideClient || (hideClient && mDeferHidingClient)) {
473 return;
474 }
Jorim Jaggi067b5bf2018-02-23 17:42:39 +0100475 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "setClientHidden: " + this
476 + " clientHidden=" + hideClient + " Callers=" + Debug.getCallers(5));
Wale Ogunwale89973222017-04-23 18:39:45 -0700477 mClientHidden = hideClient;
478 sendAppVisibilityToClients();
479 }
480
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800481 void setVisibility(boolean visible, boolean deferHidingClient) {
482 final AppTransition appTransition = getDisplayContent().mAppTransition;
483
484 // Don't set visibility to false if we were already not visible. This prevents WM from
485 // adding the app to the closing app list which doesn't make sense for something that is
486 // already not visible. However, set visibility to true even if we are already visible.
487 // This makes sure the app is added to the opening apps list so that the right
488 // transition can be selected.
489 // TODO: Probably a good idea to separate the concept of opening/closing apps from the
490 // concept of setting visibility...
491 if (!visible && hiddenRequested) {
492
493 if (!deferHidingClient && mDeferHidingClient) {
494 // We previously deferred telling the client to hide itself when visibility was
495 // initially set to false. Now we would like it to hide, so go ahead and set it.
496 mDeferHidingClient = deferHidingClient;
497 setClientHidden(true);
498 }
499 return;
500 }
501
502 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) {
503 Slog.v(TAG_WM, "setAppVisibility("
504 + appToken + ", visible=" + visible + "): " + appTransition
505 + " hidden=" + isHidden() + " hiddenRequested="
506 + hiddenRequested + " Callers=" + Debug.getCallers(6));
507 }
508
509 final DisplayContent displayContent = getDisplayContent();
510 displayContent.mOpeningApps.remove(this);
511 displayContent.mClosingApps.remove(this);
Evan Roskyb1e75f72019-04-26 20:23:26 -0700512 if (isInChangeTransition()) {
513 clearChangeLeash(getPendingTransaction(), true /* cancel */);
514 }
515 displayContent.mChangingApps.remove(this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800516 waitingToShow = false;
517 hiddenRequested = !visible;
518 mDeferHidingClient = deferHidingClient;
519
520 if (!visible) {
521 // If the app is dead while it was visible, we kept its dead window on screen.
522 // Now that the app is going invisible, we can remove it. It will be restarted
523 // if made visible again.
524 removeDeadWindows();
525 } else {
526 if (!appTransition.isTransitionSet()
527 && appTransition.isReady()) {
528 // Add the app mOpeningApps if transition is unset but ready. This means
529 // we're doing a screen freeze, and the unfreeze will wait for all opening
530 // apps to be ready.
531 displayContent.mOpeningApps.add(this);
532 }
533 startingMoved = false;
534 // If the token is currently hidden (should be the common case), or has been
535 // stopped, then we need to set up to wait for its windows to be ready.
536 if (isHidden() || mAppStopped) {
537 clearAllDrawn();
538
539 // If the app was already visible, don't reset the waitingToShow state.
540 if (isHidden()) {
541 waitingToShow = true;
542 }
543 }
544
545 // In the case where we are making an app visible but holding off for a transition,
546 // we still need to tell the client to make its windows visible so they get drawn.
547 // Otherwise, we will wait on performing the transition until all windows have been
548 // drawn, they never will be, and we are sad.
549 setClientHidden(false);
550
551 requestUpdateWallpaperIfNeeded();
552
553 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "No longer Stopped: " + this);
554 mAppStopped = false;
555
556 transferStartingWindowFromHiddenAboveTokenIfNeeded();
557 }
558
559 // If we are preparing an app transition, then delay changing
560 // the visibility of this token until we execute that transition.
561 if (okToAnimate() && appTransition.isTransitionSet()) {
562 inPendingTransaction = true;
563 if (visible) {
564 displayContent.mOpeningApps.add(this);
565 mEnteringAnimation = true;
566 } else {
567 displayContent.mClosingApps.add(this);
568 mEnteringAnimation = false;
569 }
570 if (appTransition.getAppTransition()
571 == WindowManager.TRANSIT_TASK_OPEN_BEHIND) {
572 // We're launchingBehind, add the launching activity to mOpeningApps.
573 final WindowState win = getDisplayContent().findFocusedWindow();
574 if (win != null) {
575 final AppWindowToken focusedToken = win.mAppToken;
576 if (focusedToken != null) {
577 if (DEBUG_APP_TRANSITIONS) {
578 Slog.d(TAG_WM, "TRANSIT_TASK_OPEN_BEHIND, "
579 + " adding " + focusedToken + " to mOpeningApps");
580 }
581 // Force animation to be loaded.
582 focusedToken.setHidden(true);
583 displayContent.mOpeningApps.add(focusedToken);
584 }
585 }
586 }
Garfield Tanb6776602019-02-20 14:44:26 -0800587 // Changes in opening apps and closing apps may cause orientation change.
588 reportDescendantOrientationChangeIfNeeded();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800589 return;
590 }
591
592 commitVisibility(null, visible, TRANSIT_UNSET, true, mVoiceInteraction);
593 updateReportedVisibilityLocked();
594 }
595
596 boolean commitVisibility(WindowManager.LayoutParams lp,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700597 boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
598
599 boolean delayed = false;
600 inPendingTransaction = false;
Wale Ogunwale9e4721f2017-05-23 19:37:30 -0700601 // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually
602 // been set by the app now.
603 mHiddenSetFromTransferredStartingWindow = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700604
605 // Allow for state changes and animation to be applied if:
606 // * token is transitioning visibility state
607 // * or the token was marked as hidden and is exiting before we had a chance to play the
608 // transition animation
609 // * or this is an opening app and windows are being replaced.
610 boolean visibilityChanged = false;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200611 if (isHidden() == visible || (isHidden() && mIsExiting) || (visible && waitingForReplacement())) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800612 final AccessibilityController accessibilityController =
613 mWmService.mAccessibilityController;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700614 boolean changed = false;
615 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM,
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200616 "Changing app " + this + " hidden=" + isHidden() + " performLayout=" + performLayout);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700617
618 boolean runningAppAnimation = false;
619
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100620 if (transit != WindowManager.TRANSIT_UNSET) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200621 if (applyAnimationLocked(lp, transit, visible, isVoiceInteraction)) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700622 delayed = runningAppAnimation = true;
623 }
624 final WindowState window = findMainWindow();
Rhed Jao02655dc2018-10-30 20:44:52 +0800625 if (window != null && accessibilityController != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700626 accessibilityController.onAppWindowTransitionLocked(window, transit);
627 }
628 changed = true;
629 }
630
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700631 final int windowsCount = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700632 for (int i = 0; i < windowsCount; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700633 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700634 changed |= win.onAppVisibilityChanged(visible, runningAppAnimation);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700635 }
636
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200637 setHidden(!visible);
638 hiddenRequested = !visible;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700639 visibilityChanged = true;
640 if (!visible) {
641 stopFreezingScreen(true, true);
642 } else {
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700643 // If we are being set visible, and the starting window is not yet displayed,
644 // then make sure it doesn't get displayed.
645 if (startingWindow != null && !startingWindow.isDrawnLw()) {
chaviw15ad49f2019-04-24 15:05:39 -0700646 startingWindow.clearPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY);
647 startingWindow.mLegacyPolicyVisibilityAfterAnim = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700648 }
Jorim Jaggi38d44ec2017-06-14 16:04:59 -0700649
650 // We are becoming visible, so better freeze the screen with the windows that are
651 // getting visible so we also wait for them.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800652 forAllWindows(mWmService::makeWindowFreezingScreenIfNeededLocked, true);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700653 }
654
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800655 if (DEBUG_APP_TRANSITIONS) {
656 Slog.v(TAG_WM, "commitVisibility: " + this
657 + ": hidden=" + isHidden() + " hiddenRequested=" + hiddenRequested);
658 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700659
660 if (changed) {
Arthur Hung95b38a92018-07-20 18:56:12 +0800661 getDisplayContent().getInputMonitor().setUpdateInputWindowsNeededLw();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700662 if (performLayout) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800663 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700664 false /*updateInputWindows*/);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800665 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700666 }
Arthur Hung95b38a92018-07-20 18:56:12 +0800667 getDisplayContent().getInputMonitor().updateInputWindowsLw(false /*force*/);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700668 }
669 }
670
lumarkd14173e2019-03-27 19:14:33 +0800671 if (isReallyAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700672 delayed = true;
Jorim Jaggiab9fcb22018-03-15 23:46:12 +0100673 } else {
674
675 // We aren't animating anything, but exiting windows rely on the animation finished
676 // callback being called in case the AppWindowToken was pretending to be animating,
677 // which we might have done because we were in closing/opening apps list.
678 onAnimationFinished();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700679 }
680
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700681 for (int i = mChildren.size() - 1; i >= 0 && !delayed; i--) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100682 if ((mChildren.get(i)).isSelfOrChildAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700683 delayed = true;
684 }
685 }
686
687 if (visibilityChanged) {
688 if (visible && !delayed) {
689 // The token was made immediately visible, there will be no entrance animation.
690 // We need to inform the client the enter animation was finished.
691 mEnteringAnimation = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800692 mWmService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(
693 token);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700694 }
Robert Carr61b81112017-07-17 18:08:15 -0700695
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800696 // If we're becoming visible, immediately change client visibility as well. there seem
697 // to be some edge cases where we change our visibility but client visibility never gets
698 // updated.
Jorim Jaggi110839b2018-01-22 12:49:04 +0100699 // If we're becoming invisible, update the client visibility if we are not running an
700 // animation. Otherwise, we'll update client visibility in onAnimationFinished.
Jorim Jaggi3cad57f2018-02-20 18:32:01 +0100701 if (visible || !isReallyAnimating()) {
Jorim Jaggi110839b2018-01-22 12:49:04 +0100702 setClientHidden(!visible);
Jorim Jaggi4876b4a2018-01-11 15:43:49 +0100703 }
704
lumark588a3e82018-07-20 18:53:54 +0800705 if (!getDisplayContent().mClosingApps.contains(this)
706 && !getDisplayContent().mOpeningApps.contains(this)) {
chaviwa953fcf2018-03-01 12:00:39 -0800707 // The token is not closing nor opening, so even if there is an animation set, that
708 // doesn't mean that it goes through the normal app transition cycle so we have
709 // to inform the docked controller about visibility change.
710 // TODO(multi-display): notify docked divider on all displays where visibility was
711 // affected.
lumark588a3e82018-07-20 18:53:54 +0800712 getDisplayContent().getDockedDividerController().notifyAppVisibilityChanged();
chaviwa953fcf2018-03-01 12:00:39 -0800713
714 // Take the screenshot before possibly hiding the WSA, otherwise the screenshot
715 // will not be taken.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800716 mWmService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible);
chaviwa953fcf2018-03-01 12:00:39 -0800717 }
718
Robert Carre7cc44d2017-03-20 19:04:30 -0700719 // If we are hidden but there is no delay needed we immediately
720 // apply the Surface transaction so that the ActivityManager
Robert Carr61b81112017-07-17 18:08:15 -0700721 // can have some guarantee on the Surface state following
722 // setting the visibility. This captures cases like dismissing
723 // the docked or pinned stack where there is no app transition.
724 //
725 // In the case of a "Null" animation, there will be
726 // no animation but there will still be a transition set.
727 // We still need to delay hiding the surface such that it
728 // can be synchronized with showing the next surface in the transition.
lumark588a3e82018-07-20 18:53:54 +0800729 if (isHidden() && !delayed && !getDisplayContent().mAppTransition.isTransitionSet()) {
Robert Carr6914f082017-03-20 19:04:30 -0700730 SurfaceControl.openTransaction();
731 for (int i = mChildren.size() - 1; i >= 0; i--) {
732 mChildren.get(i).mWinAnimator.hide("immediately hidden");
733 }
734 SurfaceControl.closeTransaction();
735 }
Garfield Tanb6776602019-02-20 14:44:26 -0800736
737 // Visibility changes may cause orientation request change.
738 reportDescendantOrientationChangeIfNeeded();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700739 }
740
741 return delayed;
742 }
743
Garfield Tanb6776602019-02-20 14:44:26 -0800744 private void reportDescendantOrientationChangeIfNeeded() {
745 // Orientation request is exposed only when we're visible. Therefore visibility change
746 // will change requested orientation. Notify upward the hierarchy ladder to adjust
747 // configuration. This is important to cases where activities with incompatible
748 // orientations launch, or user goes back from an activity of bi-orientation to an
749 // activity with specified orientation.
750 if (mActivityRecord.getRequestedConfigurationOrientation() == getConfiguration().orientation
751 || getOrientationIgnoreVisibility() == SCREEN_ORIENTATION_UNSET) {
752 return;
753 }
754
755 final IBinder freezeToken =
756 mActivityRecord.mayFreezeScreenLocked(mActivityRecord.app)
757 ? mActivityRecord.appToken : null;
758 onDescendantOrientationChanged(freezeToken, mActivityRecord);
759 }
760
Jorim Jaggi87fdbcb2017-08-17 13:41:11 +0200761 /**
762 * @return The to top most child window for which {@link LayoutParams#isFullscreen()} returns
763 * true.
764 */
765 WindowState getTopFullscreenWindow() {
766 for (int i = mChildren.size() - 1; i >= 0; i--) {
767 final WindowState win = mChildren.get(i);
768 if (win != null && win.mAttrs.isFullscreen()) {
769 return win;
770 }
771 }
772 return null;
773 }
774
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800775 WindowState findMainWindow() {
Matthew Ng53e66b22018-01-12 17:13:13 -0800776 return findMainWindow(true);
777 }
778
779 /**
780 * Finds the main window that either has type base application or application starting if
781 * requested.
782 *
783 * @param includeStartingApp Allow to search application-starting windows to also be returned.
784 * @return The main window of type base application or application starting if requested.
785 */
786 WindowState findMainWindow(boolean includeStartingApp) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700787 WindowState candidate = null;
Matthew Ng53e66b22018-01-12 17:13:13 -0800788 for (int j = mChildren.size() - 1; j >= 0; --j) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700789 final WindowState win = mChildren.get(j);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700790 final int type = win.mAttrs.type;
791 // No need to loop through child window as base application and starting types can't be
792 // child windows.
Matthew Ng53e66b22018-01-12 17:13:13 -0800793 if (type == TYPE_BASE_APPLICATION
794 || (includeStartingApp && type == TYPE_APPLICATION_STARTING)) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700795 // In cases where there are multiple windows, we prefer the non-exiting window. This
Sungsoo Lim0d3d1f82015-12-02 14:47:59 +0900796 // happens for example when replacing windows during an activity relaunch. When
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700797 // constructing the animation, we want the new window, not the exiting one.
Wale Ogunwalec48a3542016-02-19 15:18:45 -0800798 if (win.mAnimatingExit) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700799 candidate = win;
800 } else {
801 return win;
802 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800803 }
804 }
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700805 return candidate;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800806 }
807
Wale Ogunwale6cae7652015-12-26 07:36:26 -0800808 boolean windowsAreFocusable() {
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800809 if (mTargetSdk < Build.VERSION_CODES.Q) {
810 final int pid = mActivityRecord != null
811 ? (mActivityRecord.app != null ? mActivityRecord.app.getPid() : 0) : 0;
812 final AppWindowToken topFocusedAppOfMyProcess =
813 mWmService.mRoot.mTopFocusedAppByProcess.get(pid);
814 if (topFocusedAppOfMyProcess != null && topFocusedAppOfMyProcess != this) {
815 // For the apps below Q, there can be only one app which has the focused window per
816 // process, because legacy apps may not be ready for a multi-focus system.
817 return false;
818 }
819 }
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700820 return getWindowConfiguration().canReceiveKeys() || mAlwaysFocusable;
Wale Ogunwaled045c822015-12-02 09:14:28 -0800821 }
822
Wale Ogunwale571771c2016-08-26 13:18:50 -0700823 @Override
Wale Ogunwale44f21802016-09-02 12:49:48 -0700824 boolean isVisible() {
Wale Ogunwalee471be62016-10-03 07:53:55 -0700825 // If the app token isn't hidden then it is considered visible and there is no need to check
826 // its children windows to see if they are visible.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200827 return !isHidden();
Wale Ogunwale44f21802016-09-02 12:49:48 -0700828 }
829
830 @Override
Wale Ogunwalee287e192017-04-21 09:30:12 -0700831 void removeImmediately() {
832 onRemovedFromDisplay();
Yunfan Chen3a77f282018-12-12 15:47:52 -0800833 if (mActivityRecord != null) {
834 mActivityRecord.unregisterConfigurationChangeListener(this);
835 }
Wale Ogunwalee287e192017-04-21 09:30:12 -0700836 super.removeImmediately();
837 }
838
839 @Override
Wale Ogunwale571771c2016-08-26 13:18:50 -0700840 void removeIfPossible() {
Craig Mautnere3119b72015-01-20 15:02:36 -0800841 mIsExiting = false;
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800842 removeAllWindowsIfPossible();
Bryce Lee6d410262017-02-28 15:30:17 -0800843 removeImmediately();
Craig Mautnere3119b72015-01-20 15:02:36 -0800844 }
845
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700846 @Override
847 boolean checkCompleteDeferredRemoval() {
848 if (mIsExiting) {
849 removeIfPossible();
850 }
851 return super.checkCompleteDeferredRemoval();
852 }
853
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700854 void onRemovedFromDisplay() {
Wale Ogunwalee287e192017-04-21 09:30:12 -0700855 if (mRemovingFromDisplay) {
856 return;
857 }
858 mRemovingFromDisplay = true;
859
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700860 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app token: " + this);
861
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800862 boolean delayed = commitVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700863
lumark588a3e82018-07-20 18:53:54 +0800864 getDisplayContent().mOpeningApps.remove(this);
Evan Rosky2289ba12018-11-19 18:28:18 -0800865 getDisplayContent().mChangingApps.remove(this);
lumark588a3e82018-07-20 18:53:54 +0800866 getDisplayContent().mUnknownAppVisibilityController.appRemovedOrHidden(this);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800867 mWmService.mTaskSnapshotController.onAppRemoved(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700868 waitingToShow = false;
lumark588a3e82018-07-20 18:53:54 +0800869 if (getDisplayContent().mClosingApps.contains(this)) {
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700870 delayed = true;
lumark588a3e82018-07-20 18:53:54 +0800871 } else if (getDisplayContent().mAppTransition.isTransitionSet()) {
872 getDisplayContent().mClosingApps.add(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700873 delayed = true;
874 }
875
876 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app " + this + " delayed=" + delayed
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200877 + " animation=" + getAnimation() + " animating=" + isSelfAnimating());
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700878
879 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: "
880 + this + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
881
chaviwa8f07a72019-05-01 16:25:39 -0700882 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800883 removeStartingWindow();
Jorim Jaggi19be6052017-08-03 18:33:43 +0200884 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800885
Winson Chung87e5d552017-04-05 11:49:38 -0700886 // If this window was animating, then we need to ensure that the app transition notifies
lumark588a3e82018-07-20 18:53:54 +0800887 // that animations have completed in DisplayContent.handleAnimatingStoppedAndTransition(),
888 // so add to that list now
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200889 if (isSelfAnimating()) {
lumark588a3e82018-07-20 18:53:54 +0800890 getDisplayContent().mNoAnimationNotifyOnTransitionFinished.add(token);
Winson Chung87e5d552017-04-05 11:49:38 -0700891 }
892
Wale Ogunwalee287e192017-04-21 09:30:12 -0700893 final TaskStack stack = getStack();
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700894 if (delayed && !isEmpty()) {
895 // set the token aside because it has an active animation to be finished
896 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM,
897 "removeAppToken make exiting: " + this);
Wale Ogunwalee287e192017-04-21 09:30:12 -0700898 if (stack != null) {
899 stack.mExitingAppTokens.add(this);
900 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700901 mIsExiting = true;
902 } else {
903 // Make sure there is no animation running on this token, so any windows associated
904 // with it will be removed as soon as their animations are complete
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200905 cancelAnimation();
Wale Ogunwale3106ae012017-05-16 08:56:37 -0700906 if (stack != null) {
907 stack.mExitingAppTokens.remove(this);
908 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700909 removeIfPossible();
910 }
911
912 removed = true;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700913 stopFreezingScreen(true, true);
Bryce Lee6d410262017-02-28 15:30:17 -0800914
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800915 final DisplayContent dc = getDisplayContent();
916 if (dc.mFocusedApp == this) {
917 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + this
918 + " displayId=" + dc.getDisplayId());
919 dc.setFocusedApp(null);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800920 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700921 }
Riddle Hsu192fe762019-01-15 23:41:57 +0800922 if (mLetterbox != null) {
923 mLetterbox.destroy();
924 mLetterbox = null;
925 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700926
927 if (!delayed) {
928 updateReportedVisibilityLocked();
929 }
Wale Ogunwalee287e192017-04-21 09:30:12 -0700930
931 mRemovingFromDisplay = false;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700932 }
933
Chong Zhange05bcb12016-07-26 17:47:29 -0700934 void clearAnimatingFlags() {
Chong Zhangb0d26702016-08-12 16:03:29 -0700935 boolean wallpaperMightChange = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700936 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700937 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700938 wallpaperMightChange |= win.clearAnimatingFlags();
Chong Zhange05bcb12016-07-26 17:47:29 -0700939 }
Chong Zhangb0d26702016-08-12 16:03:29 -0700940 if (wallpaperMightChange) {
941 requestUpdateWallpaperIfNeeded();
942 }
Chong Zhange05bcb12016-07-26 17:47:29 -0700943 }
944
Robert Carre12aece2016-02-02 22:43:27 -0800945 void destroySurfaces() {
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700946 destroySurfaces(false /*cleanupOnResume*/);
947 }
948
949 /**
950 * Destroy surfaces which have been marked as eligible by the animator, taking care to ensure
951 * the client has finished with them.
952 *
953 * @param cleanupOnResume whether this is done when app is resumed without fully stopped. If
954 * set to true, destroy only surfaces of removed windows, and clear relevant flags of the
955 * others so that they are ready to be reused. If set to false (common case), destroy all
956 * surfaces that's eligible, if the app is already stopped.
957 */
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700958 private void destroySurfaces(boolean cleanupOnResume) {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700959 boolean destroyedSomething = false;
Jorim Jaggia5e10572017-11-15 14:36:26 +0100960
961 // Copying to a different list as multiple children can be removed.
Jorim Jaggi59f3e922018-01-05 15:40:32 +0100962 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
Jorim Jaggia5e10572017-11-15 14:36:26 +0100963 for (int i = children.size() - 1; i >= 0; i--) {
964 final WindowState win = children.get(i);
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700965 destroyedSomething |= win.destroySurface(cleanupOnResume, mAppStopped);
Robert Carre12aece2016-02-02 22:43:27 -0800966 }
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700967 if (destroyedSomething) {
968 final DisplayContent dc = getDisplayContent();
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700969 dc.assignWindowLayers(true /*setLayoutNeeded*/);
Adrian Roos23df3a32018-03-15 15:41:13 +0100970 updateLetterboxSurface(null);
Robert Carre12aece2016-02-02 22:43:27 -0800971 }
972 }
973
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800974 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700975 * Notify that the app is now resumed, and it was not stopped before, perform a clean
976 * up of the surfaces
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800977 */
Jorim Jaggibae01b12017-04-11 16:29:10 -0700978 void notifyAppResumed(boolean wasStopped) {
Chong Zhangad24f962016-08-25 12:12:33 -0700979 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppResumed: wasStopped=" + wasStopped
Jorim Jaggibae01b12017-04-11 16:29:10 -0700980 + " " + this);
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700981 mAppStopped = false;
chaviwd3bf08d2017-08-01 17:24:59 -0700982 // Allow the window to turn the screen on once the app is resumed again.
983 setCanTurnScreenOn(true);
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700984 if (!wasStopped) {
985 destroySurfaces(true /*cleanupOnResume*/);
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800986 }
Robert Carre12aece2016-02-02 22:43:27 -0800987 }
988
Chong Zhangbef461f2015-10-27 11:38:24 -0700989 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700990 * Notify that the app has stopped, and it is okay to destroy any surfaces which were
991 * keeping alive in case they were still being used.
992 */
993 void notifyAppStopped() {
994 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: " + this);
995 mAppStopped = true;
996 destroySurfaces();
997 // Remove any starting window that was added for this app if they are still around.
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800998 removeStartingWindow();
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700999 }
1000
Chong Zhang92147042016-05-09 12:47:11 -07001001 void clearAllDrawn() {
1002 allDrawn = false;
1003 deferClearAllDrawn = false;
Chong Zhangbef461f2015-10-27 11:38:24 -07001004 }
1005
Bryce Lee6d410262017-02-28 15:30:17 -08001006 Task getTask() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001007 return (Task) getParent();
Bryce Lee6d410262017-02-28 15:30:17 -08001008 }
1009
Jorim Jaggi3878ca32017-02-02 17:13:05 -08001010 TaskStack getStack() {
1011 final Task task = getTask();
1012 if (task != null) {
1013 return task.mStack;
1014 } else {
1015 return null;
1016 }
1017 }
1018
Bryce Lee6d410262017-02-28 15:30:17 -08001019 @Override
Riddle Hsu3a4bb612019-01-31 00:02:22 +08001020 void onParentChanged() {
1021 super.onParentChanged();
Bryce Lee6d410262017-02-28 15:30:17 -08001022
Robert Carred3e83b2017-04-21 13:26:55 -07001023 final Task task = getTask();
1024
Bryce Lee6d410262017-02-28 15:30:17 -08001025 // When the associated task is {@code null}, the {@link AppWindowToken} can no longer
1026 // access visual elements like the {@link DisplayContent}. We must remove any associations
1027 // such as animations.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001028 if (!mReparenting) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001029 if (task == null) {
1030 // It is possible we have been marked as a closing app earlier. We must remove ourselves
1031 // from this list so we do not participate in any future animations.
lumark588a3e82018-07-20 18:53:54 +08001032 getDisplayContent().mClosingApps.remove(this);
Robert Carred3e83b2017-04-21 13:26:55 -07001033 } else if (mLastParent != null && mLastParent.mStack != null) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001034 task.mStack.mExitingAppTokens.remove(this);
1035 }
Bryce Lee6d410262017-02-28 15:30:17 -08001036 }
Jorim Jaggi6de61012018-03-19 14:53:23 +01001037 final TaskStack stack = getStack();
1038
1039 // If we reparent, make sure to remove ourselves from the old animation registry.
1040 if (mAnimatingAppWindowTokenRegistry != null) {
1041 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
1042 }
1043 mAnimatingAppWindowTokenRegistry = stack != null
1044 ? stack.getAnimatingAppWindowTokenRegistry()
1045 : null;
1046
Robert Carred3e83b2017-04-21 13:26:55 -07001047 mLastParent = task;
chaviwdcf76ec2019-01-11 16:48:46 -08001048
1049 updateColorTransform();
Bryce Lee6d410262017-02-28 15:30:17 -08001050 }
1051
Wale Ogunwalefa854eb2016-09-20 13:43:52 -07001052 void postWindowRemoveStartingWindowCleanup(WindowState win) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001053 // TODO: Something smells about the code below...Is there a better way?
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001054 if (startingWindow == win) {
1055 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Notify removed startingWindow " + win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001056 removeStartingWindow();
Wale Ogunwale6c459212017-05-17 08:56:03 -07001057 } else if (mChildren.size() == 0) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001058 // If this is the last window and we had requested a starting transition window,
1059 // well there is no point now.
Jorim Jaggi02886a82016-12-06 09:10:06 -08001060 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Nulling last startingData");
chaviwa8f07a72019-05-01 16:25:39 -07001061 mStartingData = null;
Wale Ogunwale6c459212017-05-17 08:56:03 -07001062 if (mHiddenSetFromTransferredStartingWindow) {
1063 // We set the hidden state to false for the token from a transferred starting window.
1064 // We now reset it back to true since the starting window was the last window in the
1065 // token.
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001066 setHidden(true);
Wale Ogunwale6c459212017-05-17 08:56:03 -07001067 }
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01001068 } else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001069 // If this is the last window except for a starting transition window,
1070 // we need to get rid of the starting transition.
Jorim Jaggie4b0f282017-05-17 15:10:29 +02001071 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Last window, removing starting window "
1072 + win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001073 removeStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001074 }
1075 }
1076
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001077 void removeDeadWindows() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001078 for (int winNdx = mChildren.size() - 1; winNdx >= 0; --winNdx) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001079 WindowState win = mChildren.get(winNdx);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001080 if (win.mAppDied) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001081 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.w(TAG,
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001082 "removeDeadWindows: " + win);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001083 // Set mDestroying, we don't want any animation or delayed removal here.
1084 win.mDestroying = true;
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001085 // Also removes child windows.
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001086 win.removeIfPossible();
Chong Zhang112eb8c2015-11-02 11:17:00 -08001087 }
1088 }
1089 }
1090
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001091 boolean hasWindowsAlive() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001092 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001093 // No need to loop through child windows as the answer should be the same as that of the
1094 // parent window.
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001095 if (!(mChildren.get(i)).mAppDied) {
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001096 return true;
1097 }
1098 }
1099 return false;
1100 }
1101
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001102 void setWillReplaceWindows(boolean animate) {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001103 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
1104 "Marking app token " + this + " with replacing windows.");
Robert Carra1eb4392015-12-10 12:43:51 -08001105
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001106 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001107 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001108 w.setWillReplaceWindow(animate);
Robert Carra1eb4392015-12-10 12:43:51 -08001109 }
Robert Carra1eb4392015-12-10 12:43:51 -08001110 }
1111
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001112 void setWillReplaceChildWindows() {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001113 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Marking app token " + this
Robert Carr23fa16b2016-01-13 13:19:58 -08001114 + " with replacing child windows.");
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001115 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001116 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001117 w.setWillReplaceChildWindows();
Robert Carr23fa16b2016-01-13 13:19:58 -08001118 }
1119 }
1120
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001121 void clearWillReplaceWindows() {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001122 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
1123 "Resetting app token " + this + " of replacing window marks.");
Chong Zhangf596cd52016-01-05 13:42:44 -08001124
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001125 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001126 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001127 w.clearWillReplaceWindow();
Chong Zhangf596cd52016-01-05 13:42:44 -08001128 }
1129 }
1130
Chong Zhang4d7369a2016-04-25 16:09:14 -07001131 void requestUpdateWallpaperIfNeeded() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001132 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001133 final WindowState w = mChildren.get(i);
Chong Zhang4d7369a2016-04-25 16:09:14 -07001134 w.requestUpdateWallpaperIfNeeded();
1135 }
1136 }
1137
Chong Zhangd78ddb42016-03-02 17:01:14 -08001138 boolean isRelaunching() {
1139 return mPendingRelaunchCount > 0;
1140 }
1141
Robert Carr68375192017-06-13 12:41:53 -07001142 boolean shouldFreezeBounds() {
1143 final Task task = getTask();
1144
1145 // For freeform windows, we can't freeze the bounds at the moment because this would make
1146 // the resizing unresponsive.
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001147 if (task == null || task.inFreeformWindowingMode()) {
Robert Carr68375192017-06-13 12:41:53 -07001148 return false;
1149 }
1150
1151 // We freeze the bounds while drag resizing to deal with the time between
1152 // the divider/drag handle being released, and the handling it's new
1153 // configuration. If we are relaunched outside of the drag resizing state,
1154 // we need to be careful not to do this.
1155 return getTask().isDragResizing();
1156 }
1157
Chong Zhangd78ddb42016-03-02 17:01:14 -08001158 void startRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001159 if (shouldFreezeBounds()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08001160 freezeBounds();
1161 }
Robert Carrd5c7dd62017-03-08 10:39:30 -08001162
1163 // In the process of tearing down before relaunching, the app will
1164 // try and clean up it's child surfaces. We need to prevent this from
1165 // happening, so we sever the children, transfering their ownership
1166 // from the client it-self to the parent surface (owned by us).
Robert Carr29daa922018-04-27 11:56:48 -07001167 detachChildren();
1168
1169 mPendingRelaunchCount++;
1170 }
1171
1172 void detachChildren() {
Robert Carrfd8e93b2018-05-10 13:40:25 -07001173 SurfaceControl.openTransaction();
Robert Carrd5c7dd62017-03-08 10:39:30 -08001174 for (int i = mChildren.size() - 1; i >= 0; i--) {
1175 final WindowState w = mChildren.get(i);
1176 w.mWinAnimator.detachChildren();
1177 }
Robert Carrfd8e93b2018-05-10 13:40:25 -07001178 SurfaceControl.closeTransaction();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001179 }
1180
1181 void finishRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001182 unfreezeBounds();
1183
Chong Zhangd78ddb42016-03-02 17:01:14 -08001184 if (mPendingRelaunchCount > 0) {
1185 mPendingRelaunchCount--;
Bryce Lee081554b2017-05-25 07:52:12 -07001186 } else {
1187 // Update keyguard flags upon finishing relaunch.
1188 checkKeyguardFlagsChanged();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001189 }
1190 }
1191
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001192 void clearRelaunching() {
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001193 if (mPendingRelaunchCount == 0) {
1194 return;
1195 }
Robert Carr68375192017-06-13 12:41:53 -07001196 unfreezeBounds();
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001197 mPendingRelaunchCount = 0;
1198 }
1199
Wale Ogunwale07bcab72016-10-14 15:30:09 -07001200 /**
1201 * Returns true if the new child window we are adding to this token is considered greater than
1202 * the existing child window in this token in terms of z-order.
1203 */
1204 @Override
1205 protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
1206 WindowState existingWindow) {
1207 final int type1 = newWindow.mAttrs.type;
1208 final int type2 = existingWindow.mAttrs.type;
1209
1210 // Base application windows should be z-ordered BELOW all other windows in the app token.
1211 if (type1 == TYPE_BASE_APPLICATION && type2 != TYPE_BASE_APPLICATION) {
1212 return false;
1213 } else if (type1 != TYPE_BASE_APPLICATION && type2 == TYPE_BASE_APPLICATION) {
1214 return true;
1215 }
1216
1217 // Starting windows should be z-ordered ABOVE all other windows in the app token.
1218 if (type1 == TYPE_APPLICATION_STARTING && type2 != TYPE_APPLICATION_STARTING) {
1219 return true;
1220 } else if (type1 != TYPE_APPLICATION_STARTING && type2 == TYPE_APPLICATION_STARTING) {
1221 return false;
1222 }
1223
1224 // Otherwise the new window is greater than the existing window.
1225 return true;
1226 }
1227
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001228 @Override
Robert Carra1eb4392015-12-10 12:43:51 -08001229 void addWindow(WindowState w) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001230 super.addWindow(w);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001231
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001232 boolean gotReplacementWindow = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001233 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001234 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001235 gotReplacementWindow |= candidate.setReplacementWindowIfNeeded(w);
1236 }
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001237
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001238 // if we got a replacement window, reset the timeout to give drawing more time
1239 if (gotReplacementWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001240 mWmService.scheduleWindowReplacementTimeouts(this);
Robert Carra1eb4392015-12-10 12:43:51 -08001241 }
Jorim Jaggife762342016-10-13 14:33:27 +02001242 checkKeyguardFlagsChanged();
1243 }
1244
1245 @Override
1246 void removeChild(WindowState child) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001247 if (!mChildren.contains(child)) {
1248 // This can be true when testing.
1249 return;
1250 }
Jorim Jaggife762342016-10-13 14:33:27 +02001251 super.removeChild(child);
1252 checkKeyguardFlagsChanged();
Adrian Roos23df3a32018-03-15 15:41:13 +01001253 updateLetterboxSurface(child);
Robert Carra1eb4392015-12-10 12:43:51 -08001254 }
1255
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001256 private boolean waitingForReplacement() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001257 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001258 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001259 if (candidate.waitingForReplacement()) {
Robert Carra1eb4392015-12-10 12:43:51 -08001260 return true;
1261 }
1262 }
1263 return false;
1264 }
1265
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001266 void onWindowReplacementTimeout() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001267 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001268 (mChildren.get(i)).onWindowReplacementTimeout();
Robert Carra1eb4392015-12-10 12:43:51 -08001269 }
1270 }
1271
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001272 void reparent(Task task, int position) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001273 if (DEBUG_ADD_REMOVE) {
1274 Slog.i(TAG_WM, "reparent: moving app token=" + this
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001275 + " to task=" + task.mTaskId + " at " + position);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001276 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001277 if (task == null) {
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001278 throw new IllegalArgumentException("reparent: could not find task");
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001279 }
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001280 final Task currentTask = getTask();
1281 if (task == currentTask) {
Winson Chung30480042017-01-26 10:55:34 -08001282 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001283 "window token=" + this + " already child of task=" + currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001284 }
Bryce Lee6d410262017-02-28 15:30:17 -08001285
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001286 if (currentTask.mStack != task.mStack) {
Bryce Lee6d410262017-02-28 15:30:17 -08001287 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001288 "window token=" + this + " current task=" + currentTask
Bryce Lee6d410262017-02-28 15:30:17 -08001289 + " belongs to a different stack than " + task);
1290 }
1291
Winson Chung30480042017-01-26 10:55:34 -08001292 if (DEBUG_ADD_REMOVE) Slog.i(TAG, "reParentWindowToken: removing window token=" + this
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001293 + " from task=" + currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001294 final DisplayContent prevDisplayContent = getDisplayContent();
1295
Bryce Lee6d410262017-02-28 15:30:17 -08001296 mReparenting = true;
1297
Winson Chung30480042017-01-26 10:55:34 -08001298 getParent().removeChild(this);
1299 task.addChild(this, position);
1300
Bryce Lee6d410262017-02-28 15:30:17 -08001301 mReparenting = false;
1302
Winson Chung30480042017-01-26 10:55:34 -08001303 // Relayout display(s).
1304 final DisplayContent displayContent = task.getDisplayContent();
1305 displayContent.setLayoutNeeded();
1306 if (prevDisplayContent != displayContent) {
1307 onDisplayChanged(displayContent);
1308 prevDisplayContent.setLayoutNeeded();
1309 }
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001310 getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
Winson Chung30480042017-01-26 10:55:34 -08001311 }
1312
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001313 @Override
1314 void onDisplayChanged(DisplayContent dc) {
1315 DisplayContent prevDc = mDisplayContent;
1316 super.onDisplayChanged(dc);
Evan Roskyb1e75f72019-04-26 20:23:26 -07001317 if (prevDc == null || prevDc == mDisplayContent) {
Evan Rosky25b56192019-02-06 16:10:56 -08001318 return;
1319 }
1320 if (prevDc.mChangingApps.contains(this)) {
1321 // This gets called *after* the AppWindowToken has been reparented to the new display.
1322 // That reparenting resulted in this window changing modes (eg. FREEFORM -> FULLSCREEN),
1323 // so this token is now "frozen" while waiting for the animation to start on prevDc
1324 // (which will be cancelled since the window is no-longer a child). However, since this
1325 // is no longer a child of prevDc, this won't be notified of the cancelled animation,
1326 // so we need to cancel the change transition here.
1327 clearChangeLeash(getPendingTransaction(), true /* cancel */);
1328 }
1329 if (prevDc.mFocusedApp == this) {
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001330 prevDc.setFocusedApp(null);
lumarkbf844642018-11-23 17:11:36 +08001331 final TaskStack stack = dc.getTopStack();
1332 if (stack != null) {
1333 final Task task = stack.getTopChild();
1334 if (task != null && task.getTopChild() == this) {
1335 dc.setFocusedApp(this);
1336 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001337 }
1338 }
Riddle Hsu192fe762019-01-15 23:41:57 +08001339
Evan Roskyb1e75f72019-04-26 20:23:26 -07001340 if (mLetterbox != null) {
Riddle Hsu192fe762019-01-15 23:41:57 +08001341 mLetterbox.onMovedToDisplay(mDisplayContent.getDisplayId());
1342 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001343 }
1344
Jorim Jaggi0429f352015-12-22 16:29:16 +01001345 /**
1346 * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds
1347 * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even
1348 * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen
1349 * with a queue.
1350 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001351 private void freezeBounds() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001352 final Task task = getTask();
1353 mFrozenBounds.offer(new Rect(task.mPreparedFrozenBounds));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001354
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001355 if (task.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001356 // We didn't call prepareFreezingBounds on the task, so use the current value.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001357 mFrozenMergedConfig.offer(new Configuration(task.getConfiguration()));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001358 } else {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001359 mFrozenMergedConfig.offer(new Configuration(task.mPreparedFrozenMergedConfig));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001360 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001361 // Calling unset() to make it equal to Configuration.EMPTY.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001362 task.mPreparedFrozenMergedConfig.unset();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001363 }
1364
1365 /**
1366 * Unfreezes the previously frozen bounds. See {@link #freezeBounds}.
1367 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001368 private void unfreezeBounds() {
Robert Carr68375192017-06-13 12:41:53 -07001369 if (mFrozenBounds.isEmpty()) {
1370 return;
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001371 }
Robert Carr68375192017-06-13 12:41:53 -07001372 mFrozenBounds.remove();
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001373 if (!mFrozenMergedConfig.isEmpty()) {
1374 mFrozenMergedConfig.remove();
1375 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001376 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001377 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001378 win.onUnfreezeBounds();
Jorim Jaggi4846ee32016-01-07 17:39:12 +01001379 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001380 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001381 }
1382
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001383 void setAppLayoutChanges(int changes, String reason) {
1384 if (!mChildren.isEmpty()) {
1385 final DisplayContent dc = getDisplayContent();
1386 dc.pendingLayoutChanges |= changes;
1387 if (DEBUG_LAYOUT_REPEATS) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001388 mWmService.mWindowPlacerLocked.debugLayoutRepeats(reason, dc.pendingLayoutChanges);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001389 }
1390 }
1391 }
1392
1393 void removeReplacedWindowIfNeeded(WindowState replacement) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001394 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001395 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001396 if (win.removeReplacedWindowIfNeeded(replacement)) {
1397 return;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001398 }
1399 }
1400 }
1401
1402 void startFreezingScreen() {
1403 if (DEBUG_ORIENTATION) logWithStack(TAG, "Set freezing of " + appToken + ": hidden="
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001404 + isHidden() + " freezing=" + mFreezingScreen + " hiddenRequested="
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001405 + hiddenRequested);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001406 if (!hiddenRequested) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001407 if (!mFreezingScreen) {
1408 mFreezingScreen = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001409 mWmService.registerAppFreezeListener(this);
1410 mWmService.mAppsFreezingScreen++;
1411 if (mWmService.mAppsFreezingScreen == 1) {
1412 mWmService.startFreezingDisplayLocked(0, 0, getDisplayContent());
1413 mWmService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
1414 mWmService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001415 }
1416 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001417 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001418 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001419 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001420 w.onStartFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001421 }
1422 }
1423 }
1424
1425 void stopFreezingScreen(boolean unfreezeSurfaceNow, boolean force) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001426 if (!mFreezingScreen) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001427 return;
1428 }
1429 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + this + " force=" + force);
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001430 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001431 boolean unfrozeWindows = false;
1432 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001433 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001434 unfrozeWindows |= w.onStopFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001435 }
1436 if (force || unfrozeWindows) {
1437 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "No longer freezing: " + this);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001438 mFreezingScreen = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001439 mWmService.unregisterAppFreezeListener(this);
1440 mWmService.mAppsFreezingScreen--;
1441 mWmService.mLastFinishedFreezeSource = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001442 }
1443 if (unfreezeSurfaceNow) {
1444 if (unfrozeWindows) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001445 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001446 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001447 mWmService.stopFreezingDisplayLocked();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001448 }
1449 }
1450
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001451 @Override
1452 public void onAppFreezeTimeout() {
1453 Slog.w(TAG_WM, "Force clearing freeze: " + this);
1454 stopFreezingScreen(true, true);
1455 }
1456
Jorim Jaggi60f9c972018-02-01 19:21:07 +01001457 /**
1458 * Tries to transfer the starting window from a token that's above ourselves in the task but
1459 * not visible anymore. This is a common scenario apps use: Trampoline activity T start main
1460 * activity M in the same task. Now, when reopening the task, T starts on top of M but then
1461 * immediately finishes after, so we have to transfer T to M.
1462 */
1463 void transferStartingWindowFromHiddenAboveTokenIfNeeded() {
1464 final Task task = getTask();
1465 for (int i = task.mChildren.size() - 1; i >= 0; i--) {
1466 final AppWindowToken fromToken = task.mChildren.get(i);
1467 if (fromToken == this) {
1468 return;
1469 }
1470 if (fromToken.hiddenRequested && transferStartingWindow(fromToken.token)) {
1471 return;
1472 }
1473 }
1474 }
1475
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001476 boolean transferStartingWindow(IBinder transferFrom) {
Wale Ogunwale02319a62016-09-26 15:21:22 -07001477 final AppWindowToken fromToken = getDisplayContent().getAppWindowToken(transferFrom);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001478 if (fromToken == null) {
1479 return false;
1480 }
1481
1482 final WindowState tStartingWindow = fromToken.startingWindow;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08001483 if (tStartingWindow != null && fromToken.startingSurface != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001484 // In this case, the starting icon has already been displayed, so start
1485 // letting windows get shown immediately without any more transitions.
lumark588a3e82018-07-20 18:53:54 +08001486 getDisplayContent().mSkipAppTransitionAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001487
1488 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Moving existing starting " + tStartingWindow
1489 + " from " + fromToken + " to " + this);
1490
1491 final long origId = Binder.clearCallingIdentity();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001492 try {
1493 // Transfer the starting window over to the new token.
chaviwa8f07a72019-05-01 16:25:39 -07001494 mStartingData = fromToken.mStartingData;
Peter Visontay3556a3b2017-11-01 17:23:17 +00001495 startingSurface = fromToken.startingSurface;
1496 startingDisplayed = fromToken.startingDisplayed;
1497 fromToken.startingDisplayed = false;
1498 startingWindow = tStartingWindow;
1499 reportedVisible = fromToken.reportedVisible;
chaviwa8f07a72019-05-01 16:25:39 -07001500 fromToken.mStartingData = null;
Peter Visontay3556a3b2017-11-01 17:23:17 +00001501 fromToken.startingSurface = null;
1502 fromToken.startingWindow = null;
1503 fromToken.startingMoved = true;
1504 tStartingWindow.mToken = this;
1505 tStartingWindow.mAppToken = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001506
Peter Visontay3556a3b2017-11-01 17:23:17 +00001507 if (DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
1508 "Removing starting " + tStartingWindow + " from " + fromToken);
1509 fromToken.removeChild(tStartingWindow);
1510 fromToken.postWindowRemoveStartingWindowCleanup(tStartingWindow);
1511 fromToken.mHiddenSetFromTransferredStartingWindow = false;
1512 addWindow(tStartingWindow);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001513
Peter Visontay3556a3b2017-11-01 17:23:17 +00001514 // Propagate other interesting state between the tokens. If the old token is displayed,
1515 // we should immediately force the new one to be displayed. If it is animating, we need
1516 // to move that animation to the new one.
1517 if (fromToken.allDrawn) {
1518 allDrawn = true;
1519 deferClearAllDrawn = fromToken.deferClearAllDrawn;
1520 }
1521 if (fromToken.firstWindowDrawn) {
1522 firstWindowDrawn = true;
1523 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001524 if (!fromToken.isHidden()) {
1525 setHidden(false);
Peter Visontay3556a3b2017-11-01 17:23:17 +00001526 hiddenRequested = false;
1527 mHiddenSetFromTransferredStartingWindow = true;
1528 }
1529 setClientHidden(fromToken.mClientHidden);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001530
Jorim Jaggi980c9de2017-11-17 01:41:37 +01001531 transferAnimation(fromToken);
1532
1533 // When transferring an animation, we no longer need to apply an animation to the
1534 // the token we transfer the animation over. Thus, remove the animation from
1535 // pending opening apps.
lumark588a3e82018-07-20 18:53:54 +08001536 getDisplayContent().mOpeningApps.remove(this);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001537
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001538 mWmService.updateFocusedWindowLocked(
Peter Visontay3556a3b2017-11-01 17:23:17 +00001539 UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/);
1540 getDisplayContent().setLayoutNeeded();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001541 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001542 } finally {
1543 Binder.restoreCallingIdentity(origId);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001544 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001545 return true;
chaviwa8f07a72019-05-01 16:25:39 -07001546 } else if (fromToken.mStartingData != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001547 // The previous app was getting ready to show a
1548 // starting window, but hasn't yet done so. Steal it!
1549 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
1550 "Moving pending starting from " + fromToken + " to " + this);
chaviwa8f07a72019-05-01 16:25:39 -07001551 mStartingData = fromToken.mStartingData;
1552 fromToken.mStartingData = null;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001553 fromToken.startingMoved = true;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001554 scheduleAddStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001555 return true;
1556 }
1557
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001558 // TODO: Transfer thumbnail
1559
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001560 return false;
1561 }
1562
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001563 boolean isLastWindow(WindowState win) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001564 return mChildren.size() == 1 && mChildren.get(0) == win;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001565 }
1566
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001567 @Override
1568 void onAppTransitionDone() {
1569 sendingToBottom = false;
1570 }
1571
Wale Ogunwale51362492016-09-08 17:49:17 -07001572 /**
1573 * We override because this class doesn't want its children affecting its reported orientation
1574 * in anyway.
1575 */
1576 @Override
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001577 int getOrientation(int candidate) {
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001578 if (candidate == SCREEN_ORIENTATION_BEHIND) {
1579 // Allow app to specify orientation regardless of its visibility state if the current
1580 // candidate want us to use orientation behind. I.e. the visible app on-top of this one
1581 // wants us to use the orientation of the app behind it.
1582 return mOrientation;
1583 }
1584
Bryce Lee61fbcbc2017-03-10 14:14:03 -08001585 // The {@link AppWindowToken} should only specify an orientation when it is not closing or
1586 // going to the bottom. Allowing closing {@link AppWindowToken} to participate can lead to
1587 // an Activity in another task being started in the wrong orientation during the transition.
lumark588a3e82018-07-20 18:53:54 +08001588 if (!(sendingToBottom || getDisplayContent().mClosingApps.contains(this))
1589 && (isVisible() || getDisplayContent().mOpeningApps.contains(this))) {
Bryce Leea163b762017-01-24 11:05:01 -08001590 return mOrientation;
Wale Ogunwale51362492016-09-08 17:49:17 -07001591 }
Bryce Leea163b762017-01-24 11:05:01 -08001592
1593 return SCREEN_ORIENTATION_UNSET;
Wale Ogunwale51362492016-09-08 17:49:17 -07001594 }
1595
Wale Ogunwaleb198b742016-12-01 08:44:09 -08001596 /** Returns the app's preferred orientation regardless of its currently visibility state. */
1597 int getOrientationIgnoreVisibility() {
1598 return mOrientation;
1599 }
1600
Riddle Hsub398da32019-01-21 21:48:16 +08001601 /** @return {@code true} if the compatibility bounds is taking effect. */
1602 boolean inSizeCompatMode() {
1603 return mSizeCompatBounds != null;
1604 }
1605
1606 @Override
1607 float getSizeCompatScale() {
1608 return inSizeCompatMode() ? mSizeCompatScale : super.getSizeCompatScale();
1609 }
1610
1611 /**
1612 * @return Non-empty bounds if the activity has override bounds.
1613 * @see ActivityRecord#resolveOverrideConfiguration(Configuration)
1614 */
1615 Rect getResolvedOverrideBounds() {
1616 // Get bounds from resolved override configuration because it is computed with orientation.
1617 return getResolvedOverrideConfiguration().windowConfiguration.getBounds();
1618 }
1619
Craig Mautnerdbb79912012-03-01 18:59:14 -08001620 @Override
Winson Chunge55c0192017-08-24 14:50:48 -07001621 public void onConfigurationChanged(Configuration newParentConfig) {
1622 final int prevWinMode = getWindowingMode();
Evan Rosky2289ba12018-11-19 18:28:18 -08001623 mTmpPrevBounds.set(getBounds());
Winson Chunge55c0192017-08-24 14:50:48 -07001624 super.onConfigurationChanged(newParentConfig);
Riddle Hsub398da32019-01-21 21:48:16 +08001625
1626 final Task task = getTask();
1627 final Rect overrideBounds = getResolvedOverrideBounds();
1628 if (task != null && !overrideBounds.isEmpty()
1629 // If the changes come from change-listener, the incoming parent configuration is
1630 // still the old one. Make sure their orientations are the same to reduce computing
1631 // the compatibility bounds for the intermediate state.
Riddle Hsu04164182019-03-07 18:03:27 +08001632 && (task.mTaskRecord == null || task.mTaskRecord
1633 .getConfiguration().orientation == newParentConfig.orientation)) {
Riddle Hsub398da32019-01-21 21:48:16 +08001634 final Rect taskBounds = task.getBounds();
1635 // Since we only center the activity horizontally, if only the fixed height is smaller
1636 // than its container, the override bounds don't need to take effect.
1637 if ((overrideBounds.width() != taskBounds.width()
1638 || overrideBounds.height() > taskBounds.height())) {
1639 calculateCompatBoundsTransformation(newParentConfig);
1640 updateSurfacePosition();
1641 } else if (mSizeCompatBounds != null) {
1642 mSizeCompatBounds = null;
1643 mSizeCompatScale = 1f;
1644 updateSurfacePosition();
1645 }
1646 }
1647
Winson Chunge55c0192017-08-24 14:50:48 -07001648 final int winMode = getWindowingMode();
1649
1650 if (prevWinMode == winMode) {
1651 return;
1652 }
1653
1654 if (prevWinMode != WINDOWING_MODE_UNDEFINED && winMode == WINDOWING_MODE_PINNED) {
1655 // Entering PiP from fullscreen, reset the snap fraction
1656 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(this);
Winson Chung82267ce2018-04-06 16:38:26 -07001657 } else if (prevWinMode == WINDOWING_MODE_PINNED && winMode != WINDOWING_MODE_UNDEFINED
1658 && !isHidden()) {
Winson Chunge55c0192017-08-24 14:50:48 -07001659 // Leaving PiP to fullscreen, save the snap fraction based on the pre-animation bounds
1660 // for the next re-entry into PiP (assuming the activity is not hidden or destroyed)
1661 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
1662 if (pinnedStack != null) {
Winson Chung8efa1652018-06-06 09:34:23 -07001663 final Rect stackBounds;
1664 if (pinnedStack.lastAnimatingBoundsWasToFullscreen()) {
1665 // We are animating the bounds, use the pre-animation bounds to save the snap
1666 // fraction
1667 stackBounds = pinnedStack.mPreAnimationBounds;
1668 } else {
1669 // We skip the animation if the fullscreen configuration is not compatible, so
1670 // use the current bounds to calculate the saved snap fraction instead
1671 // (see PinnedActivityStack.skipResizeAnimation())
1672 stackBounds = mTmpRect;
1673 pinnedStack.getBounds(stackBounds);
1674 }
Winson Chunge55c0192017-08-24 14:50:48 -07001675 mDisplayContent.mPinnedStackControllerLocked.saveReentrySnapFraction(this,
Winson Chung8efa1652018-06-06 09:34:23 -07001676 stackBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001677 }
Evan Rosky2289ba12018-11-19 18:28:18 -08001678 } else if (shouldStartChangeTransition(prevWinMode, winMode)) {
1679 initializeChangeTransition(mTmpPrevBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001680 }
1681 }
1682
Evan Rosky2289ba12018-11-19 18:28:18 -08001683 private boolean shouldStartChangeTransition(int prevWinMode, int newWinMode) {
Evan Rosky25b56192019-02-06 16:10:56 -08001684 if (mWmService.mDisableTransitionAnimation
1685 || !isVisible()
1686 || getDisplayContent().mAppTransition.isTransitionSet()
1687 || getSurfaceControl() == null) {
Evan Rosky2289ba12018-11-19 18:28:18 -08001688 return false;
1689 }
1690 // Only do an animation into and out-of freeform mode for now. Other mode
1691 // transition animations are currently handled by system-ui.
1692 return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
1693 }
1694
1695 /**
1696 * Initializes a change transition. Because the app is visible already, there is a small period
1697 * of time where the user can see the app content/window update before the transition starts.
1698 * To prevent this, we immediately take a snapshot and place the app/snapshot into a leash which
1699 * "freezes" the location/crop until the transition starts.
1700 * <p>
1701 * Here's a walk-through of the process:
1702 * 1. Create a temporary leash ("interim-change-leash") and reparent the app to it.
1703 * 2. Set the temporary leash's position/crop to the current state.
1704 * 3. Create a snapshot and place that at the top of the leash to cover up content changes.
1705 * 4. Once the transition is ready, it will reparent the app to the animation leash.
1706 * 5. Detach the interim-change-leash.
1707 */
1708 private void initializeChangeTransition(Rect startBounds) {
1709 mDisplayContent.prepareAppTransition(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
1710 false /* alwaysKeepCurrent */, 0, false /* forceOverride */);
1711 mDisplayContent.mChangingApps.add(this);
1712 mTransitStartRect.set(startBounds);
1713
1714 final SurfaceControl.Builder builder = makeAnimationLeash()
1715 .setParent(getAnimationLeashParent())
1716 .setName(getSurfaceControl() + " - interim-change-leash");
1717 mTransitChangeLeash = builder.build();
1718 Transaction t = getPendingTransaction();
1719 t.setWindowCrop(mTransitChangeLeash, startBounds.width(), startBounds.height());
1720 t.setPosition(mTransitChangeLeash, startBounds.left, startBounds.top);
1721 t.show(mTransitChangeLeash);
1722 t.reparent(getSurfaceControl(), mTransitChangeLeash);
1723 onAnimationLeashCreated(t, mTransitChangeLeash);
1724
Evan Rosky966759f2019-01-15 10:33:58 -08001725 // Skip creating snapshot if this transition is controlled by a remote animator which
1726 // doesn't need it.
1727 ArraySet<Integer> activityTypes = new ArraySet<>();
1728 activityTypes.add(getActivityType());
1729 RemoteAnimationAdapter adapter =
1730 mDisplayContent.mAppTransitionController.getRemoteAnimationOverride(
1731 this, TRANSIT_TASK_CHANGE_WINDOWING_MODE, activityTypes);
1732 if (adapter != null && !adapter.getChangeNeedsSnapshot()) {
1733 return;
1734 }
1735
Evan Rosky2289ba12018-11-19 18:28:18 -08001736 if (mThumbnail == null && getTask() != null) {
1737 final TaskSnapshotController snapshotCtrl = mWmService.mTaskSnapshotController;
1738 final ArraySet<Task> tasks = new ArraySet<>();
1739 tasks.add(getTask());
1740 snapshotCtrl.snapshotTasks(tasks);
1741 snapshotCtrl.addSkipClosingAppSnapshotTasks(tasks);
1742 final ActivityManager.TaskSnapshot snapshot = snapshotCtrl.getSnapshot(
1743 getTask().mTaskId, getTask().mUserId, false /* restoreFromDisk */,
1744 false /* reducedResolution */);
Yunfan Chendcb1fcf2019-02-07 19:08:41 +09001745 if (snapshot != null) {
1746 mThumbnail = new AppWindowThumbnail(t, this, snapshot.getSnapshot(),
1747 true /* relative */);
1748 }
Evan Rosky2289ba12018-11-19 18:28:18 -08001749 }
1750 }
1751
1752 boolean isInChangeTransition() {
Evan Roskyec9488c2019-03-01 19:32:12 -08001753 return mTransitChangeLeash != null || AppTransition.isChangeTransit(mTransit);
Evan Rosky2289ba12018-11-19 18:28:18 -08001754 }
1755
Evan Rosky966759f2019-01-15 10:33:58 -08001756 @VisibleForTesting
1757 AppWindowThumbnail getThumbnail() {
1758 return mThumbnail;
1759 }
1760
Riddle Hsub398da32019-01-21 21:48:16 +08001761 /**
1762 * Calculates the scale and offset to horizontal center the size compatibility bounds into the
1763 * region which is available to application.
1764 */
1765 private void calculateCompatBoundsTransformation(Configuration newParentConfig) {
1766 final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds();
Riddle Hsu74826262019-04-17 14:57:42 +08001767 final Rect parentBounds = newParentConfig.windowConfiguration.getBounds();
1768 final Rect viewportBounds = parentAppBounds != null ? parentAppBounds : parentBounds;
Riddle Hsu04164182019-03-07 18:03:27 +08001769 final Rect appBounds = getWindowConfiguration().getAppBounds();
1770 final Rect contentBounds = appBounds != null ? appBounds : getResolvedOverrideBounds();
Riddle Hsub398da32019-01-21 21:48:16 +08001771 final float contentW = contentBounds.width();
1772 final float contentH = contentBounds.height();
1773 final float viewportW = viewportBounds.width();
1774 final float viewportH = viewportBounds.height();
1775 // Only allow to scale down.
1776 mSizeCompatScale = (contentW <= viewportW && contentH <= viewportH)
1777 ? 1 : Math.min(viewportW / contentW, viewportH / contentH);
1778 final int offsetX = (int) ((viewportW - contentW * mSizeCompatScale + 1) * 0.5f)
1779 + viewportBounds.left;
1780
1781 if (mSizeCompatBounds == null) {
1782 mSizeCompatBounds = new Rect();
1783 }
1784 mSizeCompatBounds.set(contentBounds);
1785 mSizeCompatBounds.offsetTo(0, 0);
1786 mSizeCompatBounds.scale(mSizeCompatScale);
Riddle Hsu74826262019-04-17 14:57:42 +08001787 // Ensure to align the top with the parent.
1788 mSizeCompatBounds.top = parentBounds.top;
Riddle Hsu04164182019-03-07 18:03:27 +08001789 // The decor inset is included in height.
1790 mSizeCompatBounds.bottom += viewportBounds.top;
Riddle Hsub398da32019-01-21 21:48:16 +08001791 mSizeCompatBounds.left += offsetX;
1792 mSizeCompatBounds.right += offsetX;
1793 }
1794
1795 @Override
1796 public Rect getBounds() {
1797 if (mSizeCompatBounds != null) {
1798 return mSizeCompatBounds;
1799 }
1800 return super.getBounds();
1801 }
1802
1803 @Override
1804 public boolean matchParentBounds() {
1805 if (super.matchParentBounds()) {
1806 return true;
1807 }
1808 // An activity in size compatibility mode may have override bounds which equals to its
1809 // parent bounds, so the exact bounds should also be checked.
1810 final WindowContainer parent = getParent();
1811 return parent == null || parent.getBounds().equals(getResolvedOverrideBounds());
1812 }
1813
Winson Chunge55c0192017-08-24 14:50:48 -07001814 @Override
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001815 void checkAppWindowsReadyToShow() {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001816 if (allDrawn == mLastAllDrawn) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001817 return;
1818 }
1819
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001820 mLastAllDrawn = allDrawn;
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001821 if (!allDrawn) {
1822 return;
1823 }
1824
1825 // The token has now changed state to having all windows shown... what to do, what to do?
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001826 if (mFreezingScreen) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001827 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001828 stopFreezingScreen(false, true);
1829 if (DEBUG_ORIENTATION) Slog.i(TAG,
1830 "Setting mOrientationChangeComplete=true because wtoken " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001831 + " numInteresting=" + mNumInterestingWindows + " numDrawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001832 // This will set mOrientationChangeComplete and cause a pass through layout.
1833 setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001834 "checkAppWindowsReadyToShow: freezingScreen");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001835 } else {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001836 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001837
1838 // We can now show all of the drawn windows!
lumark588a3e82018-07-20 18:53:54 +08001839 if (!getDisplayContent().mOpeningApps.contains(this) && canShowWindows()) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001840 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001841 }
1842 }
1843 }
1844
Matthew Ng5d23afa2017-06-21 16:16:24 -07001845 /**
Bryce Leed390deb2017-06-22 13:14:28 -07001846 * Returns whether the drawn window states of this {@link AppWindowToken} has considered every
1847 * child {@link WindowState}. A child is considered if it has been passed into
1848 * {@link #updateDrawnWindowStates(WindowState)} after being added. This is used to determine
1849 * whether states, such as {@code allDrawn}, can be set, which relies on state variables such as
1850 * {@code mNumInterestingWindows}, which depend on all {@link WindowState}s being considered.
1851 *
1852 * @return {@code true} If all children have been considered, {@code false}.
1853 */
1854 private boolean allDrawnStatesConsidered() {
Bryce Lee6311c4b2017-07-06 14:09:29 -07001855 for (int i = mChildren.size() - 1; i >= 0; --i) {
1856 final WindowState child = mChildren.get(i);
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001857 if (child.mightAffectAllDrawn() && !child.getDrawnStateEvaluated()) {
Bryce Leed390deb2017-06-22 13:14:28 -07001858 return false;
1859 }
1860 }
1861 return true;
1862 }
1863
1864 /**
Matthew Ng5d23afa2017-06-21 16:16:24 -07001865 * Determines if the token has finished drawing. This should only be called from
1866 * {@link DisplayContent#applySurfaceChangesTransaction}
1867 */
Matthew Ng498c71d2017-04-18 13:55:45 -07001868 void updateAllDrawn() {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001869 if (!allDrawn) {
Matthew Ng498c71d2017-04-18 13:55:45 -07001870 // Number of drawn windows can be less when a window is being relaunched, wait for
Bryce Leed390deb2017-06-22 13:14:28 -07001871 // all windows to be launched and drawn for this token be considered all drawn.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001872 final int numInteresting = mNumInterestingWindows;
Bryce Leed390deb2017-06-22 13:14:28 -07001873
1874 // We must make sure that all present children have been considered (determined by
1875 // {@link #allDrawnStatesConsidered}) before evaluating whether everything has been
1876 // drawn.
1877 if (numInteresting > 0 && allDrawnStatesConsidered()
1878 && mNumDrawnWindows >= numInteresting && !isRelaunching()) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001879 if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawn: " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001880 + " interesting=" + numInteresting + " drawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001881 allDrawn = true;
1882 // Force an additional layout pass where
1883 // WindowStateAnimator#commitFinishDrawingLocked() will call performShowLocked().
Matthew Ng498c71d2017-04-18 13:55:45 -07001884 if (mDisplayContent != null) {
1885 mDisplayContent.setLayoutNeeded();
1886 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001887 mWmService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
Robert Carrecc06b32017-04-18 14:25:10 -07001888
Winson Chunge7ba6862017-05-24 12:13:33 -07001889 // Notify the pinned stack upon all windows drawn. If there was an animation in
1890 // progress then this signal will resume that animation.
Wale Ogunwale61911492017-10-11 08:50:50 -07001891 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
Winson Chunge7ba6862017-05-24 12:13:33 -07001892 if (pinnedStack != null) {
1893 pinnedStack.onAllWindowsDrawn();
Robert Carrecc06b32017-04-18 14:25:10 -07001894 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001895 }
1896 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001897 }
1898
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001899 boolean keyDispatchingTimedOut(String reason, int windowPid) {
1900 return mActivityRecord != null && mActivityRecord.keyDispatchingTimedOut(reason, windowPid);
1901 }
1902
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001903 /**
1904 * Updated this app token tracking states for interesting and drawn windows based on the window.
1905 *
1906 * @return Returns true if the input window is considered interesting and drawn while all the
1907 * windows in this app token where not considered drawn as of the last pass.
1908 */
1909 boolean updateDrawnWindowStates(WindowState w) {
Bryce Leed390deb2017-06-22 13:14:28 -07001910 w.setDrawnStateEvaluated(true /*evaluated*/);
1911
Jorim Jaggie4b0f282017-05-17 15:10:29 +02001912 if (DEBUG_STARTING_WINDOW_VERBOSE && w == startingWindow) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001913 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + w.isOnScreen()
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001914 + " allDrawn=" + allDrawn + " freezingScreen=" + mFreezingScreen);
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001915 }
1916
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001917 if (allDrawn && !mFreezingScreen) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001918 return false;
1919 }
1920
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001921 if (mLastTransactionSequence != mWmService.mTransactionSequence) {
1922 mLastTransactionSequence = mWmService.mTransactionSequence;
Matthew Ng53e66b22018-01-12 17:13:13 -08001923 mNumDrawnWindows = 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001924 startingDisplayed = false;
Matthew Ng53e66b22018-01-12 17:13:13 -08001925
1926 // There is the main base application window, even if it is exiting, wait for it
1927 mNumInterestingWindows = findMainWindow(false /* includeStartingApp */) != null ? 1 : 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001928 }
1929
1930 final WindowStateAnimator winAnimator = w.mWinAnimator;
1931
1932 boolean isInterestingAndDrawn = false;
1933
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001934 if (!allDrawn && w.mightAffectAllDrawn()) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001935 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
1936 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001937 + ", isAnimationSet=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001938 if (!w.isDrawnLw()) {
1939 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController
chaviw15ad49f2019-04-24 15:05:39 -07001940 + " pv=" + w.isVisibleByPolicy()
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001941 + " mDrawState=" + winAnimator.drawStateToString()
1942 + " ph=" + w.isParentWindowHidden() + " th=" + hiddenRequested
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001943 + " a=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001944 }
1945 }
1946
1947 if (w != startingWindow) {
1948 if (w.isInteresting()) {
Matthew Ng53e66b22018-01-12 17:13:13 -08001949 // Add non-main window as interesting since the main app has already been added
1950 if (findMainWindow(false /* includeStartingApp */) != w) {
1951 mNumInterestingWindows++;
1952 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001953 if (w.isDrawnLw()) {
1954 mNumDrawnWindows++;
1955
1956 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, "tokenMayBeDrawn: "
1957 + this + " w=" + w + " numInteresting=" + mNumInterestingWindows
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001958 + " freezingScreen=" + mFreezingScreen
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001959 + " mAppFreezing=" + w.mAppFreezing);
1960
1961 isInterestingAndDrawn = true;
1962 }
1963 }
1964 } else if (w.isDrawnLw()) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001965 if (mActivityRecord != null) {
1966 mActivityRecord.onStartingWindowDrawn(SystemClock.uptimeMillis());
Jorim Jaggi3878ca32017-02-02 17:13:05 -08001967 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001968 startingDisplayed = true;
1969 }
1970 }
1971
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001972 return isInterestingAndDrawn;
1973 }
1974
Adrian Roos23df3a32018-03-15 15:41:13 +01001975 void layoutLetterbox(WindowState winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001976 final WindowState w = findMainWindow();
Adrian Roosf93b6d22018-03-21 13:48:26 +01001977 if (w == null || winHint != null && w != winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001978 return;
1979 }
Jorim Jaggia32da382018-03-28 18:01:22 +02001980 final boolean surfaceReady = w.isDrawnLw() // Regular case
Adrian Roosf93b6d22018-03-21 13:48:26 +01001981 || w.mWinAnimator.mSurfaceDestroyDeferred // The preserved surface is still ready.
1982 || w.isDragResizeChanged(); // Waiting for relayoutWindow to call preserveSurface.
Jorim Jaggi4981f152019-03-26 18:58:45 +01001983 final boolean needsLetterbox = surfaceReady && w.isLetterboxedAppWindow() && fillsParent();
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001984 if (needsLetterbox) {
1985 if (mLetterbox == null) {
1986 mLetterbox = new Letterbox(() -> makeChildSurface(null));
Riddle Hsu192fe762019-01-15 23:41:57 +08001987 mLetterbox.attachInput(w);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001988 }
Adrian Roos7af9d972018-11-30 15:26:27 +01001989 getPosition(mTmpPoint);
Evan Rosky67c15642019-04-24 13:17:28 -07001990 // Get the bounds of the "space-to-fill". In multi-window mode, the task-level
1991 // represents this. In fullscreen-mode, the stack does (since the orientation letterbox
1992 // is also applied to the task).
1993 Rect spaceToFill = (inMultiWindowMode() || getStack() == null)
1994 ? getTask().getDisplayedBounds() : getStack().getDisplayedBounds();
Evan Rosky4fb1e912019-03-06 13:54:43 -08001995 mLetterbox.layout(spaceToFill, w.getFrameLw(), mTmpPoint);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001996 } else if (mLetterbox != null) {
Adrian Roos23df3a32018-03-15 15:41:13 +01001997 mLetterbox.hide();
1998 }
1999 }
2000
2001 void updateLetterboxSurface(WindowState winHint) {
2002 final WindowState w = findMainWindow();
2003 if (w != winHint && winHint != null && w != null) {
2004 return;
2005 }
2006 layoutLetterbox(winHint);
2007 if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) {
Tiger Huanged6794e2019-05-07 20:07:59 +08002008 mLetterbox.applySurfaceChanges(getPendingTransaction());
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002009 }
2010 }
2011
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07002012 @Override
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002013 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002014 // For legacy reasons we process the TaskStack.mExitingAppTokens first in DisplayContent
2015 // before the non-exiting app tokens. So, we skip the exiting app tokens here.
2016 // TODO: Investigate if we need to continue to do this or if we can just process them
2017 // in-order.
2018 if (mIsExiting && !waitingForReplacement()) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002019 return false;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002020 }
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002021 return forAllWindowsUnchecked(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002022 }
2023
lumark588a3e82018-07-20 18:53:54 +08002024 @Override
2025 void forAllAppWindows(Consumer<AppWindowToken> callback) {
2026 callback.accept(this);
2027 }
2028
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002029 boolean forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback,
2030 boolean traverseTopToBottom) {
2031 return super.forAllWindows(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002032 }
2033
2034 @Override
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002035 AppWindowToken asAppWindowToken() {
2036 // I am an app window token!
2037 return this;
2038 }
2039
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002040 boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
2041 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
2042 IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
2043 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
2044 // If the display is frozen, we won't do anything until the actual window is
2045 // displayed so there is no reason to put in the starting window.
2046 if (!okToDisplay()) {
2047 return false;
2048 }
2049
chaviwa8f07a72019-05-01 16:25:39 -07002050 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002051 return false;
2052 }
2053
2054 final WindowState mainWin = findMainWindow();
2055 if (mainWin != null && mainWin.mWinAnimator.getShown()) {
2056 // App already has a visible window...why would you want a starting window?
2057 return false;
2058 }
2059
2060 final ActivityManager.TaskSnapshot snapshot =
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002061 mWmService.mTaskSnapshotController.getSnapshot(
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002062 getTask().mTaskId, getTask().mUserId,
2063 false /* restoreFromDisk */, false /* reducedResolution */);
2064 final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
2065 allowTaskSnapshot, activityCreated, fromRecents, snapshot);
2066
2067 if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
2068 return createSnapshot(snapshot);
2069 }
2070
2071 // If this is a translucent window, then don't show a starting window -- the current
2072 // effect (a full-screen opaque starting window that fades away to the real contents
2073 // when it is ready) does not work for this.
2074 if (DEBUG_STARTING_WINDOW) {
2075 Slog.v(TAG, "Checking theme of starting window: 0x" + Integer.toHexString(theme));
2076 }
2077 if (theme != 0) {
2078 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
2079 com.android.internal.R.styleable.Window,
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002080 mWmService.mCurrentUserId);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002081 if (ent == null) {
2082 // Whoops! App doesn't exist. Um. Okay. We'll just pretend like we didn't
2083 // see that.
2084 return false;
2085 }
2086 final boolean windowIsTranslucent = ent.array.getBoolean(
2087 com.android.internal.R.styleable.Window_windowIsTranslucent, false);
2088 final boolean windowIsFloating = ent.array.getBoolean(
2089 com.android.internal.R.styleable.Window_windowIsFloating, false);
2090 final boolean windowShowWallpaper = ent.array.getBoolean(
2091 com.android.internal.R.styleable.Window_windowShowWallpaper, false);
2092 final boolean windowDisableStarting = ent.array.getBoolean(
2093 com.android.internal.R.styleable.Window_windowDisablePreview, false);
2094 if (DEBUG_STARTING_WINDOW) {
2095 Slog.v(TAG, "Translucent=" + windowIsTranslucent
2096 + " Floating=" + windowIsFloating
2097 + " ShowWallpaper=" + windowShowWallpaper);
2098 }
2099 if (windowIsTranslucent) {
2100 return false;
2101 }
2102 if (windowIsFloating || windowDisableStarting) {
2103 return false;
2104 }
2105 if (windowShowWallpaper) {
2106 if (getDisplayContent().mWallpaperController
2107 .getWallpaperTarget() == null) {
2108 // If this theme is requesting a wallpaper, and the wallpaper
2109 // is not currently visible, then this effectively serves as
2110 // an opaque window and our starting window transition animation
2111 // can still work. We just need to make sure the starting window
2112 // is also showing the wallpaper.
2113 windowFlags |= FLAG_SHOW_WALLPAPER;
2114 } else {
2115 return false;
2116 }
2117 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002118 }
Yunfan Chen8a8c0ed2018-12-18 16:46:32 -08002119
2120 if (transferStartingWindow(transferFrom)) {
2121 return true;
2122 }
2123
2124 // There is no existing starting window, and we don't want to create a splash screen, so
2125 // that's it!
2126 if (type != STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
2127 return false;
2128 }
2129
2130 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SplashScreenStartingData");
chaviwa8f07a72019-05-01 16:25:39 -07002131 mStartingData = new SplashScreenStartingData(mWmService, pkg,
Yunfan Chen8a8c0ed2018-12-18 16:46:32 -08002132 theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
2133 getMergedOverrideConfiguration());
2134 scheduleAddStartingWindow();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002135 return true;
2136 }
2137
2138
2139 private boolean createSnapshot(ActivityManager.TaskSnapshot snapshot) {
2140 if (snapshot == null) {
2141 return false;
2142 }
2143
2144 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SnapshotStartingData");
chaviwa8f07a72019-05-01 16:25:39 -07002145 mStartingData = new SnapshotStartingData(mWmService, snapshot);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002146 scheduleAddStartingWindow();
2147 return true;
2148 }
2149
2150 void scheduleAddStartingWindow() {
2151 // Note: we really want to do sendMessageAtFrontOfQueue() because we
2152 // want to process the message ASAP, before any other queued
2153 // messages.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002154 if (!mWmService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002155 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING");
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002156 mWmService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002157 }
2158 }
2159
2160 private final Runnable mAddStartingWindow = new Runnable() {
2161
2162 @Override
2163 public void run() {
chaviwa8f07a72019-05-01 16:25:39 -07002164 // Can be accessed without holding the global lock
2165 final StartingData startingData;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002166 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002167 // There can only be one adding request, silly caller!
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002168 mWmService.mAnimationHandler.removeCallbacks(this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002169
chaviwa8f07a72019-05-01 16:25:39 -07002170 if (mStartingData == null) {
2171 // Animation has been canceled... do nothing.
2172 if (DEBUG_STARTING_WINDOW) {
2173 Slog.v(TAG, "startingData was nulled out before handling"
2174 + " mAddStartingWindow: " + AppWindowToken.this);
2175 }
2176 return;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002177 }
chaviwa8f07a72019-05-01 16:25:39 -07002178 startingData = mStartingData;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002179 }
2180
2181 if (DEBUG_STARTING_WINDOW) {
2182 Slog.v(TAG, "Add starting " + this + ": startingData=" + startingData);
2183 }
2184
2185 WindowManagerPolicy.StartingSurface surface = null;
2186 try {
2187 surface = startingData.createStartingSurface(AppWindowToken.this);
2188 } catch (Exception e) {
2189 Slog.w(TAG, "Exception when adding starting window", e);
2190 }
2191 if (surface != null) {
2192 boolean abort = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002193 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002194 // If the window was successfully added, then
2195 // we need to remove it.
chaviwa8f07a72019-05-01 16:25:39 -07002196 if (removed || mStartingData == null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002197 if (DEBUG_STARTING_WINDOW) {
2198 Slog.v(TAG, "Aborted starting " + AppWindowToken.this
chaviwa8f07a72019-05-01 16:25:39 -07002199 + ": removed=" + removed + " startingData=" + mStartingData);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002200 }
2201 startingWindow = null;
chaviwa8f07a72019-05-01 16:25:39 -07002202 mStartingData = null;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002203 abort = true;
2204 } else {
2205 startingSurface = surface;
2206 }
2207 if (DEBUG_STARTING_WINDOW && !abort) {
chaviwa8f07a72019-05-01 16:25:39 -07002208 Slog.v(TAG,
2209 "Added starting " + AppWindowToken.this + ": startingWindow="
2210 + startingWindow + " startingView=" + startingSurface);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002211 }
2212 }
2213 if (abort) {
2214 surface.remove();
2215 }
2216 } else if (DEBUG_STARTING_WINDOW) {
2217 Slog.v(TAG, "Surface returned was null: " + AppWindowToken.this);
2218 }
2219 }
2220 };
2221
2222 private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
2223 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents,
2224 ActivityManager.TaskSnapshot snapshot) {
2225 if (getDisplayContent().mAppTransition.getAppTransition()
2226 == TRANSIT_DOCK_TASK_FROM_RECENTS) {
2227 // TODO(b/34099271): Remove this statement to add back the starting window and figure
2228 // out why it causes flickering, the starting window appears over the thumbnail while
2229 // the docked from recents transition occurs
2230 return STARTING_WINDOW_TYPE_NONE;
2231 } else if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
2232 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2233 } else if (taskSwitch && allowTaskSnapshot) {
Kevin716a9db2018-12-18 16:53:39 -08002234 if (mWmService.mLowRamTaskSnapshotsAndRecents) {
Kevin58b47f12018-12-17 14:09:01 -08002235 // For low RAM devices, we use the splash screen starting window instead of the
2236 // task snapshot starting window.
2237 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2238 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002239 return snapshot == null ? STARTING_WINDOW_TYPE_NONE
2240 : snapshotOrientationSameAsTask(snapshot) || fromRecents
2241 ? STARTING_WINDOW_TYPE_SNAPSHOT : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2242 } else {
2243 return STARTING_WINDOW_TYPE_NONE;
2244 }
2245 }
2246
2247
2248 private boolean snapshotOrientationSameAsTask(ActivityManager.TaskSnapshot snapshot) {
2249 if (snapshot == null) {
2250 return false;
2251 }
2252 return getTask().getConfiguration().orientation == snapshot.getOrientation();
2253 }
2254
2255 void removeStartingWindow() {
2256 if (startingWindow == null) {
chaviwa8f07a72019-05-01 16:25:39 -07002257 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002258 // Starting window has not been added yet, but it is scheduled to be added.
2259 // Go ahead and cancel the request.
2260 if (DEBUG_STARTING_WINDOW) {
2261 Slog.v(TAG_WM, "Clearing startingData for token=" + this);
2262 }
chaviwa8f07a72019-05-01 16:25:39 -07002263 mStartingData = null;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002264 }
2265 return;
2266 }
2267
2268 final WindowManagerPolicy.StartingSurface surface;
chaviwa8f07a72019-05-01 16:25:39 -07002269 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002270 surface = startingSurface;
chaviwa8f07a72019-05-01 16:25:39 -07002271 mStartingData = null;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002272 startingSurface = null;
2273 startingWindow = null;
2274 startingDisplayed = false;
2275 if (surface == null) {
2276 if (DEBUG_STARTING_WINDOW) {
2277 Slog.v(TAG_WM, "startingWindow was set but startingSurface==null, couldn't "
2278 + "remove");
2279 }
2280 return;
2281 }
2282 } else {
2283 if (DEBUG_STARTING_WINDOW) {
2284 Slog.v(TAG_WM, "Tried to remove starting window but startingWindow was null:"
2285 + this);
2286 }
2287 return;
2288 }
2289
2290 if (DEBUG_STARTING_WINDOW) {
2291 Slog.v(TAG_WM, "Schedule remove starting " + this
2292 + " startingWindow=" + startingWindow
2293 + " startingView=" + startingSurface
2294 + " Callers=" + Debug.getCallers(5));
2295 }
2296
2297 // Use the same thread to remove the window as we used to add it, as otherwise we end up
2298 // with things in the view hierarchy being called from different threads.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002299 mWmService.mAnimationHandler.post(() -> {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002300 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Removing startingView=" + surface);
2301 try {
2302 surface.remove();
2303 } catch (Exception e) {
2304 Slog.w(TAG_WM, "Exception when removing starting window", e);
2305 }
2306 });
2307 }
2308
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002309 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -07002310 boolean fillsParent() {
2311 return mFillsParent;
2312 }
2313
2314 void setFillsParent(boolean fillsParent) {
2315 mFillsParent = fillsParent;
2316 }
2317
Jorim Jaggife762342016-10-13 14:33:27 +02002318 boolean containsDismissKeyguardWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002319 // Window state is transient during relaunch. We are not guaranteed to be frozen during the
2320 // entirety of the relaunch.
2321 if (isRelaunching()) {
2322 return mLastContainsDismissKeyguardWindow;
2323 }
2324
Jorim Jaggife762342016-10-13 14:33:27 +02002325 for (int i = mChildren.size() - 1; i >= 0; i--) {
2326 if ((mChildren.get(i).mAttrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
2327 return true;
2328 }
2329 }
2330 return false;
2331 }
2332
2333 boolean containsShowWhenLockedWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002334 // When we are relaunching, it is possible for us to be unfrozen before our previous
2335 // windows have been added back. Using the cached value ensures that our previous
2336 // showWhenLocked preference is honored until relaunching is complete.
2337 if (isRelaunching()) {
2338 return mLastContainsShowWhenLockedWindow;
2339 }
2340
Jorim Jaggife762342016-10-13 14:33:27 +02002341 for (int i = mChildren.size() - 1; i >= 0; i--) {
2342 if ((mChildren.get(i).mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
2343 return true;
2344 }
2345 }
Bryce Lee081554b2017-05-25 07:52:12 -07002346
Jorim Jaggife762342016-10-13 14:33:27 +02002347 return false;
2348 }
2349
2350 void checkKeyguardFlagsChanged() {
2351 final boolean containsDismissKeyguard = containsDismissKeyguardWindow();
2352 final boolean containsShowWhenLocked = containsShowWhenLockedWindow();
2353 if (containsDismissKeyguard != mLastContainsDismissKeyguardWindow
2354 || containsShowWhenLocked != mLastContainsShowWhenLockedWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002355 mWmService.notifyKeyguardFlagsChanged(null /* callback */,
lumark588a3e82018-07-20 18:53:54 +08002356 getDisplayContent().getDisplayId());
Jorim Jaggife762342016-10-13 14:33:27 +02002357 }
2358 mLastContainsDismissKeyguardWindow = containsDismissKeyguard;
2359 mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
2360 }
2361
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002362 WindowState getImeTargetBelowWindow(WindowState w) {
2363 final int index = mChildren.indexOf(w);
2364 if (index > 0) {
2365 final WindowState target = mChildren.get(index - 1);
2366 if (target.canBeImeTarget()) {
2367 return target;
2368 }
2369 }
2370 return null;
2371 }
2372
2373 WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
2374 WindowState candidate = null;
2375 for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
2376 final WindowState w = mChildren.get(i);
2377 if (w.mRemoved) {
2378 continue;
2379 }
Jorim Jaggi35d328a2018-08-14 17:00:20 +02002380 if (candidate == null) {
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002381 candidate = w;
2382 }
2383 }
2384 return candidate;
2385 }
2386
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002387 /**
2388 * See {@link Activity#setDisablePreviewScreenshots}.
2389 */
2390 void setDisablePreviewScreenshots(boolean disable) {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002391 mDisablePreviewScreenshots = disable;
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002392 }
2393
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002394 /**
chaviwd3bf08d2017-08-01 17:24:59 -07002395 * Sets whether the current launch can turn the screen on. See {@link #canTurnScreenOn()}
2396 */
2397 void setCanTurnScreenOn(boolean canTurnScreenOn) {
2398 mCanTurnScreenOn = canTurnScreenOn;
2399 }
2400
2401 /**
2402 * Indicates whether the current launch can turn the screen on. This is to prevent multiple
2403 * relayouts from turning the screen back on. The screen should only turn on at most
2404 * once per activity resume.
2405 *
2406 * @return true if the screen can be turned on.
2407 */
2408 boolean canTurnScreenOn() {
2409 return mCanTurnScreenOn;
2410 }
2411
2412 /**
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002413 * Retrieves whether we'd like to generate a snapshot that's based solely on the theme. This is
2414 * the case when preview screenshots are disabled {@link #setDisablePreviewScreenshots} or when
2415 * we can't take a snapshot for other reasons, for example, if we have a secure window.
2416 *
2417 * @return True if we need to generate an app theme snapshot, false if we'd like to take a real
2418 * screenshot.
2419 */
2420 boolean shouldUseAppThemeSnapshot() {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002421 return mDisablePreviewScreenshots || forAllWindows(w -> (w.mAttrs.flags & FLAG_SECURE) != 0,
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002422 true /* topToBottom */);
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002423 }
2424
Jorim Jaggibe418292018-03-26 16:14:12 +02002425 SurfaceControl getAppAnimationLayer() {
Jorim Jaggi391790622018-04-18 15:30:44 +02002426 return getAppAnimationLayer(isActivityTypeHome() ? ANIMATION_LAYER_HOME
2427 : needsZBoost() ? ANIMATION_LAYER_BOOSTED
2428 : ANIMATION_LAYER_STANDARD);
Jorim Jaggibe418292018-03-26 16:14:12 +02002429 }
2430
chaviw23ee71c2017-12-18 11:29:41 -08002431 @Override
Jorim Jaggi596a1992017-12-29 14:48:02 +01002432 public SurfaceControl getAnimationLeashParent() {
Robert Carrb9506032018-02-13 13:54:00 -08002433 // All normal app transitions take place in an animation layer which is below the pinned
2434 // stack but may be above the parent stacks of the given animating apps.
2435 // For transitions in the pinned stack (menu activity) we just let them occur as a child
2436 // of the pinned stack.
2437 if (!inPinnedWindowingMode()) {
2438 return getAppAnimationLayer();
2439 } else {
2440 return getStack().getSurfaceControl();
2441 }
chaviw23ee71c2017-12-18 11:29:41 -08002442 }
2443
lumarkb5a78b32019-04-25 20:31:30 +08002444
2445 @VisibleForTesting
2446 boolean shouldAnimate(int transit) {
Jorim Jaggic6976f02018-04-18 16:31:07 +02002447 final boolean isSplitScreenPrimary =
2448 getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
2449 final boolean allowSplitScreenPrimaryAnimation = transit != TRANSIT_WALLPAPER_OPEN;
2450
lumarkb5a78b32019-04-25 20:31:30 +08002451 // Don't animate while the task runs recents animation but only if we are in the mode
2452 // where we cancel with deferred screenshot, which means that the controller has
2453 // transformed the task.
lumark54284462019-03-05 20:44:27 +08002454 final RecentsAnimationController controller = mWmService.getRecentsAnimationController();
lumarkb5a78b32019-04-25 20:31:30 +08002455 if (controller != null && controller.isAnimatingTask(getTask())
2456 && controller.shouldCancelWithDeferredScreenshot()) {
lumark54284462019-03-05 20:44:27 +08002457 return false;
2458 }
2459
Jorim Jaggic6976f02018-04-18 16:31:07 +02002460 // We animate always if it's not split screen primary, and only some special cases in split
2461 // screen primary because it causes issues with stack clipping when we run an un-minimize
2462 // animation at the same time.
2463 return !isSplitScreenPrimary || allowSplitScreenPrimaryAnimation;
2464 }
2465
Vishnu Naira2977262018-07-26 13:31:26 -07002466 /**
2467 * Creates a layer to apply crop to an animation.
2468 */
2469 private SurfaceControl createAnimationBoundsLayer(Transaction t) {
2470 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.i(TAG, "Creating animation bounds layer");
2471 final SurfaceControl.Builder builder = makeAnimationLeash()
2472 .setParent(getAnimationLeashParent())
Vishnu Naire86bd982018-11-28 13:23:17 -08002473 .setName(getSurfaceControl() + " - animation-bounds");
Vishnu Naira2977262018-07-26 13:31:26 -07002474 final SurfaceControl boundsLayer = builder.build();
2475 t.show(boundsLayer);
2476 return boundsLayer;
2477 }
2478
Evan Roskyed6767f2018-10-26 17:21:06 -07002479 @Override
2480 Rect getDisplayedBounds() {
2481 final Task task = getTask();
2482 if (task != null) {
2483 final Rect overrideDisplayedBounds = task.getOverrideDisplayedBounds();
2484 if (!overrideDisplayedBounds.isEmpty()) {
2485 return overrideDisplayedBounds;
2486 }
2487 }
2488 return getBounds();
2489 }
2490
Evan Rosky641daea2019-04-24 14:45:24 -07002491 @VisibleForTesting
2492 Rect getAnimationBounds(int appStackClipMode) {
2493 if (appStackClipMode == STACK_CLIP_BEFORE_ANIM && getStack() != null) {
2494 // Using the stack bounds here effectively applies the clipping before animation.
2495 return getStack().getBounds();
2496 }
2497 // Use task-bounds if available so that activity-level letterbox (maxAspectRatio) is
2498 // included in the animation.
2499 return getTask() != null ? getTask().getBounds() : getBounds();
2500 }
2501
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002502 boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter,
2503 boolean isVoiceInteraction) {
2504
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002505 if (mWmService.mDisableTransitionAnimation || !shouldAnimate(transit)) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002506 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
Jorim Jaggic6976f02018-04-18 16:31:07 +02002507 Slog.v(TAG_WM, "applyAnimation: transition animation is disabled or skipped."
2508 + " atoken=" + this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002509 }
2510 cancelAnimation();
2511 return false;
2512 }
2513
2514 // Only apply an animation if the display isn't frozen. If it is frozen, there is no reason
2515 // to animate and it can cause strange artifacts when we unfreeze the display if some
2516 // different animation is running.
2517 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#applyAnimationLocked");
2518 if (okToAnimate()) {
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002519 final AnimationAdapter adapter;
Evan Rosky2289ba12018-11-19 18:28:18 -08002520 AnimationAdapter thumbnailAdapter = null;
Evan Rosky4fb1e912019-03-06 13:54:43 -08002521
Evan Rosky641daea2019-04-24 14:45:24 -07002522 final int appStackClipMode =
2523 getDisplayContent().mAppTransition.getAppStackClipMode();
2524
2525 // Separate position and size for use in animators.
2526 mTmpRect.set(getAnimationBounds(appStackClipMode));
Evan Rosky4fb1e912019-03-06 13:54:43 -08002527 mTmpPoint.set(mTmpRect.left, mTmpRect.top);
2528 mTmpRect.offsetTo(0, 0);
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002529
Evan Roskyec9488c2019-03-01 19:32:12 -08002530 final boolean isChanging = AppTransition.isChangeTransit(transit) && enter
2531 && getDisplayContent().mChangingApps.contains(this);
Evan Rosky2289ba12018-11-19 18:28:18 -08002532
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002533 // Delaying animation start isn't compatible with remote animations at all.
lumark588a3e82018-07-20 18:53:54 +08002534 if (getDisplayContent().mAppTransition.getRemoteAnimationController() != null
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002535 && !mSurfaceAnimator.isAnimationStartDelayed()) {
Evan Rosky2289ba12018-11-19 18:28:18 -08002536 RemoteAnimationRecord adapters =
2537 getDisplayContent().mAppTransition.getRemoteAnimationController()
2538 .createRemoteAnimationRecord(this, mTmpPoint, mTmpRect,
2539 (isChanging ? mTransitStartRect : null));
2540 adapter = adapters.mAdapter;
2541 thumbnailAdapter = adapters.mThumbnailAdapter;
2542 } else if (isChanging) {
Evan Roskycf76bed2019-01-15 10:33:58 -08002543 final float durationScale = mWmService.getTransitionAnimationScaleLocked();
Evan Rosky2289ba12018-11-19 18:28:18 -08002544 mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y);
2545 adapter = new LocalAnimationAdapter(
2546 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
Evan Roskycf76bed2019-01-15 10:33:58 -08002547 getDisplayContent().getDisplayInfo(), durationScale,
Evan Rosky2289ba12018-11-19 18:28:18 -08002548 true /* isAppAnimation */, false /* isThumbnail */),
2549 mWmService.mSurfaceAnimationRunner);
Evan Rosky966759f2019-01-15 10:33:58 -08002550 if (mThumbnail != null) {
2551 thumbnailAdapter = new LocalAnimationAdapter(
2552 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
Evan Roskycf76bed2019-01-15 10:33:58 -08002553 getDisplayContent().getDisplayInfo(), durationScale,
Evan Rosky966759f2019-01-15 10:33:58 -08002554 true /* isAppAnimation */, true /* isThumbnail */),
2555 mWmService.mSurfaceAnimationRunner);
2556 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002557 mTransit = transit;
2558 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002559 } else {
Vishnu Naira2977262018-07-26 13:31:26 -07002560 mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM);
2561
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002562 final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
2563 if (a != null) {
Lucas Dupin95acf432019-04-29 17:55:38 -07002564 // Only apply corner radius to animation if we're not in multi window mode.
2565 // We don't want rounded corners when in pip or split screen.
2566 final float windowCornerRadius = !inMultiWindowMode()
2567 ? getDisplayContent().getWindowCornerRadius()
2568 : 0;
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002569 adapter = new LocalAnimationAdapter(
2570 new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
lumark588a3e82018-07-20 18:53:54 +08002571 getDisplayContent().mAppTransition.canSkipFirstFrame(),
Vishnu Naira2977262018-07-26 13:31:26 -07002572 appStackClipMode,
Lucas Dupin3e1dc202018-12-02 15:14:20 -08002573 true /* isAppAnimation */,
Lucas Dupin95acf432019-04-29 17:55:38 -07002574 windowCornerRadius),
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002575 mWmService.mSurfaceAnimationRunner);
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002576 if (a.getZAdjustment() == Animation.ZORDER_TOP) {
2577 mNeedsZBoost = true;
2578 }
2579 mTransit = transit;
lumark588a3e82018-07-20 18:53:54 +08002580 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002581 } else {
2582 adapter = null;
chaviw23ee71c2017-12-18 11:29:41 -08002583 }
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002584 }
2585 if (adapter != null) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002586 startAnimation(getPendingTransaction(), adapter, !isVisible());
Jorim Jaggi82c17862018-02-21 17:50:18 +01002587 if (adapter.getShowWallpaper()) {
2588 mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2589 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002590 if (thumbnailAdapter != null) {
2591 mThumbnail.startAnimation(
2592 getPendingTransaction(), thumbnailAdapter, !isVisible());
2593 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002594 }
2595 } else {
2596 cancelAnimation();
2597 }
2598 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2599
2600 return isReallyAnimating();
2601 }
2602
2603 private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
2604 boolean isVoiceInteraction) {
2605 final DisplayContent displayContent = getTask().getDisplayContent();
2606 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2607 final int width = displayInfo.appWidth;
2608 final int height = displayInfo.appHeight;
2609 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG_WM,
2610 "applyAnimation: atoken=" + this);
2611
2612 // Determine the visible rect to calculate the thumbnail clip
2613 final WindowState win = findMainWindow();
2614 final Rect frame = new Rect(0, 0, width, height);
2615 final Rect displayFrame = new Rect(0, 0,
2616 displayInfo.logicalWidth, displayInfo.logicalHeight);
2617 final Rect insets = new Rect();
2618 final Rect stableInsets = new Rect();
2619 Rect surfaceInsets = null;
2620 final boolean freeform = win != null && win.inFreeformWindowingMode();
2621 if (win != null) {
2622 // Containing frame will usually cover the whole screen, including dialog windows.
2623 // For freeform workspace windows it will not cover the whole screen and it also
2624 // won't exactly match the final freeform window frame (e.g. when overlapping with
2625 // the status bar). In that case we need to use the final frame.
2626 if (freeform) {
chaviw492139a2018-07-16 16:07:35 -07002627 frame.set(win.getFrameLw());
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002628 } else if (win.isLetterboxedAppWindow()) {
2629 frame.set(getTask().getBounds());
Winson Chungc1674272018-02-21 10:15:17 -08002630 } else if (win.isDockedResizing()) {
2631 // If we are animating while docked resizing, then use the stack bounds as the
2632 // animation target (which will be different than the task bounds)
2633 frame.set(getTask().getParent().getBounds());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002634 } else {
chaviw553b0212018-07-12 13:37:01 -07002635 frame.set(win.getContainingFrame());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002636 }
2637 surfaceInsets = win.getAttrs().surfaceInsets;
Adrian Roos20e07892018-02-23 19:12:01 +01002638 // XXX(b/72757033): These are insets relative to the window frame, but we're really
2639 // interested in the insets relative to the frame we chose in the if-blocks above.
chaviw9c81e632018-07-31 11:17:52 -07002640 win.getContentInsets(insets);
2641 win.getStableInsets(stableInsets);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002642 }
2643
2644 if (mLaunchTaskBehind) {
2645 // Differentiate the two animations. This one which is briefly on the screen
2646 // gets the !enter animation, and the other activity which remains on the
2647 // screen gets the enter animation. Both appear in the mOpeningApps set.
2648 enter = false;
2649 }
2650 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "Loading animation for app transition."
2651 + " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter
2652 + " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets);
2653 final Configuration displayConfig = displayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08002654 final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002655 displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
2656 surfaceInsets, stableInsets, isVoiceInteraction, freeform, getTask().mTaskId);
2657 if (a != null) {
2658 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
2659 final int containingWidth = frame.width();
2660 final int containingHeight = frame.height();
2661 a.initialize(containingWidth, containingHeight, width, height);
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002662 a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002663 }
2664 return a;
2665 }
2666
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002667 @Override
Jorim Jaggi6de61012018-03-19 14:53:23 +01002668 public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
2669 return mAnimatingAppWindowTokenRegistry != null
2670 && mAnimatingAppWindowTokenRegistry.notifyAboutToFinish(
2671 this, endDeferFinishCallback);
2672 }
2673
2674 @Override
lumarkf6f34942019-04-29 16:56:50 +08002675 public void onAnimationLeashLost(Transaction t) {
2676 super.onAnimationLeashLost(t);
Vishnu Naira2977262018-07-26 13:31:26 -07002677 if (mAnimationBoundsLayer != null) {
Robert Carr71200f22019-02-05 09:44:53 -08002678 t.remove(mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002679 mAnimationBoundsLayer = null;
2680 }
2681
Jorim Jaggi6de61012018-03-19 14:53:23 +01002682 if (mAnimatingAppWindowTokenRegistry != null) {
2683 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
2684 }
2685 }
2686
2687 @Override
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002688 protected void setLayer(Transaction t, int layer) {
2689 if (!mSurfaceAnimator.hasLeash()) {
2690 t.setLayer(mSurfaceControl, layer);
2691 }
2692 }
2693
2694 @Override
2695 protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
2696 if (!mSurfaceAnimator.hasLeash()) {
2697 t.setRelativeLayer(mSurfaceControl, relativeTo, layer);
2698 }
2699 }
2700
2701 @Override
2702 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
2703 if (!mSurfaceAnimator.hasLeash()) {
Robert Carr10584fa2019-01-14 15:55:19 -08002704 t.reparent(mSurfaceControl, newParent);
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002705 }
2706 }
2707
2708 @Override
2709 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002710 // The leash is parented to the animation layer. We need to preserve the z-order by using
2711 // the prefix order index, but we boost if necessary.
Robert Carrb9506032018-02-13 13:54:00 -08002712 int layer = 0;
2713 if (!inPinnedWindowingMode()) {
2714 layer = getPrefixOrderIndex();
2715 } else {
2716 // Pinned stacks have animations take place within themselves rather than an animation
2717 // layer so we need to preserve the order relative to the stack (e.g. the order of our
2718 // task/parent).
2719 layer = getParent().getPrefixOrderIndex();
2720 }
2721
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002722 if (mNeedsZBoost) {
2723 layer += Z_BOOST_BASE;
2724 }
Jorim Jaggi9cd99132019-04-24 17:41:35 +02002725 if (!mNeedsAnimationBoundsLayer) {
2726 leash.setLayer(layer);
2727 }
Robert Carr2f8aa392018-01-31 14:46:51 -08002728
2729 final DisplayContent dc = getDisplayContent();
Jorim Jaggibe418292018-03-26 16:14:12 +02002730 dc.assignStackOrdering();
Evan Rosky2289ba12018-11-19 18:28:18 -08002731
2732 if (leash == mTransitChangeLeash) {
2733 // This is a temporary state so skip any animation notifications
2734 return;
2735 } else if (mTransitChangeLeash != null) {
2736 // unparent mTransitChangeLeash for clean-up
Evan Rosky25b56192019-02-06 16:10:56 -08002737 clearChangeLeash(t, false /* cancel */);
Evan Rosky2289ba12018-11-19 18:28:18 -08002738 }
2739
Jorim Jaggi6de61012018-03-19 14:53:23 +01002740 if (mAnimatingAppWindowTokenRegistry != null) {
2741 mAnimatingAppWindowTokenRegistry.notifyStarting(this);
2742 }
Vishnu Naira2977262018-07-26 13:31:26 -07002743
2744 // If the animation needs to be cropped then an animation bounds layer is created as a child
2745 // of the pinned stack or animation layer. The leash is then reparented to this new layer.
2746 if (mNeedsAnimationBoundsLayer) {
Evan Rosky7735d352019-03-18 17:27:27 -07002747 mTmpRect.setEmpty();
2748 final Task task = getTask();
2749 if (getDisplayContent().mAppTransitionController.isTransitWithinTask(
2750 getTransit(), task)) {
2751 task.getBounds(mTmpRect);
2752 } else {
2753 final TaskStack stack = getStack();
2754 if (stack == null) {
2755 return;
2756 }
2757 // Set clip rect to stack bounds.
2758 stack.getBounds(mTmpRect);
Vishnu Naira2977262018-07-26 13:31:26 -07002759 }
2760 mAnimationBoundsLayer = createAnimationBoundsLayer(t);
2761
Vishnu Naira2977262018-07-26 13:31:26 -07002762 // Crop to stack bounds.
2763 t.setWindowCrop(mAnimationBoundsLayer, mTmpRect);
Jorim Jaggi9cd99132019-04-24 17:41:35 +02002764 t.setLayer(mAnimationBoundsLayer, layer);
Vishnu Naira2977262018-07-26 13:31:26 -07002765
2766 // Reparent leash to animation bounds layer.
Robert Carr10584fa2019-01-14 15:55:19 -08002767 t.reparent(leash, mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002768 }
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002769 }
2770
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002771 /**
2772 * This must be called while inside a transaction.
2773 */
2774 void showAllWindowsLocked() {
2775 forAllWindows(windowState -> {
2776 if (DEBUG_VISIBILITY) Slog.v(TAG, "performing show on: " + windowState);
2777 windowState.performShowLocked();
2778 }, false /* traverseTopToBottom */);
Jorim Jaggia5e10572017-11-15 14:36:26 +01002779 }
2780
2781 @Override
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002782 protected void onAnimationFinished() {
2783 super.onAnimationFinished();
2784
2785 mTransit = TRANSIT_UNSET;
2786 mTransitFlags = 0;
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002787 mNeedsZBoost = false;
Vishnu Naira2977262018-07-26 13:31:26 -07002788 mNeedsAnimationBoundsLayer = false;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002789
2790 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER,
2791 "AppWindowToken");
2792
Jorim Jaggi988f6682017-11-17 17:46:43 +01002793 clearThumbnail();
Jorim Jaggi752cd822018-03-29 16:29:18 +02002794 setClientHidden(isHidden() && hiddenRequested);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002795
lumarkff0ab692018-11-05 20:32:30 +08002796 getDisplayContent().computeImeTargetIfNeeded(this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002797
2798 if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + this
2799 + ": reportedVisible=" + reportedVisible
2800 + " okToDisplay=" + okToDisplay()
2801 + " okToAnimate=" + okToAnimate()
2802 + " startingDisplayed=" + startingDisplayed);
2803
Evan Rosky2289ba12018-11-19 18:28:18 -08002804 // clean up thumbnail window
2805 if (mThumbnail != null) {
2806 mThumbnail.destroy();
2807 mThumbnail = null;
2808 }
2809
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002810 // WindowState.onExitAnimationDone might modify the children list, so make a copy and then
2811 // traverse the copy.
2812 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
2813 children.forEach(WindowState::onExitAnimationDone);
2814
lumark588a3e82018-07-20 18:53:54 +08002815 getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002816 scheduleAnimation();
Jorim Jaggi9b5e3312019-03-01 18:08:00 +01002817
2818 mActivityRecord.onAnimationFinished();
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002819 }
2820
2821 @Override
2822 boolean isAppAnimating() {
2823 return isSelfAnimating();
2824 }
2825
2826 @Override
2827 boolean isSelfAnimating() {
2828 // If we are about to start a transition, we also need to be considered animating.
2829 return isWaitingForTransitionStart() || isReallyAnimating();
2830 }
2831
2832 /**
2833 * @return True if and only if we are actually running an animation. Note that
2834 * {@link #isSelfAnimating} also returns true if we are waiting for an animation to
2835 * start.
2836 */
2837 private boolean isReallyAnimating() {
2838 return super.isSelfAnimating();
2839 }
2840
Evan Rosky25b56192019-02-06 16:10:56 -08002841 /**
2842 * @param cancel {@code true} if clearing the leash due to cancelling instead of transferring
2843 * to another leash.
2844 */
2845 private void clearChangeLeash(Transaction t, boolean cancel) {
2846 if (mTransitChangeLeash == null) {
2847 return;
2848 }
2849 if (cancel) {
2850 clearThumbnail();
2851 SurfaceControl sc = getSurfaceControl();
2852 SurfaceControl parentSc = getParentSurfaceControl();
2853 // Don't reparent if surface is getting destroyed
2854 if (parentSc != null && sc != null) {
2855 t.reparent(sc, getParentSurfaceControl());
2856 }
2857 }
2858 t.hide(mTransitChangeLeash);
2859 t.reparent(mTransitChangeLeash, null);
2860 mTransitChangeLeash = null;
2861 if (cancel) {
lumarkf6f34942019-04-29 16:56:50 +08002862 onAnimationLeashLost(t);
Evan Rosky25b56192019-02-06 16:10:56 -08002863 }
2864 }
2865
Jorim Jaggi988f6682017-11-17 17:46:43 +01002866 @Override
2867 void cancelAnimation() {
Evan Rosky2289ba12018-11-19 18:28:18 -08002868 cancelAnimationOnly();
Jorim Jaggi988f6682017-11-17 17:46:43 +01002869 clearThumbnail();
Evan Rosky25b56192019-02-06 16:10:56 -08002870 clearChangeLeash(getPendingTransaction(), true /* cancel */);
Evan Rosky2289ba12018-11-19 18:28:18 -08002871 }
2872
2873 /**
2874 * This only cancels the animation. It doesn't do other teardown like cleaning-up thumbnail
2875 * or interim leashes.
2876 * <p>
2877 * Used when canceling in preparation for starting a new animation.
2878 */
2879 void cancelAnimationOnly() {
2880 super.cancelAnimation();
Jorim Jaggi988f6682017-11-17 17:46:43 +01002881 }
2882
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002883 boolean isWaitingForTransitionStart() {
lumark588a3e82018-07-20 18:53:54 +08002884 return getDisplayContent().mAppTransition.isTransitionSet()
2885 && (getDisplayContent().mOpeningApps.contains(this)
Evan Rosky2289ba12018-11-19 18:28:18 -08002886 || getDisplayContent().mClosingApps.contains(this)
2887 || getDisplayContent().mChangingApps.contains(this));
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002888 }
2889
2890 public int getTransit() {
2891 return mTransit;
2892 }
2893
2894 int getTransitFlags() {
2895 return mTransitFlags;
2896 }
2897
Jorim Jaggi988f6682017-11-17 17:46:43 +01002898 void attachThumbnailAnimation() {
2899 if (!isReallyAnimating()) {
2900 return;
2901 }
2902 final int taskId = getTask().mTaskId;
2903 final GraphicBuffer thumbnailHeader =
lumark588a3e82018-07-20 18:53:54 +08002904 getDisplayContent().mAppTransition.getAppTransitionThumbnailHeader(taskId);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002905 if (thumbnailHeader == null) {
2906 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG, "No thumbnail header bitmap for: " + taskId);
2907 return;
2908 }
2909 clearThumbnail();
2910 mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnailHeader);
2911 mThumbnail.startAnimation(getPendingTransaction(), loadThumbnailAnimation(thumbnailHeader));
2912 }
2913
Tony Mak64b8d562017-12-28 17:44:02 +00002914 /**
2915 * Attaches a surface with a thumbnail for the
2916 * {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation.
2917 */
2918 void attachCrossProfileAppsThumbnailAnimation() {
2919 if (!isReallyAnimating()) {
2920 return;
2921 }
2922 clearThumbnail();
2923
2924 final WindowState win = findMainWindow();
2925 if (win == null) {
2926 return;
2927 }
chaviw492139a2018-07-16 16:07:35 -07002928 final Rect frame = win.getFrameLw();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002929 final int thumbnailDrawableRes = getTask().mUserId == mWmService.mCurrentUserId
Tony Mak64b8d562017-12-28 17:44:02 +00002930 ? R.drawable.ic_account_circle
Tony Makda4af232018-04-27 11:01:10 +01002931 : R.drawable.ic_corp_badge;
Tony Mak64b8d562017-12-28 17:44:02 +00002932 final GraphicBuffer thumbnail =
lumark588a3e82018-07-20 18:53:54 +08002933 getDisplayContent().mAppTransition
Tony Mak64b8d562017-12-28 17:44:02 +00002934 .createCrossProfileAppsThumbnail(thumbnailDrawableRes, frame);
2935 if (thumbnail == null) {
2936 return;
2937 }
2938 mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnail);
2939 final Animation animation =
lumark588a3e82018-07-20 18:53:54 +08002940 getDisplayContent().mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(
chaviw492139a2018-07-16 16:07:35 -07002941 win.getFrameLw());
Tony Mak64b8d562017-12-28 17:44:02 +00002942 mThumbnail.startAnimation(getPendingTransaction(), animation, new Point(frame.left,
2943 frame.top));
2944 }
2945
Jorim Jaggi988f6682017-11-17 17:46:43 +01002946 private Animation loadThumbnailAnimation(GraphicBuffer thumbnailHeader) {
2947 final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
2948
2949 // If this is a multi-window scenario, we use the windows frame as
2950 // destination of the thumbnail header animation. If this is a full screen
2951 // window scenario, we use the whole display as the target.
2952 WindowState win = findMainWindow();
2953 Rect appRect = win != null ? win.getContentFrameLw() :
2954 new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
chaviw9c81e632018-07-31 11:17:52 -07002955 final Rect insets = win != null ? win.getContentInsets() : null;
Jorim Jaggi988f6682017-11-17 17:46:43 +01002956 final Configuration displayConfig = mDisplayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08002957 return getDisplayContent().mAppTransition.createThumbnailAspectScaleAnimationLocked(
Jorim Jaggi988f6682017-11-17 17:46:43 +01002958 appRect, insets, thumbnailHeader, getTask().mTaskId, displayConfig.uiMode,
2959 displayConfig.orientation);
2960 }
2961
2962 private void clearThumbnail() {
2963 if (mThumbnail == null) {
2964 return;
2965 }
2966 mThumbnail.destroy();
2967 mThumbnail = null;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002968 }
2969
Jorim Jaggif84e2f62018-01-16 14:17:59 +01002970 void registerRemoteAnimations(RemoteAnimationDefinition definition) {
2971 mRemoteAnimationDefinition = definition;
2972 }
2973
2974 RemoteAnimationDefinition getRemoteAnimationDefinition() {
2975 return mRemoteAnimationDefinition;
2976 }
2977
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002978 @Override
2979 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
2980 super.dump(pw, prefix, dumpAll);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002981 if (appToken != null) {
Wale Ogunwale72919d22016-12-08 18:58:50 -08002982 pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002983 }
Winson Chung48b25652018-10-22 14:04:30 -07002984 pw.println(prefix + "component=" + mActivityComponent.flattenToShortString());
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08002985 pw.print(prefix); pw.print("task="); pw.println(getTask());
Wale Ogunwale51362492016-09-08 17:49:17 -07002986 pw.print(prefix); pw.print(" mFillsParent="); pw.print(mFillsParent);
2987 pw.print(" mOrientation="); pw.println(mOrientation);
Wale Ogunwale89973222017-04-23 18:39:45 -07002988 pw.println(prefix + "hiddenRequested=" + hiddenRequested + " mClientHidden=" + mClientHidden
2989 + ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "")
2990 + " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible);
Craig Mautner59431632012-04-04 11:56:44 -07002991 if (paused) {
2992 pw.print(prefix); pw.print("paused="); pw.println(paused);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002993 }
Wale Ogunwale9017ec02016-02-25 08:55:25 -08002994 if (mAppStopped) {
2995 pw.print(prefix); pw.print("mAppStopped="); pw.println(mAppStopped);
2996 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002997 if (mNumInterestingWindows != 0 || mNumDrawnWindows != 0
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002998 || allDrawn || mLastAllDrawn) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002999 pw.print(prefix); pw.print("mNumInterestingWindows=");
3000 pw.print(mNumInterestingWindows);
3001 pw.print(" mNumDrawnWindows="); pw.print(mNumDrawnWindows);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003002 pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
Craig Mautner6fbda632012-07-03 09:26:39 -07003003 pw.print(" allDrawn="); pw.print(allDrawn);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00003004 pw.print(" lastAllDrawn="); pw.print(mLastAllDrawn);
Craig Mautner6fbda632012-07-03 09:26:39 -07003005 pw.println(")");
3006 }
3007 if (inPendingTransaction) {
3008 pw.print(prefix); pw.print("inPendingTransaction=");
3009 pw.println(inPendingTransaction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003010 }
chaviwa8f07a72019-05-01 16:25:39 -07003011 if (mStartingData != null || removed || firstWindowDrawn || mIsExiting) {
3012 pw.print(prefix); pw.print("startingData="); pw.print(mStartingData);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003013 pw.print(" removed="); pw.print(removed);
Craig Mautner3d7ca312015-01-08 10:56:00 -08003014 pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
Craig Mautner799bc1d2015-01-14 10:33:48 -08003015 pw.print(" mIsExiting="); pw.println(mIsExiting);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003016 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08003017 if (startingWindow != null || startingSurface != null
Wale Ogunwale6c459212017-05-17 08:56:03 -07003018 || startingDisplayed || startingMoved || mHiddenSetFromTransferredStartingWindow) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003019 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08003020 pw.print(" startingSurface="); pw.print(startingSurface);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003021 pw.print(" startingDisplayed="); pw.print(startingDisplayed);
Wale Ogunwale6c459212017-05-17 08:56:03 -07003022 pw.print(" startingMoved="); pw.print(startingMoved);
3023 pw.println(" mHiddenSetFromTransferredStartingWindow="
3024 + mHiddenSetFromTransferredStartingWindow);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003025 }
Jorim Jaggi0429f352015-12-22 16:29:16 +01003026 if (!mFrozenBounds.isEmpty()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08003027 pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
Jorim Jaggi26c8c422016-05-09 19:57:25 -07003028 pw.print(prefix); pw.print("mFrozenMergedConfig="); pw.println(mFrozenMergedConfig);
Chong Zhangd78ddb42016-03-02 17:01:14 -08003029 }
3030 if (mPendingRelaunchCount != 0) {
3031 pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount);
Jorim Jaggi0429f352015-12-22 16:29:16 +01003032 }
Riddle Hsub398da32019-01-21 21:48:16 +08003033 if (mSizeCompatScale != 1f || mSizeCompatBounds != null) {
3034 pw.println(prefix + "mSizeCompatScale=" + mSizeCompatScale + " mSizeCompatBounds="
3035 + mSizeCompatBounds);
3036 }
Wale Ogunwalee287e192017-04-21 09:30:12 -07003037 if (mRemovingFromDisplay) {
3038 pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay);
3039 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003040 }
3041
3042 @Override
3043 void setHidden(boolean hidden) {
3044 super.setHidden(hidden);
Winson Chunge55c0192017-08-24 14:50:48 -07003045
3046 if (hidden) {
3047 // Once the app window is hidden, reset the last saved PiP snap fraction
3048 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(this);
3049 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003050 scheduleAnimation();
3051 }
3052
3053 @Override
3054 void prepareSurfaces() {
3055 // isSelfAnimating also returns true when we are about to start a transition, so we need
3056 // to check super here.
3057 final boolean reallyAnimating = super.isSelfAnimating();
3058 final boolean show = !isHidden() || reallyAnimating;
Robert Carrd8e4fb72019-01-31 11:14:30 -08003059
3060 if (mSurfaceControl != null) {
3061 if (show && !mLastSurfaceShowing) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003062 getPendingTransaction().show(mSurfaceControl);
Robert Carrd8e4fb72019-01-31 11:14:30 -08003063 } else if (!show && mLastSurfaceShowing) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003064 getPendingTransaction().hide(mSurfaceControl);
Robert Carrd8e4fb72019-01-31 11:14:30 -08003065 }
Jorim Jaggi4d1835d2017-08-31 17:28:27 +02003066 }
Jorim Jaggi988f6682017-11-17 17:46:43 +01003067 if (mThumbnail != null) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003068 mThumbnail.setShowing(getPendingTransaction(), show);
Jorim Jaggi988f6682017-11-17 17:46:43 +01003069 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003070 mLastSurfaceShowing = show;
3071 super.prepareSurfaces();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003072 }
3073
Jorim Jaggi77d0f36c2018-03-16 17:49:49 +01003074 /**
3075 * @return Whether our {@link #getSurfaceControl} is currently showing.
3076 */
3077 boolean isSurfaceShowing() {
3078 return mLastSurfaceShowing;
3079 }
3080
Jorim Jaggib0fc8172017-11-23 17:04:08 +00003081 boolean isFreezingScreen() {
3082 return mFreezingScreen;
3083 }
3084
3085 @Override
3086 boolean needsZBoost() {
3087 return mNeedsZBoost || super.needsZBoost();
3088 }
3089
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07003090 @CallSuper
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003091 @Override
Nataniel Borges023ecb52019-01-16 14:15:43 -08003092 public void writeToProto(ProtoOutputStream proto, long fieldId,
3093 @WindowTraceLogLevel int logLevel) {
3094 // Critical log level logs only visible elements to mitigate performance overheard
3095 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
3096 return;
3097 }
3098
Steven Timotiusaf03df62017-07-18 16:56:43 -07003099 final long token = proto.start(fieldId);
3100 writeNameToProto(proto, NAME);
Nataniel Borges023ecb52019-01-16 14:15:43 -08003101 super.writeToProto(proto, WINDOW_TOKEN, logLevel);
Vishnu Nair04ab4392018-01-10 11:00:06 -08003102 proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing);
3103 proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart());
3104 proto.write(IS_REALLY_ANIMATING, isReallyAnimating());
3105 if (mThumbnail != null){
3106 mThumbnail.writeToProto(proto, THUMBNAIL);
3107 }
3108 proto.write(FILLS_PARENT, mFillsParent);
3109 proto.write(APP_STOPPED, mAppStopped);
3110 proto.write(HIDDEN_REQUESTED, hiddenRequested);
3111 proto.write(CLIENT_HIDDEN, mClientHidden);
3112 proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient);
3113 proto.write(REPORTED_DRAWN, reportedDrawn);
3114 proto.write(REPORTED_VISIBLE, reportedVisible);
3115 proto.write(NUM_INTERESTING_WINDOWS, mNumInterestingWindows);
3116 proto.write(NUM_DRAWN_WINDOWS, mNumDrawnWindows);
3117 proto.write(ALL_DRAWN, allDrawn);
3118 proto.write(LAST_ALL_DRAWN, mLastAllDrawn);
3119 proto.write(REMOVED, removed);
Nataniel Borges023ecb52019-01-16 14:15:43 -08003120 if (startingWindow != null) {
Vishnu Nair04ab4392018-01-10 11:00:06 -08003121 startingWindow.writeIdentifierToProto(proto, STARTING_WINDOW);
3122 }
3123 proto.write(STARTING_DISPLAYED, startingDisplayed);
3124 proto.write(STARTING_MOVED, startingMoved);
3125 proto.write(HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW,
3126 mHiddenSetFromTransferredStartingWindow);
3127 for (Rect bounds : mFrozenBounds) {
3128 bounds.writeToProto(proto, FROZEN_BOUNDS);
3129 }
Steven Timotiusaf03df62017-07-18 16:56:43 -07003130 proto.end(token);
3131 }
3132
3133 void writeNameToProto(ProtoOutputStream proto, long fieldId) {
3134 if (appToken == null) {
3135 return;
3136 }
3137 try {
3138 proto.write(fieldId, appToken.getName());
3139 } catch (RemoteException e) {
3140 // This shouldn't happen, but in this case fall back to outputting nothing
3141 Slog.e(TAG, e.toString());
3142 }
3143 }
3144
3145 @Override
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003146 public String toString() {
3147 if (stringName == null) {
3148 StringBuilder sb = new StringBuilder();
3149 sb.append("AppWindowToken{");
3150 sb.append(Integer.toHexString(System.identityHashCode(this)));
3151 sb.append(" token="); sb.append(token); sb.append('}');
3152 stringName = sb.toString();
3153 }
Wale Ogunwaleba51ca22016-09-23 06:06:54 -07003154 return stringName + ((mIsExiting) ? " mIsExiting=" : "");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003155 }
Adrian Roos20e07892018-02-23 19:12:01 +01003156
3157 Rect getLetterboxInsets() {
3158 if (mLetterbox != null) {
3159 return mLetterbox.getInsets();
3160 } else {
3161 return new Rect();
3162 }
3163 }
Adrian Roos23df3a32018-03-15 15:41:13 +01003164
Riddle Hsu69de5fb2019-02-23 01:19:50 +08003165 /** Gets the inner bounds of letterbox. The bounds will be empty if there is no letterbox. */
3166 void getLetterboxInnerBounds(Rect outBounds) {
3167 if (mLetterbox != null) {
3168 outBounds.set(mLetterbox.getInnerFrame());
3169 } else {
3170 outBounds.setEmpty();
3171 }
3172 }
3173
Adrian Roos23df3a32018-03-15 15:41:13 +01003174 /**
Riddle Hsu69de5fb2019-02-23 01:19:50 +08003175 * @return {@code true} if there is a letterbox and any part of that letterbox overlaps with
Adrian Roos23df3a32018-03-15 15:41:13 +01003176 * the given {@code rect}.
3177 */
3178 boolean isLetterboxOverlappingWith(Rect rect) {
3179 return mLetterbox != null && mLetterbox.isOverlappingWith(rect);
3180 }
chaviw4ad54912018-05-30 11:05:44 -07003181
3182 /**
3183 * Sets if this AWT is in the process of closing or entering PIP.
3184 * {@link #mWillCloseOrEnterPip}}
3185 */
3186 void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
3187 mWillCloseOrEnterPip = willCloseOrEnterPip;
3188 }
3189
3190 /**
3191 * Returns whether this AWT is considered closing. Conditions are either
3192 * 1. Is this app animating and was requested to be hidden
3193 * 2. App is delayed closing since it might enter PIP.
3194 */
3195 boolean isClosingOrEnteringPip() {
3196 return (isAnimating() && hiddenRequested) || mWillCloseOrEnterPip;
3197 }
Jorim Jaggiaf0d6d22018-06-08 15:25:35 +02003198
3199 /**
3200 * @return Whether we are allowed to show non-starting windows at the moment. We disallow
3201 * showing windows during transitions in case we have windows that have wide-color-gamut
3202 * color mode set to avoid jank in the middle of the transition.
3203 */
3204 boolean canShowWindows() {
3205 return allDrawn && !(isReallyAnimating() && hasNonDefaultColorWindow());
3206 }
3207
3208 /**
3209 * @return true if we have a window that has a non-default color mode set; false otherwise.
3210 */
3211 private boolean hasNonDefaultColorWindow() {
3212 return forAllWindows(ws -> ws.mAttrs.getColorMode() != COLOR_MODE_DEFAULT,
3213 true /* topToBottom */);
3214 }
lumark588a3e82018-07-20 18:53:54 +08003215
3216 void removeFromPendingTransition() {
3217 if (isWaitingForTransitionStart() && mDisplayContent != null) {
3218 mDisplayContent.mOpeningApps.remove(this);
Evan Rosky25b56192019-02-06 16:10:56 -08003219 if (mDisplayContent.mChangingApps.remove(this)) {
3220 clearChangeLeash(getPendingTransaction(), true /* cancel */);
3221 }
lumark588a3e82018-07-20 18:53:54 +08003222 mDisplayContent.mClosingApps.remove(this);
3223 }
3224 }
chaviwdcf76ec2019-01-11 16:48:46 -08003225
3226 private void updateColorTransform() {
3227 if (mSurfaceControl != null && mLastAppSaturationInfo != null) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003228 getPendingTransaction().setColorTransform(mSurfaceControl,
3229 mLastAppSaturationInfo.mMatrix, mLastAppSaturationInfo.mTranslation);
chaviwdcf76ec2019-01-11 16:48:46 -08003230 mWmService.scheduleAnimationLocked();
3231 }
3232 }
3233
3234 private static class AppSaturationInfo {
3235 float[] mMatrix = new float[9];
3236 float[] mTranslation = new float[3];
3237
3238 void setSaturation(@Size(9) float[] matrix, @Size(3) float[] translation) {
3239 System.arraycopy(matrix, 0, mMatrix, 0, mMatrix.length);
3240 System.arraycopy(translation, 0, mTranslation, 0, mTranslation.length);
3241 }
3242 }
Jeff Browne9bdb312012-04-05 15:30:10 -07003243}