blob: cae7612e0fcc29359347912111b71db11b723563 [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 Rosky08e20932019-05-14 10:54:07 -07001736 Task task = getTask();
1737 if (mThumbnail == null && task != null && !hasCommittedReparentToAnimationLeash()) {
1738 SurfaceControl.ScreenshotGraphicBuffer snapshot =
1739 mWmService.mTaskSnapshotController.createTaskSnapshot(
1740 task, 1 /* scaleFraction */);
Yunfan Chendcb1fcf2019-02-07 19:08:41 +09001741 if (snapshot != null) {
Evan Rosky08e20932019-05-14 10:54:07 -07001742 mThumbnail = new AppWindowThumbnail(t, this, snapshot.getGraphicBuffer(),
Yunfan Chendcb1fcf2019-02-07 19:08:41 +09001743 true /* relative */);
1744 }
Evan Rosky2289ba12018-11-19 18:28:18 -08001745 }
1746 }
1747
1748 boolean isInChangeTransition() {
Evan Roskyec9488c2019-03-01 19:32:12 -08001749 return mTransitChangeLeash != null || AppTransition.isChangeTransit(mTransit);
Evan Rosky2289ba12018-11-19 18:28:18 -08001750 }
1751
Evan Rosky966759f2019-01-15 10:33:58 -08001752 @VisibleForTesting
1753 AppWindowThumbnail getThumbnail() {
1754 return mThumbnail;
1755 }
1756
Riddle Hsub398da32019-01-21 21:48:16 +08001757 /**
1758 * Calculates the scale and offset to horizontal center the size compatibility bounds into the
1759 * region which is available to application.
1760 */
1761 private void calculateCompatBoundsTransformation(Configuration newParentConfig) {
1762 final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds();
Riddle Hsu74826262019-04-17 14:57:42 +08001763 final Rect parentBounds = newParentConfig.windowConfiguration.getBounds();
1764 final Rect viewportBounds = parentAppBounds != null ? parentAppBounds : parentBounds;
Riddle Hsu04164182019-03-07 18:03:27 +08001765 final Rect appBounds = getWindowConfiguration().getAppBounds();
1766 final Rect contentBounds = appBounds != null ? appBounds : getResolvedOverrideBounds();
Riddle Hsub398da32019-01-21 21:48:16 +08001767 final float contentW = contentBounds.width();
1768 final float contentH = contentBounds.height();
1769 final float viewportW = viewportBounds.width();
1770 final float viewportH = viewportBounds.height();
1771 // Only allow to scale down.
1772 mSizeCompatScale = (contentW <= viewportW && contentH <= viewportH)
1773 ? 1 : Math.min(viewportW / contentW, viewportH / contentH);
1774 final int offsetX = (int) ((viewportW - contentW * mSizeCompatScale + 1) * 0.5f)
1775 + viewportBounds.left;
1776
1777 if (mSizeCompatBounds == null) {
1778 mSizeCompatBounds = new Rect();
1779 }
1780 mSizeCompatBounds.set(contentBounds);
1781 mSizeCompatBounds.offsetTo(0, 0);
1782 mSizeCompatBounds.scale(mSizeCompatScale);
Riddle Hsu74826262019-04-17 14:57:42 +08001783 // Ensure to align the top with the parent.
1784 mSizeCompatBounds.top = parentBounds.top;
Riddle Hsu04164182019-03-07 18:03:27 +08001785 // The decor inset is included in height.
1786 mSizeCompatBounds.bottom += viewportBounds.top;
Riddle Hsub398da32019-01-21 21:48:16 +08001787 mSizeCompatBounds.left += offsetX;
1788 mSizeCompatBounds.right += offsetX;
1789 }
1790
1791 @Override
1792 public Rect getBounds() {
1793 if (mSizeCompatBounds != null) {
1794 return mSizeCompatBounds;
1795 }
1796 return super.getBounds();
1797 }
1798
1799 @Override
1800 public boolean matchParentBounds() {
1801 if (super.matchParentBounds()) {
1802 return true;
1803 }
1804 // An activity in size compatibility mode may have override bounds which equals to its
1805 // parent bounds, so the exact bounds should also be checked.
1806 final WindowContainer parent = getParent();
1807 return parent == null || parent.getBounds().equals(getResolvedOverrideBounds());
1808 }
1809
Winson Chunge55c0192017-08-24 14:50:48 -07001810 @Override
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001811 void checkAppWindowsReadyToShow() {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001812 if (allDrawn == mLastAllDrawn) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001813 return;
1814 }
1815
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001816 mLastAllDrawn = allDrawn;
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001817 if (!allDrawn) {
1818 return;
1819 }
1820
1821 // The token has now changed state to having all windows shown... what to do, what to do?
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001822 if (mFreezingScreen) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001823 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001824 stopFreezingScreen(false, true);
1825 if (DEBUG_ORIENTATION) Slog.i(TAG,
1826 "Setting mOrientationChangeComplete=true because wtoken " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001827 + " numInteresting=" + mNumInterestingWindows + " numDrawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001828 // This will set mOrientationChangeComplete and cause a pass through layout.
1829 setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001830 "checkAppWindowsReadyToShow: freezingScreen");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001831 } else {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001832 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001833
1834 // We can now show all of the drawn windows!
lumark588a3e82018-07-20 18:53:54 +08001835 if (!getDisplayContent().mOpeningApps.contains(this) && canShowWindows()) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001836 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001837 }
1838 }
1839 }
1840
Matthew Ng5d23afa2017-06-21 16:16:24 -07001841 /**
Bryce Leed390deb2017-06-22 13:14:28 -07001842 * Returns whether the drawn window states of this {@link AppWindowToken} has considered every
1843 * child {@link WindowState}. A child is considered if it has been passed into
1844 * {@link #updateDrawnWindowStates(WindowState)} after being added. This is used to determine
1845 * whether states, such as {@code allDrawn}, can be set, which relies on state variables such as
1846 * {@code mNumInterestingWindows}, which depend on all {@link WindowState}s being considered.
1847 *
1848 * @return {@code true} If all children have been considered, {@code false}.
1849 */
1850 private boolean allDrawnStatesConsidered() {
Bryce Lee6311c4b2017-07-06 14:09:29 -07001851 for (int i = mChildren.size() - 1; i >= 0; --i) {
1852 final WindowState child = mChildren.get(i);
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001853 if (child.mightAffectAllDrawn() && !child.getDrawnStateEvaluated()) {
Bryce Leed390deb2017-06-22 13:14:28 -07001854 return false;
1855 }
1856 }
1857 return true;
1858 }
1859
1860 /**
Matthew Ng5d23afa2017-06-21 16:16:24 -07001861 * Determines if the token has finished drawing. This should only be called from
1862 * {@link DisplayContent#applySurfaceChangesTransaction}
1863 */
Matthew Ng498c71d2017-04-18 13:55:45 -07001864 void updateAllDrawn() {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001865 if (!allDrawn) {
Matthew Ng498c71d2017-04-18 13:55:45 -07001866 // Number of drawn windows can be less when a window is being relaunched, wait for
Bryce Leed390deb2017-06-22 13:14:28 -07001867 // all windows to be launched and drawn for this token be considered all drawn.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001868 final int numInteresting = mNumInterestingWindows;
Bryce Leed390deb2017-06-22 13:14:28 -07001869
1870 // We must make sure that all present children have been considered (determined by
1871 // {@link #allDrawnStatesConsidered}) before evaluating whether everything has been
1872 // drawn.
1873 if (numInteresting > 0 && allDrawnStatesConsidered()
1874 && mNumDrawnWindows >= numInteresting && !isRelaunching()) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001875 if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawn: " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001876 + " interesting=" + numInteresting + " drawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001877 allDrawn = true;
1878 // Force an additional layout pass where
1879 // WindowStateAnimator#commitFinishDrawingLocked() will call performShowLocked().
Matthew Ng498c71d2017-04-18 13:55:45 -07001880 if (mDisplayContent != null) {
1881 mDisplayContent.setLayoutNeeded();
1882 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001883 mWmService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
Robert Carrecc06b32017-04-18 14:25:10 -07001884
Winson Chunge7ba6862017-05-24 12:13:33 -07001885 // Notify the pinned stack upon all windows drawn. If there was an animation in
1886 // progress then this signal will resume that animation.
Wale Ogunwale61911492017-10-11 08:50:50 -07001887 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
Winson Chunge7ba6862017-05-24 12:13:33 -07001888 if (pinnedStack != null) {
1889 pinnedStack.onAllWindowsDrawn();
Robert Carrecc06b32017-04-18 14:25:10 -07001890 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001891 }
1892 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001893 }
1894
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001895 boolean keyDispatchingTimedOut(String reason, int windowPid) {
1896 return mActivityRecord != null && mActivityRecord.keyDispatchingTimedOut(reason, windowPid);
1897 }
1898
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001899 /**
1900 * Updated this app token tracking states for interesting and drawn windows based on the window.
1901 *
1902 * @return Returns true if the input window is considered interesting and drawn while all the
1903 * windows in this app token where not considered drawn as of the last pass.
1904 */
1905 boolean updateDrawnWindowStates(WindowState w) {
Bryce Leed390deb2017-06-22 13:14:28 -07001906 w.setDrawnStateEvaluated(true /*evaluated*/);
1907
Jorim Jaggie4b0f282017-05-17 15:10:29 +02001908 if (DEBUG_STARTING_WINDOW_VERBOSE && w == startingWindow) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001909 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + w.isOnScreen()
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001910 + " allDrawn=" + allDrawn + " freezingScreen=" + mFreezingScreen);
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001911 }
1912
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001913 if (allDrawn && !mFreezingScreen) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001914 return false;
1915 }
1916
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001917 if (mLastTransactionSequence != mWmService.mTransactionSequence) {
1918 mLastTransactionSequence = mWmService.mTransactionSequence;
Matthew Ng53e66b22018-01-12 17:13:13 -08001919 mNumDrawnWindows = 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001920 startingDisplayed = false;
Matthew Ng53e66b22018-01-12 17:13:13 -08001921
1922 // There is the main base application window, even if it is exiting, wait for it
1923 mNumInterestingWindows = findMainWindow(false /* includeStartingApp */) != null ? 1 : 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001924 }
1925
1926 final WindowStateAnimator winAnimator = w.mWinAnimator;
1927
1928 boolean isInterestingAndDrawn = false;
1929
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001930 if (!allDrawn && w.mightAffectAllDrawn()) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001931 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
1932 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001933 + ", isAnimationSet=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001934 if (!w.isDrawnLw()) {
1935 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController
chaviw15ad49f2019-04-24 15:05:39 -07001936 + " pv=" + w.isVisibleByPolicy()
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001937 + " mDrawState=" + winAnimator.drawStateToString()
1938 + " ph=" + w.isParentWindowHidden() + " th=" + hiddenRequested
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001939 + " a=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001940 }
1941 }
1942
1943 if (w != startingWindow) {
1944 if (w.isInteresting()) {
Matthew Ng53e66b22018-01-12 17:13:13 -08001945 // Add non-main window as interesting since the main app has already been added
1946 if (findMainWindow(false /* includeStartingApp */) != w) {
1947 mNumInterestingWindows++;
1948 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001949 if (w.isDrawnLw()) {
1950 mNumDrawnWindows++;
1951
1952 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, "tokenMayBeDrawn: "
1953 + this + " w=" + w + " numInteresting=" + mNumInterestingWindows
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001954 + " freezingScreen=" + mFreezingScreen
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001955 + " mAppFreezing=" + w.mAppFreezing);
1956
1957 isInterestingAndDrawn = true;
1958 }
1959 }
1960 } else if (w.isDrawnLw()) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001961 if (mActivityRecord != null) {
1962 mActivityRecord.onStartingWindowDrawn(SystemClock.uptimeMillis());
Jorim Jaggi3878ca32017-02-02 17:13:05 -08001963 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001964 startingDisplayed = true;
1965 }
1966 }
1967
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001968 return isInterestingAndDrawn;
1969 }
1970
Adrian Roos23df3a32018-03-15 15:41:13 +01001971 void layoutLetterbox(WindowState winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001972 final WindowState w = findMainWindow();
Adrian Roosf93b6d22018-03-21 13:48:26 +01001973 if (w == null || winHint != null && w != winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001974 return;
1975 }
Jorim Jaggia32da382018-03-28 18:01:22 +02001976 final boolean surfaceReady = w.isDrawnLw() // Regular case
Adrian Roosf93b6d22018-03-21 13:48:26 +01001977 || w.mWinAnimator.mSurfaceDestroyDeferred // The preserved surface is still ready.
1978 || w.isDragResizeChanged(); // Waiting for relayoutWindow to call preserveSurface.
Jorim Jaggi4981f152019-03-26 18:58:45 +01001979 final boolean needsLetterbox = surfaceReady && w.isLetterboxedAppWindow() && fillsParent();
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001980 if (needsLetterbox) {
1981 if (mLetterbox == null) {
1982 mLetterbox = new Letterbox(() -> makeChildSurface(null));
Riddle Hsu192fe762019-01-15 23:41:57 +08001983 mLetterbox.attachInput(w);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001984 }
Adrian Roos7af9d972018-11-30 15:26:27 +01001985 getPosition(mTmpPoint);
Evan Rosky67c15642019-04-24 13:17:28 -07001986 // Get the bounds of the "space-to-fill". In multi-window mode, the task-level
1987 // represents this. In fullscreen-mode, the stack does (since the orientation letterbox
1988 // is also applied to the task).
1989 Rect spaceToFill = (inMultiWindowMode() || getStack() == null)
1990 ? getTask().getDisplayedBounds() : getStack().getDisplayedBounds();
Evan Rosky4fb1e912019-03-06 13:54:43 -08001991 mLetterbox.layout(spaceToFill, w.getFrameLw(), mTmpPoint);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001992 } else if (mLetterbox != null) {
Adrian Roos23df3a32018-03-15 15:41:13 +01001993 mLetterbox.hide();
1994 }
1995 }
1996
1997 void updateLetterboxSurface(WindowState winHint) {
1998 final WindowState w = findMainWindow();
1999 if (w != winHint && winHint != null && w != null) {
2000 return;
2001 }
2002 layoutLetterbox(winHint);
2003 if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) {
Tiger Huanged6794e2019-05-07 20:07:59 +08002004 mLetterbox.applySurfaceChanges(getPendingTransaction());
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002005 }
2006 }
2007
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07002008 @Override
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002009 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002010 // For legacy reasons we process the TaskStack.mExitingAppTokens first in DisplayContent
2011 // before the non-exiting app tokens. So, we skip the exiting app tokens here.
2012 // TODO: Investigate if we need to continue to do this or if we can just process them
2013 // in-order.
2014 if (mIsExiting && !waitingForReplacement()) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002015 return false;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002016 }
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002017 return forAllWindowsUnchecked(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002018 }
2019
lumark588a3e82018-07-20 18:53:54 +08002020 @Override
2021 void forAllAppWindows(Consumer<AppWindowToken> callback) {
2022 callback.accept(this);
2023 }
2024
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002025 boolean forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback,
2026 boolean traverseTopToBottom) {
2027 return super.forAllWindows(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002028 }
2029
2030 @Override
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002031 AppWindowToken asAppWindowToken() {
2032 // I am an app window token!
2033 return this;
2034 }
2035
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002036 boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
2037 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
2038 IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
2039 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
2040 // If the display is frozen, we won't do anything until the actual window is
2041 // displayed so there is no reason to put in the starting window.
2042 if (!okToDisplay()) {
2043 return false;
2044 }
2045
chaviwa8f07a72019-05-01 16:25:39 -07002046 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002047 return false;
2048 }
2049
2050 final WindowState mainWin = findMainWindow();
2051 if (mainWin != null && mainWin.mWinAnimator.getShown()) {
2052 // App already has a visible window...why would you want a starting window?
2053 return false;
2054 }
2055
2056 final ActivityManager.TaskSnapshot snapshot =
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002057 mWmService.mTaskSnapshotController.getSnapshot(
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002058 getTask().mTaskId, getTask().mUserId,
2059 false /* restoreFromDisk */, false /* reducedResolution */);
2060 final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
2061 allowTaskSnapshot, activityCreated, fromRecents, snapshot);
2062
2063 if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
2064 return createSnapshot(snapshot);
2065 }
2066
2067 // If this is a translucent window, then don't show a starting window -- the current
2068 // effect (a full-screen opaque starting window that fades away to the real contents
2069 // when it is ready) does not work for this.
2070 if (DEBUG_STARTING_WINDOW) {
2071 Slog.v(TAG, "Checking theme of starting window: 0x" + Integer.toHexString(theme));
2072 }
2073 if (theme != 0) {
2074 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
2075 com.android.internal.R.styleable.Window,
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002076 mWmService.mCurrentUserId);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002077 if (ent == null) {
2078 // Whoops! App doesn't exist. Um. Okay. We'll just pretend like we didn't
2079 // see that.
2080 return false;
2081 }
2082 final boolean windowIsTranslucent = ent.array.getBoolean(
2083 com.android.internal.R.styleable.Window_windowIsTranslucent, false);
2084 final boolean windowIsFloating = ent.array.getBoolean(
2085 com.android.internal.R.styleable.Window_windowIsFloating, false);
2086 final boolean windowShowWallpaper = ent.array.getBoolean(
2087 com.android.internal.R.styleable.Window_windowShowWallpaper, false);
2088 final boolean windowDisableStarting = ent.array.getBoolean(
2089 com.android.internal.R.styleable.Window_windowDisablePreview, false);
2090 if (DEBUG_STARTING_WINDOW) {
2091 Slog.v(TAG, "Translucent=" + windowIsTranslucent
2092 + " Floating=" + windowIsFloating
2093 + " ShowWallpaper=" + windowShowWallpaper);
2094 }
2095 if (windowIsTranslucent) {
2096 return false;
2097 }
2098 if (windowIsFloating || windowDisableStarting) {
2099 return false;
2100 }
2101 if (windowShowWallpaper) {
2102 if (getDisplayContent().mWallpaperController
2103 .getWallpaperTarget() == null) {
2104 // If this theme is requesting a wallpaper, and the wallpaper
2105 // is not currently visible, then this effectively serves as
2106 // an opaque window and our starting window transition animation
2107 // can still work. We just need to make sure the starting window
2108 // is also showing the wallpaper.
2109 windowFlags |= FLAG_SHOW_WALLPAPER;
2110 } else {
2111 return false;
2112 }
2113 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002114 }
Yunfan Chen8a8c0ed2018-12-18 16:46:32 -08002115
2116 if (transferStartingWindow(transferFrom)) {
2117 return true;
2118 }
2119
2120 // There is no existing starting window, and we don't want to create a splash screen, so
2121 // that's it!
2122 if (type != STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
2123 return false;
2124 }
2125
2126 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SplashScreenStartingData");
chaviwa8f07a72019-05-01 16:25:39 -07002127 mStartingData = new SplashScreenStartingData(mWmService, pkg,
Yunfan Chen8a8c0ed2018-12-18 16:46:32 -08002128 theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
2129 getMergedOverrideConfiguration());
2130 scheduleAddStartingWindow();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002131 return true;
2132 }
2133
2134
2135 private boolean createSnapshot(ActivityManager.TaskSnapshot snapshot) {
2136 if (snapshot == null) {
2137 return false;
2138 }
2139
2140 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SnapshotStartingData");
chaviwa8f07a72019-05-01 16:25:39 -07002141 mStartingData = new SnapshotStartingData(mWmService, snapshot);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002142 scheduleAddStartingWindow();
2143 return true;
2144 }
2145
2146 void scheduleAddStartingWindow() {
2147 // Note: we really want to do sendMessageAtFrontOfQueue() because we
2148 // want to process the message ASAP, before any other queued
2149 // messages.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002150 if (!mWmService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002151 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING");
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002152 mWmService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002153 }
2154 }
2155
2156 private final Runnable mAddStartingWindow = new Runnable() {
2157
2158 @Override
2159 public void run() {
chaviwa8f07a72019-05-01 16:25:39 -07002160 // Can be accessed without holding the global lock
2161 final StartingData startingData;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002162 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002163 // There can only be one adding request, silly caller!
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002164 mWmService.mAnimationHandler.removeCallbacks(this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002165
chaviwa8f07a72019-05-01 16:25:39 -07002166 if (mStartingData == null) {
2167 // Animation has been canceled... do nothing.
2168 if (DEBUG_STARTING_WINDOW) {
2169 Slog.v(TAG, "startingData was nulled out before handling"
2170 + " mAddStartingWindow: " + AppWindowToken.this);
2171 }
2172 return;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002173 }
chaviwa8f07a72019-05-01 16:25:39 -07002174 startingData = mStartingData;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002175 }
2176
2177 if (DEBUG_STARTING_WINDOW) {
2178 Slog.v(TAG, "Add starting " + this + ": startingData=" + startingData);
2179 }
2180
2181 WindowManagerPolicy.StartingSurface surface = null;
2182 try {
2183 surface = startingData.createStartingSurface(AppWindowToken.this);
2184 } catch (Exception e) {
2185 Slog.w(TAG, "Exception when adding starting window", e);
2186 }
2187 if (surface != null) {
2188 boolean abort = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002189 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002190 // If the window was successfully added, then
2191 // we need to remove it.
chaviwa8f07a72019-05-01 16:25:39 -07002192 if (removed || mStartingData == null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002193 if (DEBUG_STARTING_WINDOW) {
2194 Slog.v(TAG, "Aborted starting " + AppWindowToken.this
chaviwa8f07a72019-05-01 16:25:39 -07002195 + ": removed=" + removed + " startingData=" + mStartingData);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002196 }
2197 startingWindow = null;
chaviwa8f07a72019-05-01 16:25:39 -07002198 mStartingData = null;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002199 abort = true;
2200 } else {
2201 startingSurface = surface;
2202 }
2203 if (DEBUG_STARTING_WINDOW && !abort) {
chaviwa8f07a72019-05-01 16:25:39 -07002204 Slog.v(TAG,
2205 "Added starting " + AppWindowToken.this + ": startingWindow="
2206 + startingWindow + " startingView=" + startingSurface);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002207 }
2208 }
2209 if (abort) {
2210 surface.remove();
2211 }
2212 } else if (DEBUG_STARTING_WINDOW) {
2213 Slog.v(TAG, "Surface returned was null: " + AppWindowToken.this);
2214 }
2215 }
2216 };
2217
2218 private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
2219 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents,
2220 ActivityManager.TaskSnapshot snapshot) {
2221 if (getDisplayContent().mAppTransition.getAppTransition()
2222 == TRANSIT_DOCK_TASK_FROM_RECENTS) {
2223 // TODO(b/34099271): Remove this statement to add back the starting window and figure
2224 // out why it causes flickering, the starting window appears over the thumbnail while
2225 // the docked from recents transition occurs
2226 return STARTING_WINDOW_TYPE_NONE;
2227 } else if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
2228 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2229 } else if (taskSwitch && allowTaskSnapshot) {
Kevin716a9db2018-12-18 16:53:39 -08002230 if (mWmService.mLowRamTaskSnapshotsAndRecents) {
Kevin58b47f12018-12-17 14:09:01 -08002231 // For low RAM devices, we use the splash screen starting window instead of the
2232 // task snapshot starting window.
2233 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2234 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002235 return snapshot == null ? STARTING_WINDOW_TYPE_NONE
2236 : snapshotOrientationSameAsTask(snapshot) || fromRecents
2237 ? STARTING_WINDOW_TYPE_SNAPSHOT : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2238 } else {
2239 return STARTING_WINDOW_TYPE_NONE;
2240 }
2241 }
2242
2243
2244 private boolean snapshotOrientationSameAsTask(ActivityManager.TaskSnapshot snapshot) {
2245 if (snapshot == null) {
2246 return false;
2247 }
2248 return getTask().getConfiguration().orientation == snapshot.getOrientation();
2249 }
2250
2251 void removeStartingWindow() {
2252 if (startingWindow == null) {
chaviwa8f07a72019-05-01 16:25:39 -07002253 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002254 // Starting window has not been added yet, but it is scheduled to be added.
2255 // Go ahead and cancel the request.
2256 if (DEBUG_STARTING_WINDOW) {
2257 Slog.v(TAG_WM, "Clearing startingData for token=" + this);
2258 }
chaviwa8f07a72019-05-01 16:25:39 -07002259 mStartingData = null;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002260 }
2261 return;
2262 }
2263
2264 final WindowManagerPolicy.StartingSurface surface;
chaviwa8f07a72019-05-01 16:25:39 -07002265 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002266 surface = startingSurface;
chaviwa8f07a72019-05-01 16:25:39 -07002267 mStartingData = null;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002268 startingSurface = null;
2269 startingWindow = null;
2270 startingDisplayed = false;
2271 if (surface == null) {
2272 if (DEBUG_STARTING_WINDOW) {
2273 Slog.v(TAG_WM, "startingWindow was set but startingSurface==null, couldn't "
2274 + "remove");
2275 }
2276 return;
2277 }
2278 } else {
2279 if (DEBUG_STARTING_WINDOW) {
2280 Slog.v(TAG_WM, "Tried to remove starting window but startingWindow was null:"
2281 + this);
2282 }
2283 return;
2284 }
2285
2286 if (DEBUG_STARTING_WINDOW) {
2287 Slog.v(TAG_WM, "Schedule remove starting " + this
2288 + " startingWindow=" + startingWindow
2289 + " startingView=" + startingSurface
2290 + " Callers=" + Debug.getCallers(5));
2291 }
2292
2293 // Use the same thread to remove the window as we used to add it, as otherwise we end up
2294 // with things in the view hierarchy being called from different threads.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002295 mWmService.mAnimationHandler.post(() -> {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002296 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Removing startingView=" + surface);
2297 try {
2298 surface.remove();
2299 } catch (Exception e) {
2300 Slog.w(TAG_WM, "Exception when removing starting window", e);
2301 }
2302 });
2303 }
2304
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002305 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -07002306 boolean fillsParent() {
2307 return mFillsParent;
2308 }
2309
2310 void setFillsParent(boolean fillsParent) {
2311 mFillsParent = fillsParent;
2312 }
2313
Jorim Jaggife762342016-10-13 14:33:27 +02002314 boolean containsDismissKeyguardWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002315 // Window state is transient during relaunch. We are not guaranteed to be frozen during the
2316 // entirety of the relaunch.
2317 if (isRelaunching()) {
2318 return mLastContainsDismissKeyguardWindow;
2319 }
2320
Jorim Jaggife762342016-10-13 14:33:27 +02002321 for (int i = mChildren.size() - 1; i >= 0; i--) {
2322 if ((mChildren.get(i).mAttrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
2323 return true;
2324 }
2325 }
2326 return false;
2327 }
2328
2329 boolean containsShowWhenLockedWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002330 // When we are relaunching, it is possible for us to be unfrozen before our previous
2331 // windows have been added back. Using the cached value ensures that our previous
2332 // showWhenLocked preference is honored until relaunching is complete.
2333 if (isRelaunching()) {
2334 return mLastContainsShowWhenLockedWindow;
2335 }
2336
Jorim Jaggife762342016-10-13 14:33:27 +02002337 for (int i = mChildren.size() - 1; i >= 0; i--) {
2338 if ((mChildren.get(i).mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
2339 return true;
2340 }
2341 }
Bryce Lee081554b2017-05-25 07:52:12 -07002342
Jorim Jaggife762342016-10-13 14:33:27 +02002343 return false;
2344 }
2345
2346 void checkKeyguardFlagsChanged() {
2347 final boolean containsDismissKeyguard = containsDismissKeyguardWindow();
2348 final boolean containsShowWhenLocked = containsShowWhenLockedWindow();
2349 if (containsDismissKeyguard != mLastContainsDismissKeyguardWindow
2350 || containsShowWhenLocked != mLastContainsShowWhenLockedWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002351 mWmService.notifyKeyguardFlagsChanged(null /* callback */,
lumark588a3e82018-07-20 18:53:54 +08002352 getDisplayContent().getDisplayId());
Jorim Jaggife762342016-10-13 14:33:27 +02002353 }
2354 mLastContainsDismissKeyguardWindow = containsDismissKeyguard;
2355 mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
2356 }
2357
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002358 WindowState getImeTargetBelowWindow(WindowState w) {
2359 final int index = mChildren.indexOf(w);
2360 if (index > 0) {
2361 final WindowState target = mChildren.get(index - 1);
2362 if (target.canBeImeTarget()) {
2363 return target;
2364 }
2365 }
2366 return null;
2367 }
2368
2369 WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
2370 WindowState candidate = null;
2371 for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
2372 final WindowState w = mChildren.get(i);
2373 if (w.mRemoved) {
2374 continue;
2375 }
Jorim Jaggi35d328a2018-08-14 17:00:20 +02002376 if (candidate == null) {
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002377 candidate = w;
2378 }
2379 }
2380 return candidate;
2381 }
2382
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002383 /**
2384 * See {@link Activity#setDisablePreviewScreenshots}.
2385 */
2386 void setDisablePreviewScreenshots(boolean disable) {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002387 mDisablePreviewScreenshots = disable;
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002388 }
2389
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002390 /**
chaviwd3bf08d2017-08-01 17:24:59 -07002391 * Sets whether the current launch can turn the screen on. See {@link #canTurnScreenOn()}
2392 */
2393 void setCanTurnScreenOn(boolean canTurnScreenOn) {
2394 mCanTurnScreenOn = canTurnScreenOn;
2395 }
2396
2397 /**
2398 * Indicates whether the current launch can turn the screen on. This is to prevent multiple
2399 * relayouts from turning the screen back on. The screen should only turn on at most
2400 * once per activity resume.
2401 *
2402 * @return true if the screen can be turned on.
2403 */
2404 boolean canTurnScreenOn() {
2405 return mCanTurnScreenOn;
2406 }
2407
2408 /**
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002409 * Retrieves whether we'd like to generate a snapshot that's based solely on the theme. This is
2410 * the case when preview screenshots are disabled {@link #setDisablePreviewScreenshots} or when
2411 * we can't take a snapshot for other reasons, for example, if we have a secure window.
2412 *
2413 * @return True if we need to generate an app theme snapshot, false if we'd like to take a real
2414 * screenshot.
2415 */
2416 boolean shouldUseAppThemeSnapshot() {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002417 return mDisablePreviewScreenshots || forAllWindows(w -> (w.mAttrs.flags & FLAG_SECURE) != 0,
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002418 true /* topToBottom */);
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002419 }
2420
Jorim Jaggibe418292018-03-26 16:14:12 +02002421 SurfaceControl getAppAnimationLayer() {
Jorim Jaggi391790622018-04-18 15:30:44 +02002422 return getAppAnimationLayer(isActivityTypeHome() ? ANIMATION_LAYER_HOME
2423 : needsZBoost() ? ANIMATION_LAYER_BOOSTED
2424 : ANIMATION_LAYER_STANDARD);
Jorim Jaggibe418292018-03-26 16:14:12 +02002425 }
2426
chaviw23ee71c2017-12-18 11:29:41 -08002427 @Override
Jorim Jaggi596a1992017-12-29 14:48:02 +01002428 public SurfaceControl getAnimationLeashParent() {
Robert Carrb9506032018-02-13 13:54:00 -08002429 // All normal app transitions take place in an animation layer which is below the pinned
2430 // stack but may be above the parent stacks of the given animating apps.
2431 // For transitions in the pinned stack (menu activity) we just let them occur as a child
2432 // of the pinned stack.
2433 if (!inPinnedWindowingMode()) {
2434 return getAppAnimationLayer();
2435 } else {
2436 return getStack().getSurfaceControl();
2437 }
chaviw23ee71c2017-12-18 11:29:41 -08002438 }
2439
lumarkb5a78b32019-04-25 20:31:30 +08002440
2441 @VisibleForTesting
2442 boolean shouldAnimate(int transit) {
Jorim Jaggic6976f02018-04-18 16:31:07 +02002443 final boolean isSplitScreenPrimary =
2444 getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
2445 final boolean allowSplitScreenPrimaryAnimation = transit != TRANSIT_WALLPAPER_OPEN;
2446
lumarkb5a78b32019-04-25 20:31:30 +08002447 // Don't animate while the task runs recents animation but only if we are in the mode
2448 // where we cancel with deferred screenshot, which means that the controller has
2449 // transformed the task.
lumark54284462019-03-05 20:44:27 +08002450 final RecentsAnimationController controller = mWmService.getRecentsAnimationController();
lumarkb5a78b32019-04-25 20:31:30 +08002451 if (controller != null && controller.isAnimatingTask(getTask())
2452 && controller.shouldCancelWithDeferredScreenshot()) {
lumark54284462019-03-05 20:44:27 +08002453 return false;
2454 }
2455
Jorim Jaggic6976f02018-04-18 16:31:07 +02002456 // We animate always if it's not split screen primary, and only some special cases in split
2457 // screen primary because it causes issues with stack clipping when we run an un-minimize
2458 // animation at the same time.
2459 return !isSplitScreenPrimary || allowSplitScreenPrimaryAnimation;
2460 }
2461
Vishnu Naira2977262018-07-26 13:31:26 -07002462 /**
2463 * Creates a layer to apply crop to an animation.
2464 */
2465 private SurfaceControl createAnimationBoundsLayer(Transaction t) {
2466 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.i(TAG, "Creating animation bounds layer");
2467 final SurfaceControl.Builder builder = makeAnimationLeash()
2468 .setParent(getAnimationLeashParent())
Vishnu Naire86bd982018-11-28 13:23:17 -08002469 .setName(getSurfaceControl() + " - animation-bounds");
Vishnu Naira2977262018-07-26 13:31:26 -07002470 final SurfaceControl boundsLayer = builder.build();
2471 t.show(boundsLayer);
2472 return boundsLayer;
2473 }
2474
Evan Roskyed6767f2018-10-26 17:21:06 -07002475 @Override
2476 Rect getDisplayedBounds() {
2477 final Task task = getTask();
2478 if (task != null) {
2479 final Rect overrideDisplayedBounds = task.getOverrideDisplayedBounds();
2480 if (!overrideDisplayedBounds.isEmpty()) {
2481 return overrideDisplayedBounds;
2482 }
2483 }
2484 return getBounds();
2485 }
2486
Evan Rosky641daea2019-04-24 14:45:24 -07002487 @VisibleForTesting
2488 Rect getAnimationBounds(int appStackClipMode) {
2489 if (appStackClipMode == STACK_CLIP_BEFORE_ANIM && getStack() != null) {
2490 // Using the stack bounds here effectively applies the clipping before animation.
2491 return getStack().getBounds();
2492 }
2493 // Use task-bounds if available so that activity-level letterbox (maxAspectRatio) is
2494 // included in the animation.
2495 return getTask() != null ? getTask().getBounds() : getBounds();
2496 }
2497
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002498 boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter,
2499 boolean isVoiceInteraction) {
2500
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002501 if (mWmService.mDisableTransitionAnimation || !shouldAnimate(transit)) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002502 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
Jorim Jaggic6976f02018-04-18 16:31:07 +02002503 Slog.v(TAG_WM, "applyAnimation: transition animation is disabled or skipped."
2504 + " atoken=" + this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002505 }
2506 cancelAnimation();
2507 return false;
2508 }
2509
2510 // Only apply an animation if the display isn't frozen. If it is frozen, there is no reason
2511 // to animate and it can cause strange artifacts when we unfreeze the display if some
2512 // different animation is running.
2513 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#applyAnimationLocked");
2514 if (okToAnimate()) {
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002515 final AnimationAdapter adapter;
Evan Rosky2289ba12018-11-19 18:28:18 -08002516 AnimationAdapter thumbnailAdapter = null;
Evan Rosky4fb1e912019-03-06 13:54:43 -08002517
Evan Rosky641daea2019-04-24 14:45:24 -07002518 final int appStackClipMode =
2519 getDisplayContent().mAppTransition.getAppStackClipMode();
2520
2521 // Separate position and size for use in animators.
2522 mTmpRect.set(getAnimationBounds(appStackClipMode));
Evan Rosky4fb1e912019-03-06 13:54:43 -08002523 mTmpPoint.set(mTmpRect.left, mTmpRect.top);
2524 mTmpRect.offsetTo(0, 0);
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002525
Evan Roskyec9488c2019-03-01 19:32:12 -08002526 final boolean isChanging = AppTransition.isChangeTransit(transit) && enter
2527 && getDisplayContent().mChangingApps.contains(this);
Evan Rosky2289ba12018-11-19 18:28:18 -08002528
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002529 // Delaying animation start isn't compatible with remote animations at all.
lumark588a3e82018-07-20 18:53:54 +08002530 if (getDisplayContent().mAppTransition.getRemoteAnimationController() != null
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002531 && !mSurfaceAnimator.isAnimationStartDelayed()) {
Evan Rosky2289ba12018-11-19 18:28:18 -08002532 RemoteAnimationRecord adapters =
2533 getDisplayContent().mAppTransition.getRemoteAnimationController()
2534 .createRemoteAnimationRecord(this, mTmpPoint, mTmpRect,
2535 (isChanging ? mTransitStartRect : null));
2536 adapter = adapters.mAdapter;
2537 thumbnailAdapter = adapters.mThumbnailAdapter;
2538 } else if (isChanging) {
Evan Roskycf76bed2019-01-15 10:33:58 -08002539 final float durationScale = mWmService.getTransitionAnimationScaleLocked();
Evan Rosky2289ba12018-11-19 18:28:18 -08002540 mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y);
2541 adapter = new LocalAnimationAdapter(
2542 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
Evan Roskycf76bed2019-01-15 10:33:58 -08002543 getDisplayContent().getDisplayInfo(), durationScale,
Evan Rosky2289ba12018-11-19 18:28:18 -08002544 true /* isAppAnimation */, false /* isThumbnail */),
2545 mWmService.mSurfaceAnimationRunner);
Evan Rosky966759f2019-01-15 10:33:58 -08002546 if (mThumbnail != null) {
2547 thumbnailAdapter = new LocalAnimationAdapter(
2548 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
Evan Roskycf76bed2019-01-15 10:33:58 -08002549 getDisplayContent().getDisplayInfo(), durationScale,
Evan Rosky966759f2019-01-15 10:33:58 -08002550 true /* isAppAnimation */, true /* isThumbnail */),
2551 mWmService.mSurfaceAnimationRunner);
2552 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002553 mTransit = transit;
2554 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002555 } else {
Vishnu Naira2977262018-07-26 13:31:26 -07002556 mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM);
2557
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002558 final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
2559 if (a != null) {
Lucas Dupin95acf432019-04-29 17:55:38 -07002560 // Only apply corner radius to animation if we're not in multi window mode.
2561 // We don't want rounded corners when in pip or split screen.
2562 final float windowCornerRadius = !inMultiWindowMode()
2563 ? getDisplayContent().getWindowCornerRadius()
2564 : 0;
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002565 adapter = new LocalAnimationAdapter(
2566 new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
lumark588a3e82018-07-20 18:53:54 +08002567 getDisplayContent().mAppTransition.canSkipFirstFrame(),
Vishnu Naira2977262018-07-26 13:31:26 -07002568 appStackClipMode,
Lucas Dupin3e1dc202018-12-02 15:14:20 -08002569 true /* isAppAnimation */,
Lucas Dupin95acf432019-04-29 17:55:38 -07002570 windowCornerRadius),
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002571 mWmService.mSurfaceAnimationRunner);
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002572 if (a.getZAdjustment() == Animation.ZORDER_TOP) {
2573 mNeedsZBoost = true;
2574 }
2575 mTransit = transit;
lumark588a3e82018-07-20 18:53:54 +08002576 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002577 } else {
2578 adapter = null;
chaviw23ee71c2017-12-18 11:29:41 -08002579 }
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002580 }
2581 if (adapter != null) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002582 startAnimation(getPendingTransaction(), adapter, !isVisible());
Jorim Jaggi82c17862018-02-21 17:50:18 +01002583 if (adapter.getShowWallpaper()) {
2584 mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2585 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002586 if (thumbnailAdapter != null) {
2587 mThumbnail.startAnimation(
2588 getPendingTransaction(), thumbnailAdapter, !isVisible());
2589 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002590 }
2591 } else {
2592 cancelAnimation();
2593 }
2594 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2595
2596 return isReallyAnimating();
2597 }
2598
2599 private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
2600 boolean isVoiceInteraction) {
2601 final DisplayContent displayContent = getTask().getDisplayContent();
2602 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2603 final int width = displayInfo.appWidth;
2604 final int height = displayInfo.appHeight;
2605 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG_WM,
2606 "applyAnimation: atoken=" + this);
2607
2608 // Determine the visible rect to calculate the thumbnail clip
2609 final WindowState win = findMainWindow();
2610 final Rect frame = new Rect(0, 0, width, height);
2611 final Rect displayFrame = new Rect(0, 0,
2612 displayInfo.logicalWidth, displayInfo.logicalHeight);
2613 final Rect insets = new Rect();
2614 final Rect stableInsets = new Rect();
2615 Rect surfaceInsets = null;
2616 final boolean freeform = win != null && win.inFreeformWindowingMode();
2617 if (win != null) {
2618 // Containing frame will usually cover the whole screen, including dialog windows.
2619 // For freeform workspace windows it will not cover the whole screen and it also
2620 // won't exactly match the final freeform window frame (e.g. when overlapping with
2621 // the status bar). In that case we need to use the final frame.
2622 if (freeform) {
chaviw492139a2018-07-16 16:07:35 -07002623 frame.set(win.getFrameLw());
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002624 } else if (win.isLetterboxedAppWindow()) {
2625 frame.set(getTask().getBounds());
Winson Chungc1674272018-02-21 10:15:17 -08002626 } else if (win.isDockedResizing()) {
2627 // If we are animating while docked resizing, then use the stack bounds as the
2628 // animation target (which will be different than the task bounds)
2629 frame.set(getTask().getParent().getBounds());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002630 } else {
chaviw553b0212018-07-12 13:37:01 -07002631 frame.set(win.getContainingFrame());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002632 }
2633 surfaceInsets = win.getAttrs().surfaceInsets;
Adrian Roos20e07892018-02-23 19:12:01 +01002634 // XXX(b/72757033): These are insets relative to the window frame, but we're really
2635 // interested in the insets relative to the frame we chose in the if-blocks above.
chaviw9c81e632018-07-31 11:17:52 -07002636 win.getContentInsets(insets);
2637 win.getStableInsets(stableInsets);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002638 }
2639
2640 if (mLaunchTaskBehind) {
2641 // Differentiate the two animations. This one which is briefly on the screen
2642 // gets the !enter animation, and the other activity which remains on the
2643 // screen gets the enter animation. Both appear in the mOpeningApps set.
2644 enter = false;
2645 }
2646 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "Loading animation for app transition."
2647 + " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter
2648 + " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets);
2649 final Configuration displayConfig = displayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08002650 final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002651 displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
2652 surfaceInsets, stableInsets, isVoiceInteraction, freeform, getTask().mTaskId);
2653 if (a != null) {
2654 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
2655 final int containingWidth = frame.width();
2656 final int containingHeight = frame.height();
2657 a.initialize(containingWidth, containingHeight, width, height);
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002658 a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002659 }
2660 return a;
2661 }
2662
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002663 @Override
Jorim Jaggi6de61012018-03-19 14:53:23 +01002664 public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
2665 return mAnimatingAppWindowTokenRegistry != null
2666 && mAnimatingAppWindowTokenRegistry.notifyAboutToFinish(
2667 this, endDeferFinishCallback);
2668 }
2669
2670 @Override
lumarkf6f34942019-04-29 16:56:50 +08002671 public void onAnimationLeashLost(Transaction t) {
2672 super.onAnimationLeashLost(t);
Vishnu Naira2977262018-07-26 13:31:26 -07002673 if (mAnimationBoundsLayer != null) {
Robert Carr71200f22019-02-05 09:44:53 -08002674 t.remove(mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002675 mAnimationBoundsLayer = null;
2676 }
2677
Jorim Jaggi6de61012018-03-19 14:53:23 +01002678 if (mAnimatingAppWindowTokenRegistry != null) {
2679 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
2680 }
2681 }
2682
2683 @Override
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002684 protected void setLayer(Transaction t, int layer) {
2685 if (!mSurfaceAnimator.hasLeash()) {
2686 t.setLayer(mSurfaceControl, layer);
2687 }
2688 }
2689
2690 @Override
2691 protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
2692 if (!mSurfaceAnimator.hasLeash()) {
2693 t.setRelativeLayer(mSurfaceControl, relativeTo, layer);
2694 }
2695 }
2696
2697 @Override
2698 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
2699 if (!mSurfaceAnimator.hasLeash()) {
Robert Carr10584fa2019-01-14 15:55:19 -08002700 t.reparent(mSurfaceControl, newParent);
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002701 }
2702 }
2703
2704 @Override
2705 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002706 // The leash is parented to the animation layer. We need to preserve the z-order by using
2707 // the prefix order index, but we boost if necessary.
Robert Carrb9506032018-02-13 13:54:00 -08002708 int layer = 0;
2709 if (!inPinnedWindowingMode()) {
2710 layer = getPrefixOrderIndex();
2711 } else {
2712 // Pinned stacks have animations take place within themselves rather than an animation
2713 // layer so we need to preserve the order relative to the stack (e.g. the order of our
2714 // task/parent).
2715 layer = getParent().getPrefixOrderIndex();
2716 }
2717
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002718 if (mNeedsZBoost) {
2719 layer += Z_BOOST_BASE;
2720 }
Jorim Jaggi9cd99132019-04-24 17:41:35 +02002721 if (!mNeedsAnimationBoundsLayer) {
2722 leash.setLayer(layer);
2723 }
Robert Carr2f8aa392018-01-31 14:46:51 -08002724
2725 final DisplayContent dc = getDisplayContent();
Jorim Jaggibe418292018-03-26 16:14:12 +02002726 dc.assignStackOrdering();
Evan Rosky2289ba12018-11-19 18:28:18 -08002727
2728 if (leash == mTransitChangeLeash) {
2729 // This is a temporary state so skip any animation notifications
2730 return;
2731 } else if (mTransitChangeLeash != null) {
2732 // unparent mTransitChangeLeash for clean-up
Evan Rosky25b56192019-02-06 16:10:56 -08002733 clearChangeLeash(t, false /* cancel */);
Evan Rosky2289ba12018-11-19 18:28:18 -08002734 }
2735
Jorim Jaggi6de61012018-03-19 14:53:23 +01002736 if (mAnimatingAppWindowTokenRegistry != null) {
2737 mAnimatingAppWindowTokenRegistry.notifyStarting(this);
2738 }
Vishnu Naira2977262018-07-26 13:31:26 -07002739
2740 // If the animation needs to be cropped then an animation bounds layer is created as a child
2741 // of the pinned stack or animation layer. The leash is then reparented to this new layer.
2742 if (mNeedsAnimationBoundsLayer) {
Evan Rosky7735d352019-03-18 17:27:27 -07002743 mTmpRect.setEmpty();
2744 final Task task = getTask();
2745 if (getDisplayContent().mAppTransitionController.isTransitWithinTask(
2746 getTransit(), task)) {
2747 task.getBounds(mTmpRect);
2748 } else {
2749 final TaskStack stack = getStack();
2750 if (stack == null) {
2751 return;
2752 }
2753 // Set clip rect to stack bounds.
2754 stack.getBounds(mTmpRect);
Vishnu Naira2977262018-07-26 13:31:26 -07002755 }
2756 mAnimationBoundsLayer = createAnimationBoundsLayer(t);
2757
Vishnu Naira2977262018-07-26 13:31:26 -07002758 // Crop to stack bounds.
2759 t.setWindowCrop(mAnimationBoundsLayer, mTmpRect);
Jorim Jaggi9cd99132019-04-24 17:41:35 +02002760 t.setLayer(mAnimationBoundsLayer, layer);
Vishnu Naira2977262018-07-26 13:31:26 -07002761
2762 // Reparent leash to animation bounds layer.
Robert Carr10584fa2019-01-14 15:55:19 -08002763 t.reparent(leash, mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002764 }
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002765 }
2766
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002767 /**
2768 * This must be called while inside a transaction.
2769 */
2770 void showAllWindowsLocked() {
2771 forAllWindows(windowState -> {
2772 if (DEBUG_VISIBILITY) Slog.v(TAG, "performing show on: " + windowState);
2773 windowState.performShowLocked();
2774 }, false /* traverseTopToBottom */);
Jorim Jaggia5e10572017-11-15 14:36:26 +01002775 }
2776
2777 @Override
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002778 protected void onAnimationFinished() {
2779 super.onAnimationFinished();
2780
Ian8b2822e2019-05-14 11:59:02 -07002781 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#onAnimationFinished");
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002782 mTransit = TRANSIT_UNSET;
2783 mTransitFlags = 0;
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002784 mNeedsZBoost = false;
Vishnu Naira2977262018-07-26 13:31:26 -07002785 mNeedsAnimationBoundsLayer = false;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002786
2787 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER,
2788 "AppWindowToken");
2789
Jorim Jaggi988f6682017-11-17 17:46:43 +01002790 clearThumbnail();
Jorim Jaggi752cd822018-03-29 16:29:18 +02002791 setClientHidden(isHidden() && hiddenRequested);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002792
lumarkff0ab692018-11-05 20:32:30 +08002793 getDisplayContent().computeImeTargetIfNeeded(this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002794
2795 if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + this
2796 + ": reportedVisible=" + reportedVisible
2797 + " okToDisplay=" + okToDisplay()
2798 + " okToAnimate=" + okToAnimate()
2799 + " startingDisplayed=" + startingDisplayed);
2800
Evan Rosky2289ba12018-11-19 18:28:18 -08002801 // clean up thumbnail window
2802 if (mThumbnail != null) {
2803 mThumbnail.destroy();
2804 mThumbnail = null;
2805 }
2806
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002807 // WindowState.onExitAnimationDone might modify the children list, so make a copy and then
2808 // traverse the copy.
2809 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
2810 children.forEach(WindowState::onExitAnimationDone);
2811
lumark588a3e82018-07-20 18:53:54 +08002812 getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002813 scheduleAnimation();
Jorim Jaggi9b5e3312019-03-01 18:08:00 +01002814
2815 mActivityRecord.onAnimationFinished();
Ian8b2822e2019-05-14 11:59:02 -07002816 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002817 }
2818
2819 @Override
2820 boolean isAppAnimating() {
2821 return isSelfAnimating();
2822 }
2823
2824 @Override
2825 boolean isSelfAnimating() {
2826 // If we are about to start a transition, we also need to be considered animating.
2827 return isWaitingForTransitionStart() || isReallyAnimating();
2828 }
2829
2830 /**
2831 * @return True if and only if we are actually running an animation. Note that
2832 * {@link #isSelfAnimating} also returns true if we are waiting for an animation to
2833 * start.
2834 */
2835 private boolean isReallyAnimating() {
2836 return super.isSelfAnimating();
2837 }
2838
Evan Rosky25b56192019-02-06 16:10:56 -08002839 /**
2840 * @param cancel {@code true} if clearing the leash due to cancelling instead of transferring
2841 * to another leash.
2842 */
2843 private void clearChangeLeash(Transaction t, boolean cancel) {
2844 if (mTransitChangeLeash == null) {
2845 return;
2846 }
2847 if (cancel) {
2848 clearThumbnail();
2849 SurfaceControl sc = getSurfaceControl();
2850 SurfaceControl parentSc = getParentSurfaceControl();
2851 // Don't reparent if surface is getting destroyed
2852 if (parentSc != null && sc != null) {
2853 t.reparent(sc, getParentSurfaceControl());
2854 }
2855 }
2856 t.hide(mTransitChangeLeash);
Evan Rosky08e20932019-05-14 10:54:07 -07002857 t.remove(mTransitChangeLeash);
Evan Rosky25b56192019-02-06 16:10:56 -08002858 mTransitChangeLeash = null;
2859 if (cancel) {
lumarkf6f34942019-04-29 16:56:50 +08002860 onAnimationLeashLost(t);
Evan Rosky25b56192019-02-06 16:10:56 -08002861 }
2862 }
2863
Jorim Jaggi988f6682017-11-17 17:46:43 +01002864 @Override
2865 void cancelAnimation() {
Evan Rosky2289ba12018-11-19 18:28:18 -08002866 cancelAnimationOnly();
Jorim Jaggi988f6682017-11-17 17:46:43 +01002867 clearThumbnail();
Evan Rosky25b56192019-02-06 16:10:56 -08002868 clearChangeLeash(getPendingTransaction(), true /* cancel */);
Evan Rosky2289ba12018-11-19 18:28:18 -08002869 }
2870
2871 /**
2872 * This only cancels the animation. It doesn't do other teardown like cleaning-up thumbnail
2873 * or interim leashes.
2874 * <p>
2875 * Used when canceling in preparation for starting a new animation.
2876 */
2877 void cancelAnimationOnly() {
2878 super.cancelAnimation();
Jorim Jaggi988f6682017-11-17 17:46:43 +01002879 }
2880
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002881 boolean isWaitingForTransitionStart() {
lumark588a3e82018-07-20 18:53:54 +08002882 return getDisplayContent().mAppTransition.isTransitionSet()
2883 && (getDisplayContent().mOpeningApps.contains(this)
Evan Rosky2289ba12018-11-19 18:28:18 -08002884 || getDisplayContent().mClosingApps.contains(this)
2885 || getDisplayContent().mChangingApps.contains(this));
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002886 }
2887
2888 public int getTransit() {
2889 return mTransit;
2890 }
2891
2892 int getTransitFlags() {
2893 return mTransitFlags;
2894 }
2895
Jorim Jaggi988f6682017-11-17 17:46:43 +01002896 void attachThumbnailAnimation() {
2897 if (!isReallyAnimating()) {
2898 return;
2899 }
2900 final int taskId = getTask().mTaskId;
2901 final GraphicBuffer thumbnailHeader =
lumark588a3e82018-07-20 18:53:54 +08002902 getDisplayContent().mAppTransition.getAppTransitionThumbnailHeader(taskId);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002903 if (thumbnailHeader == null) {
2904 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG, "No thumbnail header bitmap for: " + taskId);
2905 return;
2906 }
2907 clearThumbnail();
2908 mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnailHeader);
2909 mThumbnail.startAnimation(getPendingTransaction(), loadThumbnailAnimation(thumbnailHeader));
2910 }
2911
Tony Mak64b8d562017-12-28 17:44:02 +00002912 /**
2913 * Attaches a surface with a thumbnail for the
2914 * {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation.
2915 */
2916 void attachCrossProfileAppsThumbnailAnimation() {
2917 if (!isReallyAnimating()) {
2918 return;
2919 }
2920 clearThumbnail();
2921
2922 final WindowState win = findMainWindow();
2923 if (win == null) {
2924 return;
2925 }
chaviw492139a2018-07-16 16:07:35 -07002926 final Rect frame = win.getFrameLw();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002927 final int thumbnailDrawableRes = getTask().mUserId == mWmService.mCurrentUserId
Tony Mak64b8d562017-12-28 17:44:02 +00002928 ? R.drawable.ic_account_circle
Tony Makda4af232018-04-27 11:01:10 +01002929 : R.drawable.ic_corp_badge;
Tony Mak64b8d562017-12-28 17:44:02 +00002930 final GraphicBuffer thumbnail =
lumark588a3e82018-07-20 18:53:54 +08002931 getDisplayContent().mAppTransition
Tony Mak64b8d562017-12-28 17:44:02 +00002932 .createCrossProfileAppsThumbnail(thumbnailDrawableRes, frame);
2933 if (thumbnail == null) {
2934 return;
2935 }
2936 mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnail);
2937 final Animation animation =
lumark588a3e82018-07-20 18:53:54 +08002938 getDisplayContent().mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(
chaviw492139a2018-07-16 16:07:35 -07002939 win.getFrameLw());
Tony Mak64b8d562017-12-28 17:44:02 +00002940 mThumbnail.startAnimation(getPendingTransaction(), animation, new Point(frame.left,
2941 frame.top));
2942 }
2943
Jorim Jaggi988f6682017-11-17 17:46:43 +01002944 private Animation loadThumbnailAnimation(GraphicBuffer thumbnailHeader) {
2945 final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
2946
2947 // If this is a multi-window scenario, we use the windows frame as
2948 // destination of the thumbnail header animation. If this is a full screen
2949 // window scenario, we use the whole display as the target.
2950 WindowState win = findMainWindow();
2951 Rect appRect = win != null ? win.getContentFrameLw() :
2952 new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
chaviw9c81e632018-07-31 11:17:52 -07002953 final Rect insets = win != null ? win.getContentInsets() : null;
Jorim Jaggi988f6682017-11-17 17:46:43 +01002954 final Configuration displayConfig = mDisplayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08002955 return getDisplayContent().mAppTransition.createThumbnailAspectScaleAnimationLocked(
Jorim Jaggi988f6682017-11-17 17:46:43 +01002956 appRect, insets, thumbnailHeader, getTask().mTaskId, displayConfig.uiMode,
2957 displayConfig.orientation);
2958 }
2959
2960 private void clearThumbnail() {
2961 if (mThumbnail == null) {
2962 return;
2963 }
2964 mThumbnail.destroy();
2965 mThumbnail = null;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002966 }
2967
Jorim Jaggif84e2f62018-01-16 14:17:59 +01002968 void registerRemoteAnimations(RemoteAnimationDefinition definition) {
2969 mRemoteAnimationDefinition = definition;
2970 }
2971
2972 RemoteAnimationDefinition getRemoteAnimationDefinition() {
2973 return mRemoteAnimationDefinition;
2974 }
2975
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002976 @Override
2977 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
2978 super.dump(pw, prefix, dumpAll);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002979 if (appToken != null) {
Wale Ogunwale72919d22016-12-08 18:58:50 -08002980 pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002981 }
Winson Chung48b25652018-10-22 14:04:30 -07002982 pw.println(prefix + "component=" + mActivityComponent.flattenToShortString());
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08002983 pw.print(prefix); pw.print("task="); pw.println(getTask());
Wale Ogunwale51362492016-09-08 17:49:17 -07002984 pw.print(prefix); pw.print(" mFillsParent="); pw.print(mFillsParent);
2985 pw.print(" mOrientation="); pw.println(mOrientation);
Wale Ogunwale89973222017-04-23 18:39:45 -07002986 pw.println(prefix + "hiddenRequested=" + hiddenRequested + " mClientHidden=" + mClientHidden
2987 + ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "")
2988 + " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible);
Craig Mautner59431632012-04-04 11:56:44 -07002989 if (paused) {
2990 pw.print(prefix); pw.print("paused="); pw.println(paused);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002991 }
Wale Ogunwale9017ec02016-02-25 08:55:25 -08002992 if (mAppStopped) {
2993 pw.print(prefix); pw.print("mAppStopped="); pw.println(mAppStopped);
2994 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002995 if (mNumInterestingWindows != 0 || mNumDrawnWindows != 0
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002996 || allDrawn || mLastAllDrawn) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002997 pw.print(prefix); pw.print("mNumInterestingWindows=");
2998 pw.print(mNumInterestingWindows);
2999 pw.print(" mNumDrawnWindows="); pw.print(mNumDrawnWindows);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003000 pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
Craig Mautner6fbda632012-07-03 09:26:39 -07003001 pw.print(" allDrawn="); pw.print(allDrawn);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00003002 pw.print(" lastAllDrawn="); pw.print(mLastAllDrawn);
Craig Mautner6fbda632012-07-03 09:26:39 -07003003 pw.println(")");
3004 }
3005 if (inPendingTransaction) {
3006 pw.print(prefix); pw.print("inPendingTransaction=");
3007 pw.println(inPendingTransaction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003008 }
chaviwa8f07a72019-05-01 16:25:39 -07003009 if (mStartingData != null || removed || firstWindowDrawn || mIsExiting) {
3010 pw.print(prefix); pw.print("startingData="); pw.print(mStartingData);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003011 pw.print(" removed="); pw.print(removed);
Craig Mautner3d7ca312015-01-08 10:56:00 -08003012 pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
Craig Mautner799bc1d2015-01-14 10:33:48 -08003013 pw.print(" mIsExiting="); pw.println(mIsExiting);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003014 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08003015 if (startingWindow != null || startingSurface != null
Wale Ogunwale6c459212017-05-17 08:56:03 -07003016 || startingDisplayed || startingMoved || mHiddenSetFromTransferredStartingWindow) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003017 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08003018 pw.print(" startingSurface="); pw.print(startingSurface);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003019 pw.print(" startingDisplayed="); pw.print(startingDisplayed);
Wale Ogunwale6c459212017-05-17 08:56:03 -07003020 pw.print(" startingMoved="); pw.print(startingMoved);
3021 pw.println(" mHiddenSetFromTransferredStartingWindow="
3022 + mHiddenSetFromTransferredStartingWindow);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003023 }
Jorim Jaggi0429f352015-12-22 16:29:16 +01003024 if (!mFrozenBounds.isEmpty()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08003025 pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
Jorim Jaggi26c8c422016-05-09 19:57:25 -07003026 pw.print(prefix); pw.print("mFrozenMergedConfig="); pw.println(mFrozenMergedConfig);
Chong Zhangd78ddb42016-03-02 17:01:14 -08003027 }
3028 if (mPendingRelaunchCount != 0) {
3029 pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount);
Jorim Jaggi0429f352015-12-22 16:29:16 +01003030 }
Riddle Hsub398da32019-01-21 21:48:16 +08003031 if (mSizeCompatScale != 1f || mSizeCompatBounds != null) {
3032 pw.println(prefix + "mSizeCompatScale=" + mSizeCompatScale + " mSizeCompatBounds="
3033 + mSizeCompatBounds);
3034 }
Wale Ogunwalee287e192017-04-21 09:30:12 -07003035 if (mRemovingFromDisplay) {
3036 pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay);
3037 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003038 }
3039
3040 @Override
3041 void setHidden(boolean hidden) {
3042 super.setHidden(hidden);
Winson Chunge55c0192017-08-24 14:50:48 -07003043
3044 if (hidden) {
3045 // Once the app window is hidden, reset the last saved PiP snap fraction
3046 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(this);
3047 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003048 scheduleAnimation();
3049 }
3050
3051 @Override
3052 void prepareSurfaces() {
3053 // isSelfAnimating also returns true when we are about to start a transition, so we need
3054 // to check super here.
3055 final boolean reallyAnimating = super.isSelfAnimating();
3056 final boolean show = !isHidden() || reallyAnimating;
Robert Carrd8e4fb72019-01-31 11:14:30 -08003057
3058 if (mSurfaceControl != null) {
3059 if (show && !mLastSurfaceShowing) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003060 getPendingTransaction().show(mSurfaceControl);
Robert Carrd8e4fb72019-01-31 11:14:30 -08003061 } else if (!show && mLastSurfaceShowing) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003062 getPendingTransaction().hide(mSurfaceControl);
Robert Carrd8e4fb72019-01-31 11:14:30 -08003063 }
Jorim Jaggi4d1835d2017-08-31 17:28:27 +02003064 }
Jorim Jaggi988f6682017-11-17 17:46:43 +01003065 if (mThumbnail != null) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003066 mThumbnail.setShowing(getPendingTransaction(), show);
Jorim Jaggi988f6682017-11-17 17:46:43 +01003067 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003068 mLastSurfaceShowing = show;
3069 super.prepareSurfaces();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003070 }
3071
Jorim Jaggi77d0f36c2018-03-16 17:49:49 +01003072 /**
3073 * @return Whether our {@link #getSurfaceControl} is currently showing.
3074 */
3075 boolean isSurfaceShowing() {
3076 return mLastSurfaceShowing;
3077 }
3078
Jorim Jaggib0fc8172017-11-23 17:04:08 +00003079 boolean isFreezingScreen() {
3080 return mFreezingScreen;
3081 }
3082
3083 @Override
3084 boolean needsZBoost() {
3085 return mNeedsZBoost || super.needsZBoost();
3086 }
3087
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07003088 @CallSuper
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003089 @Override
Nataniel Borges023ecb52019-01-16 14:15:43 -08003090 public void writeToProto(ProtoOutputStream proto, long fieldId,
3091 @WindowTraceLogLevel int logLevel) {
3092 // Critical log level logs only visible elements to mitigate performance overheard
3093 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
3094 return;
3095 }
3096
Steven Timotiusaf03df62017-07-18 16:56:43 -07003097 final long token = proto.start(fieldId);
3098 writeNameToProto(proto, NAME);
Nataniel Borges023ecb52019-01-16 14:15:43 -08003099 super.writeToProto(proto, WINDOW_TOKEN, logLevel);
Vishnu Nair04ab4392018-01-10 11:00:06 -08003100 proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing);
3101 proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart());
3102 proto.write(IS_REALLY_ANIMATING, isReallyAnimating());
3103 if (mThumbnail != null){
3104 mThumbnail.writeToProto(proto, THUMBNAIL);
3105 }
3106 proto.write(FILLS_PARENT, mFillsParent);
3107 proto.write(APP_STOPPED, mAppStopped);
3108 proto.write(HIDDEN_REQUESTED, hiddenRequested);
3109 proto.write(CLIENT_HIDDEN, mClientHidden);
3110 proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient);
3111 proto.write(REPORTED_DRAWN, reportedDrawn);
3112 proto.write(REPORTED_VISIBLE, reportedVisible);
3113 proto.write(NUM_INTERESTING_WINDOWS, mNumInterestingWindows);
3114 proto.write(NUM_DRAWN_WINDOWS, mNumDrawnWindows);
3115 proto.write(ALL_DRAWN, allDrawn);
3116 proto.write(LAST_ALL_DRAWN, mLastAllDrawn);
3117 proto.write(REMOVED, removed);
Nataniel Borges023ecb52019-01-16 14:15:43 -08003118 if (startingWindow != null) {
Vishnu Nair04ab4392018-01-10 11:00:06 -08003119 startingWindow.writeIdentifierToProto(proto, STARTING_WINDOW);
3120 }
3121 proto.write(STARTING_DISPLAYED, startingDisplayed);
3122 proto.write(STARTING_MOVED, startingMoved);
3123 proto.write(HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW,
3124 mHiddenSetFromTransferredStartingWindow);
3125 for (Rect bounds : mFrozenBounds) {
3126 bounds.writeToProto(proto, FROZEN_BOUNDS);
3127 }
Steven Timotiusaf03df62017-07-18 16:56:43 -07003128 proto.end(token);
3129 }
3130
3131 void writeNameToProto(ProtoOutputStream proto, long fieldId) {
3132 if (appToken == null) {
3133 return;
3134 }
3135 try {
3136 proto.write(fieldId, appToken.getName());
3137 } catch (RemoteException e) {
3138 // This shouldn't happen, but in this case fall back to outputting nothing
3139 Slog.e(TAG, e.toString());
3140 }
3141 }
3142
3143 @Override
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003144 public String toString() {
3145 if (stringName == null) {
3146 StringBuilder sb = new StringBuilder();
3147 sb.append("AppWindowToken{");
3148 sb.append(Integer.toHexString(System.identityHashCode(this)));
3149 sb.append(" token="); sb.append(token); sb.append('}');
3150 stringName = sb.toString();
3151 }
Wale Ogunwaleba51ca22016-09-23 06:06:54 -07003152 return stringName + ((mIsExiting) ? " mIsExiting=" : "");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003153 }
Adrian Roos20e07892018-02-23 19:12:01 +01003154
3155 Rect getLetterboxInsets() {
3156 if (mLetterbox != null) {
3157 return mLetterbox.getInsets();
3158 } else {
3159 return new Rect();
3160 }
3161 }
Adrian Roos23df3a32018-03-15 15:41:13 +01003162
Riddle Hsu69de5fb2019-02-23 01:19:50 +08003163 /** Gets the inner bounds of letterbox. The bounds will be empty if there is no letterbox. */
3164 void getLetterboxInnerBounds(Rect outBounds) {
3165 if (mLetterbox != null) {
3166 outBounds.set(mLetterbox.getInnerFrame());
3167 } else {
3168 outBounds.setEmpty();
3169 }
3170 }
3171
Adrian Roos23df3a32018-03-15 15:41:13 +01003172 /**
Riddle Hsu69de5fb2019-02-23 01:19:50 +08003173 * @return {@code true} if there is a letterbox and any part of that letterbox overlaps with
Adrian Roos23df3a32018-03-15 15:41:13 +01003174 * the given {@code rect}.
3175 */
3176 boolean isLetterboxOverlappingWith(Rect rect) {
3177 return mLetterbox != null && mLetterbox.isOverlappingWith(rect);
3178 }
chaviw4ad54912018-05-30 11:05:44 -07003179
3180 /**
3181 * Sets if this AWT is in the process of closing or entering PIP.
3182 * {@link #mWillCloseOrEnterPip}}
3183 */
3184 void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
3185 mWillCloseOrEnterPip = willCloseOrEnterPip;
3186 }
3187
3188 /**
3189 * Returns whether this AWT is considered closing. Conditions are either
3190 * 1. Is this app animating and was requested to be hidden
3191 * 2. App is delayed closing since it might enter PIP.
3192 */
3193 boolean isClosingOrEnteringPip() {
3194 return (isAnimating() && hiddenRequested) || mWillCloseOrEnterPip;
3195 }
Jorim Jaggiaf0d6d22018-06-08 15:25:35 +02003196
3197 /**
3198 * @return Whether we are allowed to show non-starting windows at the moment. We disallow
3199 * showing windows during transitions in case we have windows that have wide-color-gamut
3200 * color mode set to avoid jank in the middle of the transition.
3201 */
3202 boolean canShowWindows() {
3203 return allDrawn && !(isReallyAnimating() && hasNonDefaultColorWindow());
3204 }
3205
3206 /**
3207 * @return true if we have a window that has a non-default color mode set; false otherwise.
3208 */
3209 private boolean hasNonDefaultColorWindow() {
3210 return forAllWindows(ws -> ws.mAttrs.getColorMode() != COLOR_MODE_DEFAULT,
3211 true /* topToBottom */);
3212 }
lumark588a3e82018-07-20 18:53:54 +08003213
3214 void removeFromPendingTransition() {
3215 if (isWaitingForTransitionStart() && mDisplayContent != null) {
3216 mDisplayContent.mOpeningApps.remove(this);
Evan Rosky25b56192019-02-06 16:10:56 -08003217 if (mDisplayContent.mChangingApps.remove(this)) {
3218 clearChangeLeash(getPendingTransaction(), true /* cancel */);
3219 }
lumark588a3e82018-07-20 18:53:54 +08003220 mDisplayContent.mClosingApps.remove(this);
3221 }
3222 }
chaviwdcf76ec2019-01-11 16:48:46 -08003223
3224 private void updateColorTransform() {
3225 if (mSurfaceControl != null && mLastAppSaturationInfo != null) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003226 getPendingTransaction().setColorTransform(mSurfaceControl,
3227 mLastAppSaturationInfo.mMatrix, mLastAppSaturationInfo.mTranslation);
chaviwdcf76ec2019-01-11 16:48:46 -08003228 mWmService.scheduleAnimationLocked();
3229 }
3230 }
3231
3232 private static class AppSaturationInfo {
3233 float[] mMatrix = new float[9];
3234 float[] mTranslation = new float[3];
3235
3236 void setSaturation(@Size(9) float[] matrix, @Size(3) float[] translation) {
3237 System.arraycopy(matrix, 0, mMatrix, 0, mMatrix.length);
3238 System.arraycopy(translation, 0, mTranslation, 0, mTranslation.length);
3239 }
3240 }
Jeff Browne9bdb312012-04-05 15:30:10 -07003241}