blob: 56cfe5833cb555e8dafda939cdddf7142da48e96 [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 Ogunwale72919d22016-12-08 18:58:50 -080024import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
25import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -070026import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
Wale Ogunwale51362492016-09-08 17:49:17 -070027import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
Jorim Jaggif5f9e122017-10-24 18:21:09 +020028import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
Jorim Jaggife762342016-10-13 14:33:27 +020029import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
Jorim Jaggid635a4a2017-05-03 15:21:26 +020030import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080031import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
Jorim Jaggife762342016-10-13 14:33:27 +020032import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
Wale Ogunwaled1c37912016-08-16 03:19:39 -070033import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080034import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -070035import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080036import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
Evan Rosky2289ba12018-11-19 18:28:18 -080037import static android.view.WindowManager.TRANSIT_TASK_CHANGE_WINDOWING_MODE;
chaviw9c81e632018-07-31 11:17:52 -070038import static android.view.WindowManager.TRANSIT_UNSET;
Jorim Jaggic6976f02018-04-18 16:31:07 +020039import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
chaviw9c81e632018-07-31 11:17:52 -070040
Adrian Roose99bc052017-11-20 17:55:31 +010041import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
42import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070043import static com.android.server.wm.AppWindowTokenProto.ALL_DRAWN;
44import static com.android.server.wm.AppWindowTokenProto.APP_STOPPED;
45import static com.android.server.wm.AppWindowTokenProto.CLIENT_HIDDEN;
46import static com.android.server.wm.AppWindowTokenProto.DEFER_HIDING_CLIENT;
47import static com.android.server.wm.AppWindowTokenProto.FILLS_PARENT;
48import static com.android.server.wm.AppWindowTokenProto.FROZEN_BOUNDS;
49import static com.android.server.wm.AppWindowTokenProto.HIDDEN_REQUESTED;
50import static com.android.server.wm.AppWindowTokenProto.HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW;
51import static com.android.server.wm.AppWindowTokenProto.IS_REALLY_ANIMATING;
52import static com.android.server.wm.AppWindowTokenProto.IS_WAITING_FOR_TRANSITION_START;
53import static com.android.server.wm.AppWindowTokenProto.LAST_ALL_DRAWN;
54import static com.android.server.wm.AppWindowTokenProto.LAST_SURFACE_SHOWING;
55import static com.android.server.wm.AppWindowTokenProto.NAME;
56import static com.android.server.wm.AppWindowTokenProto.NUM_DRAWN_WINDOWS;
57import static com.android.server.wm.AppWindowTokenProto.NUM_INTERESTING_WINDOWS;
58import static com.android.server.wm.AppWindowTokenProto.REMOVED;
59import static com.android.server.wm.AppWindowTokenProto.REPORTED_DRAWN;
60import static com.android.server.wm.AppWindowTokenProto.REPORTED_VISIBLE;
61import static com.android.server.wm.AppWindowTokenProto.STARTING_DISPLAYED;
62import static com.android.server.wm.AppWindowTokenProto.STARTING_MOVED;
63import static com.android.server.wm.AppWindowTokenProto.STARTING_WINDOW;
64import static com.android.server.wm.AppWindowTokenProto.THUMBNAIL;
65import static com.android.server.wm.AppWindowTokenProto.WINDOW_TOKEN;
chaviw9c81e632018-07-31 11:17:52 -070066import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
67import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
68import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
69import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
70import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
71import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
72import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
73import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
74import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
75import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
76import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
77import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
78import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
79import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN;
80import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
81import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
82import static com.android.server.wm.WindowManagerService.logWithStack;
Vishnu Naira2977262018-07-26 13:31:26 -070083import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_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.
207 StartingData startingData;
208 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();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800389 removeStartingWindow();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800390 }
391 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);
512 waitingToShow = false;
513 hiddenRequested = !visible;
514 mDeferHidingClient = deferHidingClient;
515
516 if (!visible) {
517 // If the app is dead while it was visible, we kept its dead window on screen.
518 // Now that the app is going invisible, we can remove it. It will be restarted
519 // if made visible again.
520 removeDeadWindows();
521 } else {
522 if (!appTransition.isTransitionSet()
523 && appTransition.isReady()) {
524 // Add the app mOpeningApps if transition is unset but ready. This means
525 // we're doing a screen freeze, and the unfreeze will wait for all opening
526 // apps to be ready.
527 displayContent.mOpeningApps.add(this);
528 }
529 startingMoved = false;
530 // If the token is currently hidden (should be the common case), or has been
531 // stopped, then we need to set up to wait for its windows to be ready.
532 if (isHidden() || mAppStopped) {
533 clearAllDrawn();
534
535 // If the app was already visible, don't reset the waitingToShow state.
536 if (isHidden()) {
537 waitingToShow = true;
538 }
539 }
540
541 // In the case where we are making an app visible but holding off for a transition,
542 // we still need to tell the client to make its windows visible so they get drawn.
543 // Otherwise, we will wait on performing the transition until all windows have been
544 // drawn, they never will be, and we are sad.
545 setClientHidden(false);
546
547 requestUpdateWallpaperIfNeeded();
548
549 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "No longer Stopped: " + this);
550 mAppStopped = false;
551
552 transferStartingWindowFromHiddenAboveTokenIfNeeded();
553 }
554
555 // If we are preparing an app transition, then delay changing
556 // the visibility of this token until we execute that transition.
557 if (okToAnimate() && appTransition.isTransitionSet()) {
558 inPendingTransaction = true;
559 if (visible) {
560 displayContent.mOpeningApps.add(this);
561 mEnteringAnimation = true;
562 } else {
563 displayContent.mClosingApps.add(this);
564 mEnteringAnimation = false;
565 }
566 if (appTransition.getAppTransition()
567 == WindowManager.TRANSIT_TASK_OPEN_BEHIND) {
568 // We're launchingBehind, add the launching activity to mOpeningApps.
569 final WindowState win = getDisplayContent().findFocusedWindow();
570 if (win != null) {
571 final AppWindowToken focusedToken = win.mAppToken;
572 if (focusedToken != null) {
573 if (DEBUG_APP_TRANSITIONS) {
574 Slog.d(TAG_WM, "TRANSIT_TASK_OPEN_BEHIND, "
575 + " adding " + focusedToken + " to mOpeningApps");
576 }
577 // Force animation to be loaded.
578 focusedToken.setHidden(true);
579 displayContent.mOpeningApps.add(focusedToken);
580 }
581 }
582 }
Garfield Tanb6776602019-02-20 14:44:26 -0800583 // Changes in opening apps and closing apps may cause orientation change.
584 reportDescendantOrientationChangeIfNeeded();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800585 return;
586 }
587
588 commitVisibility(null, visible, TRANSIT_UNSET, true, mVoiceInteraction);
589 updateReportedVisibilityLocked();
590 }
591
592 boolean commitVisibility(WindowManager.LayoutParams lp,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700593 boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
594
595 boolean delayed = false;
596 inPendingTransaction = false;
Wale Ogunwale9e4721f2017-05-23 19:37:30 -0700597 // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually
598 // been set by the app now.
599 mHiddenSetFromTransferredStartingWindow = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700600
601 // Allow for state changes and animation to be applied if:
602 // * token is transitioning visibility state
603 // * or the token was marked as hidden and is exiting before we had a chance to play the
604 // transition animation
605 // * or this is an opening app and windows are being replaced.
606 boolean visibilityChanged = false;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200607 if (isHidden() == visible || (isHidden() && mIsExiting) || (visible && waitingForReplacement())) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800608 final AccessibilityController accessibilityController =
609 mWmService.mAccessibilityController;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700610 boolean changed = false;
611 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM,
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200612 "Changing app " + this + " hidden=" + isHidden() + " performLayout=" + performLayout);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700613
614 boolean runningAppAnimation = false;
615
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100616 if (transit != WindowManager.TRANSIT_UNSET) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200617 if (applyAnimationLocked(lp, transit, visible, isVoiceInteraction)) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700618 delayed = runningAppAnimation = true;
619 }
620 final WindowState window = findMainWindow();
Rhed Jao02655dc2018-10-30 20:44:52 +0800621 if (window != null && accessibilityController != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700622 accessibilityController.onAppWindowTransitionLocked(window, transit);
623 }
624 changed = true;
625 }
626
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700627 final int windowsCount = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700628 for (int i = 0; i < windowsCount; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700629 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700630 changed |= win.onAppVisibilityChanged(visible, runningAppAnimation);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700631 }
632
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200633 setHidden(!visible);
634 hiddenRequested = !visible;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700635 visibilityChanged = true;
636 if (!visible) {
637 stopFreezingScreen(true, true);
638 } else {
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700639 // If we are being set visible, and the starting window is not yet displayed,
640 // then make sure it doesn't get displayed.
641 if (startingWindow != null && !startingWindow.isDrawnLw()) {
642 startingWindow.mPolicyVisibility = false;
643 startingWindow.mPolicyVisibilityAfterAnim = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700644 }
Jorim Jaggi38d44ec2017-06-14 16:04:59 -0700645
646 // We are becoming visible, so better freeze the screen with the windows that are
647 // getting visible so we also wait for them.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800648 forAllWindows(mWmService::makeWindowFreezingScreenIfNeededLocked, true);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700649 }
650
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800651 if (DEBUG_APP_TRANSITIONS) {
652 Slog.v(TAG_WM, "commitVisibility: " + this
653 + ": hidden=" + isHidden() + " hiddenRequested=" + hiddenRequested);
654 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700655
656 if (changed) {
Arthur Hung95b38a92018-07-20 18:56:12 +0800657 getDisplayContent().getInputMonitor().setUpdateInputWindowsNeededLw();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700658 if (performLayout) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800659 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700660 false /*updateInputWindows*/);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800661 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700662 }
Arthur Hung95b38a92018-07-20 18:56:12 +0800663 getDisplayContent().getInputMonitor().updateInputWindowsLw(false /*force*/);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700664 }
665 }
666
lumarkd14173e2019-03-27 19:14:33 +0800667 if (isReallyAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700668 delayed = true;
Jorim Jaggiab9fcb22018-03-15 23:46:12 +0100669 } else {
670
671 // We aren't animating anything, but exiting windows rely on the animation finished
672 // callback being called in case the AppWindowToken was pretending to be animating,
673 // which we might have done because we were in closing/opening apps list.
674 onAnimationFinished();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700675 }
676
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700677 for (int i = mChildren.size() - 1; i >= 0 && !delayed; i--) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100678 if ((mChildren.get(i)).isSelfOrChildAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700679 delayed = true;
680 }
681 }
682
683 if (visibilityChanged) {
684 if (visible && !delayed) {
685 // The token was made immediately visible, there will be no entrance animation.
686 // We need to inform the client the enter animation was finished.
687 mEnteringAnimation = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800688 mWmService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(
689 token);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700690 }
Robert Carr61b81112017-07-17 18:08:15 -0700691
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800692 // If we're becoming visible, immediately change client visibility as well. there seem
693 // to be some edge cases where we change our visibility but client visibility never gets
694 // updated.
Jorim Jaggi110839b2018-01-22 12:49:04 +0100695 // If we're becoming invisible, update the client visibility if we are not running an
696 // animation. Otherwise, we'll update client visibility in onAnimationFinished.
Jorim Jaggi3cad57f2018-02-20 18:32:01 +0100697 if (visible || !isReallyAnimating()) {
Jorim Jaggi110839b2018-01-22 12:49:04 +0100698 setClientHidden(!visible);
Jorim Jaggi4876b4a2018-01-11 15:43:49 +0100699 }
700
lumark588a3e82018-07-20 18:53:54 +0800701 if (!getDisplayContent().mClosingApps.contains(this)
702 && !getDisplayContent().mOpeningApps.contains(this)) {
chaviwa953fcf2018-03-01 12:00:39 -0800703 // The token is not closing nor opening, so even if there is an animation set, that
704 // doesn't mean that it goes through the normal app transition cycle so we have
705 // to inform the docked controller about visibility change.
706 // TODO(multi-display): notify docked divider on all displays where visibility was
707 // affected.
lumark588a3e82018-07-20 18:53:54 +0800708 getDisplayContent().getDockedDividerController().notifyAppVisibilityChanged();
chaviwa953fcf2018-03-01 12:00:39 -0800709
710 // Take the screenshot before possibly hiding the WSA, otherwise the screenshot
711 // will not be taken.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800712 mWmService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible);
chaviwa953fcf2018-03-01 12:00:39 -0800713 }
714
Robert Carre7cc44d2017-03-20 19:04:30 -0700715 // If we are hidden but there is no delay needed we immediately
716 // apply the Surface transaction so that the ActivityManager
Robert Carr61b81112017-07-17 18:08:15 -0700717 // can have some guarantee on the Surface state following
718 // setting the visibility. This captures cases like dismissing
719 // the docked or pinned stack where there is no app transition.
720 //
721 // In the case of a "Null" animation, there will be
722 // no animation but there will still be a transition set.
723 // We still need to delay hiding the surface such that it
724 // can be synchronized with showing the next surface in the transition.
lumark588a3e82018-07-20 18:53:54 +0800725 if (isHidden() && !delayed && !getDisplayContent().mAppTransition.isTransitionSet()) {
Robert Carr6914f082017-03-20 19:04:30 -0700726 SurfaceControl.openTransaction();
727 for (int i = mChildren.size() - 1; i >= 0; i--) {
728 mChildren.get(i).mWinAnimator.hide("immediately hidden");
729 }
730 SurfaceControl.closeTransaction();
731 }
Garfield Tanb6776602019-02-20 14:44:26 -0800732
733 // Visibility changes may cause orientation request change.
734 reportDescendantOrientationChangeIfNeeded();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700735 }
736
737 return delayed;
738 }
739
Garfield Tanb6776602019-02-20 14:44:26 -0800740 private void reportDescendantOrientationChangeIfNeeded() {
741 // Orientation request is exposed only when we're visible. Therefore visibility change
742 // will change requested orientation. Notify upward the hierarchy ladder to adjust
743 // configuration. This is important to cases where activities with incompatible
744 // orientations launch, or user goes back from an activity of bi-orientation to an
745 // activity with specified orientation.
746 if (mActivityRecord.getRequestedConfigurationOrientation() == getConfiguration().orientation
747 || getOrientationIgnoreVisibility() == SCREEN_ORIENTATION_UNSET) {
748 return;
749 }
750
751 final IBinder freezeToken =
752 mActivityRecord.mayFreezeScreenLocked(mActivityRecord.app)
753 ? mActivityRecord.appToken : null;
754 onDescendantOrientationChanged(freezeToken, mActivityRecord);
755 }
756
Jorim Jaggi87fdbcb2017-08-17 13:41:11 +0200757 /**
758 * @return The to top most child window for which {@link LayoutParams#isFullscreen()} returns
759 * true.
760 */
761 WindowState getTopFullscreenWindow() {
762 for (int i = mChildren.size() - 1; i >= 0; i--) {
763 final WindowState win = mChildren.get(i);
764 if (win != null && win.mAttrs.isFullscreen()) {
765 return win;
766 }
767 }
768 return null;
769 }
770
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800771 WindowState findMainWindow() {
Matthew Ng53e66b22018-01-12 17:13:13 -0800772 return findMainWindow(true);
773 }
774
775 /**
776 * Finds the main window that either has type base application or application starting if
777 * requested.
778 *
779 * @param includeStartingApp Allow to search application-starting windows to also be returned.
780 * @return The main window of type base application or application starting if requested.
781 */
782 WindowState findMainWindow(boolean includeStartingApp) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700783 WindowState candidate = null;
Matthew Ng53e66b22018-01-12 17:13:13 -0800784 for (int j = mChildren.size() - 1; j >= 0; --j) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700785 final WindowState win = mChildren.get(j);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700786 final int type = win.mAttrs.type;
787 // No need to loop through child window as base application and starting types can't be
788 // child windows.
Matthew Ng53e66b22018-01-12 17:13:13 -0800789 if (type == TYPE_BASE_APPLICATION
790 || (includeStartingApp && type == TYPE_APPLICATION_STARTING)) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700791 // In cases where there are multiple windows, we prefer the non-exiting window. This
Sungsoo Lim0d3d1f82015-12-02 14:47:59 +0900792 // happens for example when replacing windows during an activity relaunch. When
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700793 // constructing the animation, we want the new window, not the exiting one.
Wale Ogunwalec48a3542016-02-19 15:18:45 -0800794 if (win.mAnimatingExit) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700795 candidate = win;
796 } else {
797 return win;
798 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800799 }
800 }
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700801 return candidate;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800802 }
803
Wale Ogunwale6cae7652015-12-26 07:36:26 -0800804 boolean windowsAreFocusable() {
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800805 if (mTargetSdk < Build.VERSION_CODES.Q) {
806 final int pid = mActivityRecord != null
807 ? (mActivityRecord.app != null ? mActivityRecord.app.getPid() : 0) : 0;
808 final AppWindowToken topFocusedAppOfMyProcess =
809 mWmService.mRoot.mTopFocusedAppByProcess.get(pid);
810 if (topFocusedAppOfMyProcess != null && topFocusedAppOfMyProcess != this) {
811 // For the apps below Q, there can be only one app which has the focused window per
812 // process, because legacy apps may not be ready for a multi-focus system.
813 return false;
814 }
815 }
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700816 return getWindowConfiguration().canReceiveKeys() || mAlwaysFocusable;
Wale Ogunwaled045c822015-12-02 09:14:28 -0800817 }
818
Wale Ogunwale571771c2016-08-26 13:18:50 -0700819 @Override
Wale Ogunwale44f21802016-09-02 12:49:48 -0700820 boolean isVisible() {
Wale Ogunwalee471be62016-10-03 07:53:55 -0700821 // If the app token isn't hidden then it is considered visible and there is no need to check
822 // its children windows to see if they are visible.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200823 return !isHidden();
Wale Ogunwale44f21802016-09-02 12:49:48 -0700824 }
825
826 @Override
Wale Ogunwalee287e192017-04-21 09:30:12 -0700827 void removeImmediately() {
828 onRemovedFromDisplay();
Yunfan Chen3a77f282018-12-12 15:47:52 -0800829 if (mActivityRecord != null) {
830 mActivityRecord.unregisterConfigurationChangeListener(this);
831 }
Wale Ogunwalee287e192017-04-21 09:30:12 -0700832 super.removeImmediately();
833 }
834
835 @Override
Wale Ogunwale571771c2016-08-26 13:18:50 -0700836 void removeIfPossible() {
Craig Mautnere3119b72015-01-20 15:02:36 -0800837 mIsExiting = false;
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800838 removeAllWindowsIfPossible();
Bryce Lee6d410262017-02-28 15:30:17 -0800839 removeImmediately();
Craig Mautnere3119b72015-01-20 15:02:36 -0800840 }
841
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700842 @Override
843 boolean checkCompleteDeferredRemoval() {
844 if (mIsExiting) {
845 removeIfPossible();
846 }
847 return super.checkCompleteDeferredRemoval();
848 }
849
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700850 void onRemovedFromDisplay() {
Wale Ogunwalee287e192017-04-21 09:30:12 -0700851 if (mRemovingFromDisplay) {
852 return;
853 }
854 mRemovingFromDisplay = true;
855
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700856 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app token: " + this);
857
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800858 boolean delayed = commitVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700859
lumark588a3e82018-07-20 18:53:54 +0800860 getDisplayContent().mOpeningApps.remove(this);
Evan Rosky2289ba12018-11-19 18:28:18 -0800861 getDisplayContent().mChangingApps.remove(this);
lumark588a3e82018-07-20 18:53:54 +0800862 getDisplayContent().mUnknownAppVisibilityController.appRemovedOrHidden(this);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800863 mWmService.mTaskSnapshotController.onAppRemoved(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700864 waitingToShow = false;
lumark588a3e82018-07-20 18:53:54 +0800865 if (getDisplayContent().mClosingApps.contains(this)) {
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700866 delayed = true;
lumark588a3e82018-07-20 18:53:54 +0800867 } else if (getDisplayContent().mAppTransition.isTransitionSet()) {
868 getDisplayContent().mClosingApps.add(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700869 delayed = true;
870 }
871
872 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app " + this + " delayed=" + delayed
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200873 + " animation=" + getAnimation() + " animating=" + isSelfAnimating());
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700874
875 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: "
876 + this + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
877
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800878 if (startingData != null) {
879 removeStartingWindow();
Jorim Jaggi19be6052017-08-03 18:33:43 +0200880 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800881
Winson Chung87e5d552017-04-05 11:49:38 -0700882 // If this window was animating, then we need to ensure that the app transition notifies
lumark588a3e82018-07-20 18:53:54 +0800883 // that animations have completed in DisplayContent.handleAnimatingStoppedAndTransition(),
884 // so add to that list now
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200885 if (isSelfAnimating()) {
lumark588a3e82018-07-20 18:53:54 +0800886 getDisplayContent().mNoAnimationNotifyOnTransitionFinished.add(token);
Winson Chung87e5d552017-04-05 11:49:38 -0700887 }
888
Wale Ogunwalee287e192017-04-21 09:30:12 -0700889 final TaskStack stack = getStack();
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700890 if (delayed && !isEmpty()) {
891 // set the token aside because it has an active animation to be finished
892 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM,
893 "removeAppToken make exiting: " + this);
Wale Ogunwalee287e192017-04-21 09:30:12 -0700894 if (stack != null) {
895 stack.mExitingAppTokens.add(this);
896 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700897 mIsExiting = true;
898 } else {
899 // Make sure there is no animation running on this token, so any windows associated
900 // with it will be removed as soon as their animations are complete
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200901 cancelAnimation();
Wale Ogunwale3106ae012017-05-16 08:56:37 -0700902 if (stack != null) {
903 stack.mExitingAppTokens.remove(this);
904 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700905 removeIfPossible();
906 }
907
908 removed = true;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700909 stopFreezingScreen(true, true);
Bryce Lee6d410262017-02-28 15:30:17 -0800910
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800911 final DisplayContent dc = getDisplayContent();
912 if (dc.mFocusedApp == this) {
913 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + this
914 + " displayId=" + dc.getDisplayId());
915 dc.setFocusedApp(null);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800916 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700917 }
Riddle Hsu192fe762019-01-15 23:41:57 +0800918 if (mLetterbox != null) {
919 mLetterbox.destroy();
920 mLetterbox = null;
921 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700922
923 if (!delayed) {
924 updateReportedVisibilityLocked();
925 }
Wale Ogunwalee287e192017-04-21 09:30:12 -0700926
927 mRemovingFromDisplay = false;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700928 }
929
Chong Zhange05bcb12016-07-26 17:47:29 -0700930 void clearAnimatingFlags() {
Chong Zhangb0d26702016-08-12 16:03:29 -0700931 boolean wallpaperMightChange = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700932 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700933 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700934 wallpaperMightChange |= win.clearAnimatingFlags();
Chong Zhange05bcb12016-07-26 17:47:29 -0700935 }
Chong Zhangb0d26702016-08-12 16:03:29 -0700936 if (wallpaperMightChange) {
937 requestUpdateWallpaperIfNeeded();
938 }
Chong Zhange05bcb12016-07-26 17:47:29 -0700939 }
940
Robert Carre12aece2016-02-02 22:43:27 -0800941 void destroySurfaces() {
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700942 destroySurfaces(false /*cleanupOnResume*/);
943 }
944
945 /**
946 * Destroy surfaces which have been marked as eligible by the animator, taking care to ensure
947 * the client has finished with them.
948 *
949 * @param cleanupOnResume whether this is done when app is resumed without fully stopped. If
950 * set to true, destroy only surfaces of removed windows, and clear relevant flags of the
951 * others so that they are ready to be reused. If set to false (common case), destroy all
952 * surfaces that's eligible, if the app is already stopped.
953 */
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700954 private void destroySurfaces(boolean cleanupOnResume) {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700955 boolean destroyedSomething = false;
Jorim Jaggia5e10572017-11-15 14:36:26 +0100956
957 // Copying to a different list as multiple children can be removed.
Jorim Jaggi59f3e922018-01-05 15:40:32 +0100958 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
Jorim Jaggia5e10572017-11-15 14:36:26 +0100959 for (int i = children.size() - 1; i >= 0; i--) {
960 final WindowState win = children.get(i);
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700961 destroyedSomething |= win.destroySurface(cleanupOnResume, mAppStopped);
Robert Carre12aece2016-02-02 22:43:27 -0800962 }
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700963 if (destroyedSomething) {
964 final DisplayContent dc = getDisplayContent();
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700965 dc.assignWindowLayers(true /*setLayoutNeeded*/);
Adrian Roos23df3a32018-03-15 15:41:13 +0100966 updateLetterboxSurface(null);
Robert Carre12aece2016-02-02 22:43:27 -0800967 }
968 }
969
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800970 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700971 * Notify that the app is now resumed, and it was not stopped before, perform a clean
972 * up of the surfaces
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800973 */
Jorim Jaggibae01b12017-04-11 16:29:10 -0700974 void notifyAppResumed(boolean wasStopped) {
Chong Zhangad24f962016-08-25 12:12:33 -0700975 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppResumed: wasStopped=" + wasStopped
Jorim Jaggibae01b12017-04-11 16:29:10 -0700976 + " " + this);
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700977 mAppStopped = false;
chaviwd3bf08d2017-08-01 17:24:59 -0700978 // Allow the window to turn the screen on once the app is resumed again.
979 setCanTurnScreenOn(true);
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700980 if (!wasStopped) {
981 destroySurfaces(true /*cleanupOnResume*/);
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800982 }
Robert Carre12aece2016-02-02 22:43:27 -0800983 }
984
Chong Zhangbef461f2015-10-27 11:38:24 -0700985 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700986 * Notify that the app has stopped, and it is okay to destroy any surfaces which were
987 * keeping alive in case they were still being used.
988 */
989 void notifyAppStopped() {
990 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: " + this);
991 mAppStopped = true;
992 destroySurfaces();
993 // Remove any starting window that was added for this app if they are still around.
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800994 removeStartingWindow();
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700995 }
996
Chong Zhang92147042016-05-09 12:47:11 -0700997 void clearAllDrawn() {
998 allDrawn = false;
999 deferClearAllDrawn = false;
Chong Zhangbef461f2015-10-27 11:38:24 -07001000 }
1001
Bryce Lee6d410262017-02-28 15:30:17 -08001002 Task getTask() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001003 return (Task) getParent();
Bryce Lee6d410262017-02-28 15:30:17 -08001004 }
1005
Jorim Jaggi3878ca32017-02-02 17:13:05 -08001006 TaskStack getStack() {
1007 final Task task = getTask();
1008 if (task != null) {
1009 return task.mStack;
1010 } else {
1011 return null;
1012 }
1013 }
1014
Bryce Lee6d410262017-02-28 15:30:17 -08001015 @Override
Riddle Hsu3a4bb612019-01-31 00:02:22 +08001016 void onParentChanged() {
1017 super.onParentChanged();
Bryce Lee6d410262017-02-28 15:30:17 -08001018
Robert Carred3e83b2017-04-21 13:26:55 -07001019 final Task task = getTask();
1020
Bryce Lee6d410262017-02-28 15:30:17 -08001021 // When the associated task is {@code null}, the {@link AppWindowToken} can no longer
1022 // access visual elements like the {@link DisplayContent}. We must remove any associations
1023 // such as animations.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001024 if (!mReparenting) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001025 if (task == null) {
1026 // It is possible we have been marked as a closing app earlier. We must remove ourselves
1027 // from this list so we do not participate in any future animations.
lumark588a3e82018-07-20 18:53:54 +08001028 getDisplayContent().mClosingApps.remove(this);
Robert Carred3e83b2017-04-21 13:26:55 -07001029 } else if (mLastParent != null && mLastParent.mStack != null) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001030 task.mStack.mExitingAppTokens.remove(this);
1031 }
Bryce Lee6d410262017-02-28 15:30:17 -08001032 }
Jorim Jaggi6de61012018-03-19 14:53:23 +01001033 final TaskStack stack = getStack();
1034
1035 // If we reparent, make sure to remove ourselves from the old animation registry.
1036 if (mAnimatingAppWindowTokenRegistry != null) {
1037 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
1038 }
1039 mAnimatingAppWindowTokenRegistry = stack != null
1040 ? stack.getAnimatingAppWindowTokenRegistry()
1041 : null;
1042
Robert Carred3e83b2017-04-21 13:26:55 -07001043 mLastParent = task;
chaviwdcf76ec2019-01-11 16:48:46 -08001044
1045 updateColorTransform();
Bryce Lee6d410262017-02-28 15:30:17 -08001046 }
1047
Wale Ogunwalefa854eb2016-09-20 13:43:52 -07001048 void postWindowRemoveStartingWindowCleanup(WindowState win) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001049 // TODO: Something smells about the code below...Is there a better way?
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001050 if (startingWindow == win) {
1051 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Notify removed startingWindow " + win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001052 removeStartingWindow();
Wale Ogunwale6c459212017-05-17 08:56:03 -07001053 } else if (mChildren.size() == 0) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001054 // If this is the last window and we had requested a starting transition window,
1055 // well there is no point now.
Jorim Jaggi02886a82016-12-06 09:10:06 -08001056 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Nulling last startingData");
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001057 startingData = null;
Wale Ogunwale6c459212017-05-17 08:56:03 -07001058 if (mHiddenSetFromTransferredStartingWindow) {
1059 // We set the hidden state to false for the token from a transferred starting window.
1060 // We now reset it back to true since the starting window was the last window in the
1061 // token.
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001062 setHidden(true);
Wale Ogunwale6c459212017-05-17 08:56:03 -07001063 }
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01001064 } else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001065 // If this is the last window except for a starting transition window,
1066 // we need to get rid of the starting transition.
Jorim Jaggie4b0f282017-05-17 15:10:29 +02001067 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Last window, removing starting window "
1068 + win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001069 removeStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001070 }
1071 }
1072
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001073 void removeDeadWindows() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001074 for (int winNdx = mChildren.size() - 1; winNdx >= 0; --winNdx) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001075 WindowState win = mChildren.get(winNdx);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001076 if (win.mAppDied) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001077 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.w(TAG,
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001078 "removeDeadWindows: " + win);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001079 // Set mDestroying, we don't want any animation or delayed removal here.
1080 win.mDestroying = true;
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001081 // Also removes child windows.
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001082 win.removeIfPossible();
Chong Zhang112eb8c2015-11-02 11:17:00 -08001083 }
1084 }
1085 }
1086
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001087 boolean hasWindowsAlive() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001088 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001089 // No need to loop through child windows as the answer should be the same as that of the
1090 // parent window.
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001091 if (!(mChildren.get(i)).mAppDied) {
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001092 return true;
1093 }
1094 }
1095 return false;
1096 }
1097
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001098 void setWillReplaceWindows(boolean animate) {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001099 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
1100 "Marking app token " + this + " with replacing windows.");
Robert Carra1eb4392015-12-10 12:43:51 -08001101
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001102 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001103 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001104 w.setWillReplaceWindow(animate);
Robert Carra1eb4392015-12-10 12:43:51 -08001105 }
Robert Carra1eb4392015-12-10 12:43:51 -08001106 }
1107
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001108 void setWillReplaceChildWindows() {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001109 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Marking app token " + this
Robert Carr23fa16b2016-01-13 13:19:58 -08001110 + " with replacing child windows.");
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001111 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001112 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001113 w.setWillReplaceChildWindows();
Robert Carr23fa16b2016-01-13 13:19:58 -08001114 }
1115 }
1116
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001117 void clearWillReplaceWindows() {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001118 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
1119 "Resetting app token " + this + " of replacing window marks.");
Chong Zhangf596cd52016-01-05 13:42:44 -08001120
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001121 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001122 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001123 w.clearWillReplaceWindow();
Chong Zhangf596cd52016-01-05 13:42:44 -08001124 }
1125 }
1126
Chong Zhang4d7369a2016-04-25 16:09:14 -07001127 void requestUpdateWallpaperIfNeeded() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001128 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001129 final WindowState w = mChildren.get(i);
Chong Zhang4d7369a2016-04-25 16:09:14 -07001130 w.requestUpdateWallpaperIfNeeded();
1131 }
1132 }
1133
Chong Zhangd78ddb42016-03-02 17:01:14 -08001134 boolean isRelaunching() {
1135 return mPendingRelaunchCount > 0;
1136 }
1137
Robert Carr68375192017-06-13 12:41:53 -07001138 boolean shouldFreezeBounds() {
1139 final Task task = getTask();
1140
1141 // For freeform windows, we can't freeze the bounds at the moment because this would make
1142 // the resizing unresponsive.
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001143 if (task == null || task.inFreeformWindowingMode()) {
Robert Carr68375192017-06-13 12:41:53 -07001144 return false;
1145 }
1146
1147 // We freeze the bounds while drag resizing to deal with the time between
1148 // the divider/drag handle being released, and the handling it's new
1149 // configuration. If we are relaunched outside of the drag resizing state,
1150 // we need to be careful not to do this.
1151 return getTask().isDragResizing();
1152 }
1153
Chong Zhangd78ddb42016-03-02 17:01:14 -08001154 void startRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001155 if (shouldFreezeBounds()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08001156 freezeBounds();
1157 }
Robert Carrd5c7dd62017-03-08 10:39:30 -08001158
1159 // In the process of tearing down before relaunching, the app will
1160 // try and clean up it's child surfaces. We need to prevent this from
1161 // happening, so we sever the children, transfering their ownership
1162 // from the client it-self to the parent surface (owned by us).
Robert Carr29daa922018-04-27 11:56:48 -07001163 detachChildren();
1164
1165 mPendingRelaunchCount++;
1166 }
1167
1168 void detachChildren() {
Robert Carrfd8e93b2018-05-10 13:40:25 -07001169 SurfaceControl.openTransaction();
Robert Carrd5c7dd62017-03-08 10:39:30 -08001170 for (int i = mChildren.size() - 1; i >= 0; i--) {
1171 final WindowState w = mChildren.get(i);
1172 w.mWinAnimator.detachChildren();
1173 }
Robert Carrfd8e93b2018-05-10 13:40:25 -07001174 SurfaceControl.closeTransaction();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001175 }
1176
1177 void finishRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001178 unfreezeBounds();
1179
Chong Zhangd78ddb42016-03-02 17:01:14 -08001180 if (mPendingRelaunchCount > 0) {
1181 mPendingRelaunchCount--;
Bryce Lee081554b2017-05-25 07:52:12 -07001182 } else {
1183 // Update keyguard flags upon finishing relaunch.
1184 checkKeyguardFlagsChanged();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001185 }
1186 }
1187
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001188 void clearRelaunching() {
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001189 if (mPendingRelaunchCount == 0) {
1190 return;
1191 }
Robert Carr68375192017-06-13 12:41:53 -07001192 unfreezeBounds();
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001193 mPendingRelaunchCount = 0;
1194 }
1195
Wale Ogunwale07bcab72016-10-14 15:30:09 -07001196 /**
1197 * Returns true if the new child window we are adding to this token is considered greater than
1198 * the existing child window in this token in terms of z-order.
1199 */
1200 @Override
1201 protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
1202 WindowState existingWindow) {
1203 final int type1 = newWindow.mAttrs.type;
1204 final int type2 = existingWindow.mAttrs.type;
1205
1206 // Base application windows should be z-ordered BELOW all other windows in the app token.
1207 if (type1 == TYPE_BASE_APPLICATION && type2 != TYPE_BASE_APPLICATION) {
1208 return false;
1209 } else if (type1 != TYPE_BASE_APPLICATION && type2 == TYPE_BASE_APPLICATION) {
1210 return true;
1211 }
1212
1213 // Starting windows should be z-ordered ABOVE all other windows in the app token.
1214 if (type1 == TYPE_APPLICATION_STARTING && type2 != TYPE_APPLICATION_STARTING) {
1215 return true;
1216 } else if (type1 != TYPE_APPLICATION_STARTING && type2 == TYPE_APPLICATION_STARTING) {
1217 return false;
1218 }
1219
1220 // Otherwise the new window is greater than the existing window.
1221 return true;
1222 }
1223
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001224 @Override
Robert Carra1eb4392015-12-10 12:43:51 -08001225 void addWindow(WindowState w) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001226 super.addWindow(w);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001227
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001228 boolean gotReplacementWindow = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001229 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001230 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001231 gotReplacementWindow |= candidate.setReplacementWindowIfNeeded(w);
1232 }
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001233
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001234 // if we got a replacement window, reset the timeout to give drawing more time
1235 if (gotReplacementWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001236 mWmService.scheduleWindowReplacementTimeouts(this);
Robert Carra1eb4392015-12-10 12:43:51 -08001237 }
Jorim Jaggife762342016-10-13 14:33:27 +02001238 checkKeyguardFlagsChanged();
1239 }
1240
1241 @Override
1242 void removeChild(WindowState child) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001243 if (!mChildren.contains(child)) {
1244 // This can be true when testing.
1245 return;
1246 }
Jorim Jaggife762342016-10-13 14:33:27 +02001247 super.removeChild(child);
1248 checkKeyguardFlagsChanged();
Adrian Roos23df3a32018-03-15 15:41:13 +01001249 updateLetterboxSurface(child);
Robert Carra1eb4392015-12-10 12:43:51 -08001250 }
1251
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001252 private boolean waitingForReplacement() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001253 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001254 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001255 if (candidate.waitingForReplacement()) {
Robert Carra1eb4392015-12-10 12:43:51 -08001256 return true;
1257 }
1258 }
1259 return false;
1260 }
1261
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001262 void onWindowReplacementTimeout() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001263 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001264 (mChildren.get(i)).onWindowReplacementTimeout();
Robert Carra1eb4392015-12-10 12:43:51 -08001265 }
1266 }
1267
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001268 void reparent(Task task, int position) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001269 if (DEBUG_ADD_REMOVE) {
1270 Slog.i(TAG_WM, "reparent: moving app token=" + this
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001271 + " to task=" + task.mTaskId + " at " + position);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001272 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001273 if (task == null) {
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001274 throw new IllegalArgumentException("reparent: could not find task");
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001275 }
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001276 final Task currentTask = getTask();
1277 if (task == currentTask) {
Winson Chung30480042017-01-26 10:55:34 -08001278 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001279 "window token=" + this + " already child of task=" + currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001280 }
Bryce Lee6d410262017-02-28 15:30:17 -08001281
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001282 if (currentTask.mStack != task.mStack) {
Bryce Lee6d410262017-02-28 15:30:17 -08001283 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001284 "window token=" + this + " current task=" + currentTask
Bryce Lee6d410262017-02-28 15:30:17 -08001285 + " belongs to a different stack than " + task);
1286 }
1287
Winson Chung30480042017-01-26 10:55:34 -08001288 if (DEBUG_ADD_REMOVE) Slog.i(TAG, "reParentWindowToken: removing window token=" + this
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001289 + " from task=" + currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001290 final DisplayContent prevDisplayContent = getDisplayContent();
1291
Bryce Lee6d410262017-02-28 15:30:17 -08001292 mReparenting = true;
1293
Winson Chung30480042017-01-26 10:55:34 -08001294 getParent().removeChild(this);
1295 task.addChild(this, position);
1296
Bryce Lee6d410262017-02-28 15:30:17 -08001297 mReparenting = false;
1298
Winson Chung30480042017-01-26 10:55:34 -08001299 // Relayout display(s).
1300 final DisplayContent displayContent = task.getDisplayContent();
1301 displayContent.setLayoutNeeded();
1302 if (prevDisplayContent != displayContent) {
1303 onDisplayChanged(displayContent);
1304 prevDisplayContent.setLayoutNeeded();
1305 }
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001306 getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
Winson Chung30480042017-01-26 10:55:34 -08001307 }
1308
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001309 @Override
1310 void onDisplayChanged(DisplayContent dc) {
1311 DisplayContent prevDc = mDisplayContent;
1312 super.onDisplayChanged(dc);
Evan Rosky25b56192019-02-06 16:10:56 -08001313 if (prevDc == null) {
1314 return;
1315 }
1316 if (prevDc.mChangingApps.contains(this)) {
1317 // This gets called *after* the AppWindowToken has been reparented to the new display.
1318 // That reparenting resulted in this window changing modes (eg. FREEFORM -> FULLSCREEN),
1319 // so this token is now "frozen" while waiting for the animation to start on prevDc
1320 // (which will be cancelled since the window is no-longer a child). However, since this
1321 // is no longer a child of prevDc, this won't be notified of the cancelled animation,
1322 // so we need to cancel the change transition here.
1323 clearChangeLeash(getPendingTransaction(), true /* cancel */);
1324 }
1325 if (prevDc.mFocusedApp == this) {
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001326 prevDc.setFocusedApp(null);
lumarkbf844642018-11-23 17:11:36 +08001327 final TaskStack stack = dc.getTopStack();
1328 if (stack != null) {
1329 final Task task = stack.getTopChild();
1330 if (task != null && task.getTopChild() == this) {
1331 dc.setFocusedApp(this);
1332 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001333 }
1334 }
Riddle Hsu192fe762019-01-15 23:41:57 +08001335
1336 if (prevDc != mDisplayContent && mLetterbox != null) {
1337 mLetterbox.onMovedToDisplay(mDisplayContent.getDisplayId());
1338 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001339 }
1340
Jorim Jaggi0429f352015-12-22 16:29:16 +01001341 /**
1342 * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds
1343 * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even
1344 * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen
1345 * with a queue.
1346 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001347 private void freezeBounds() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001348 final Task task = getTask();
1349 mFrozenBounds.offer(new Rect(task.mPreparedFrozenBounds));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001350
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001351 if (task.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001352 // We didn't call prepareFreezingBounds on the task, so use the current value.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001353 mFrozenMergedConfig.offer(new Configuration(task.getConfiguration()));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001354 } else {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001355 mFrozenMergedConfig.offer(new Configuration(task.mPreparedFrozenMergedConfig));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001356 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001357 // Calling unset() to make it equal to Configuration.EMPTY.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001358 task.mPreparedFrozenMergedConfig.unset();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001359 }
1360
1361 /**
1362 * Unfreezes the previously frozen bounds. See {@link #freezeBounds}.
1363 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001364 private void unfreezeBounds() {
Robert Carr68375192017-06-13 12:41:53 -07001365 if (mFrozenBounds.isEmpty()) {
1366 return;
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001367 }
Robert Carr68375192017-06-13 12:41:53 -07001368 mFrozenBounds.remove();
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001369 if (!mFrozenMergedConfig.isEmpty()) {
1370 mFrozenMergedConfig.remove();
1371 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001372 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001373 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001374 win.onUnfreezeBounds();
Jorim Jaggi4846ee32016-01-07 17:39:12 +01001375 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001376 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001377 }
1378
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001379 void setAppLayoutChanges(int changes, String reason) {
1380 if (!mChildren.isEmpty()) {
1381 final DisplayContent dc = getDisplayContent();
1382 dc.pendingLayoutChanges |= changes;
1383 if (DEBUG_LAYOUT_REPEATS) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001384 mWmService.mWindowPlacerLocked.debugLayoutRepeats(reason, dc.pendingLayoutChanges);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001385 }
1386 }
1387 }
1388
1389 void removeReplacedWindowIfNeeded(WindowState replacement) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001390 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001391 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001392 if (win.removeReplacedWindowIfNeeded(replacement)) {
1393 return;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001394 }
1395 }
1396 }
1397
1398 void startFreezingScreen() {
1399 if (DEBUG_ORIENTATION) logWithStack(TAG, "Set freezing of " + appToken + ": hidden="
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001400 + isHidden() + " freezing=" + mFreezingScreen + " hiddenRequested="
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001401 + hiddenRequested);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001402 if (!hiddenRequested) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001403 if (!mFreezingScreen) {
1404 mFreezingScreen = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001405 mWmService.registerAppFreezeListener(this);
1406 mWmService.mAppsFreezingScreen++;
1407 if (mWmService.mAppsFreezingScreen == 1) {
1408 mWmService.startFreezingDisplayLocked(0, 0, getDisplayContent());
1409 mWmService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
1410 mWmService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001411 }
1412 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001413 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001414 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001415 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001416 w.onStartFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001417 }
1418 }
1419 }
1420
1421 void stopFreezingScreen(boolean unfreezeSurfaceNow, boolean force) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001422 if (!mFreezingScreen) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001423 return;
1424 }
1425 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + this + " force=" + force);
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001426 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001427 boolean unfrozeWindows = false;
1428 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001429 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001430 unfrozeWindows |= w.onStopFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001431 }
1432 if (force || unfrozeWindows) {
1433 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "No longer freezing: " + this);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001434 mFreezingScreen = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001435 mWmService.unregisterAppFreezeListener(this);
1436 mWmService.mAppsFreezingScreen--;
1437 mWmService.mLastFinishedFreezeSource = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001438 }
1439 if (unfreezeSurfaceNow) {
1440 if (unfrozeWindows) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001441 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001442 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001443 mWmService.stopFreezingDisplayLocked();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001444 }
1445 }
1446
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001447 @Override
1448 public void onAppFreezeTimeout() {
1449 Slog.w(TAG_WM, "Force clearing freeze: " + this);
1450 stopFreezingScreen(true, true);
1451 }
1452
Jorim Jaggi60f9c972018-02-01 19:21:07 +01001453 /**
1454 * Tries to transfer the starting window from a token that's above ourselves in the task but
1455 * not visible anymore. This is a common scenario apps use: Trampoline activity T start main
1456 * activity M in the same task. Now, when reopening the task, T starts on top of M but then
1457 * immediately finishes after, so we have to transfer T to M.
1458 */
1459 void transferStartingWindowFromHiddenAboveTokenIfNeeded() {
1460 final Task task = getTask();
1461 for (int i = task.mChildren.size() - 1; i >= 0; i--) {
1462 final AppWindowToken fromToken = task.mChildren.get(i);
1463 if (fromToken == this) {
1464 return;
1465 }
1466 if (fromToken.hiddenRequested && transferStartingWindow(fromToken.token)) {
1467 return;
1468 }
1469 }
1470 }
1471
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001472 boolean transferStartingWindow(IBinder transferFrom) {
Wale Ogunwale02319a62016-09-26 15:21:22 -07001473 final AppWindowToken fromToken = getDisplayContent().getAppWindowToken(transferFrom);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001474 if (fromToken == null) {
1475 return false;
1476 }
1477
1478 final WindowState tStartingWindow = fromToken.startingWindow;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08001479 if (tStartingWindow != null && fromToken.startingSurface != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001480 // In this case, the starting icon has already been displayed, so start
1481 // letting windows get shown immediately without any more transitions.
lumark588a3e82018-07-20 18:53:54 +08001482 getDisplayContent().mSkipAppTransitionAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001483
1484 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Moving existing starting " + tStartingWindow
1485 + " from " + fromToken + " to " + this);
1486
1487 final long origId = Binder.clearCallingIdentity();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001488 try {
1489 // Transfer the starting window over to the new token.
1490 startingData = fromToken.startingData;
1491 startingSurface = fromToken.startingSurface;
1492 startingDisplayed = fromToken.startingDisplayed;
1493 fromToken.startingDisplayed = false;
1494 startingWindow = tStartingWindow;
1495 reportedVisible = fromToken.reportedVisible;
1496 fromToken.startingData = null;
1497 fromToken.startingSurface = null;
1498 fromToken.startingWindow = null;
1499 fromToken.startingMoved = true;
1500 tStartingWindow.mToken = this;
1501 tStartingWindow.mAppToken = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001502
Peter Visontay3556a3b2017-11-01 17:23:17 +00001503 if (DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
1504 "Removing starting " + tStartingWindow + " from " + fromToken);
1505 fromToken.removeChild(tStartingWindow);
1506 fromToken.postWindowRemoveStartingWindowCleanup(tStartingWindow);
1507 fromToken.mHiddenSetFromTransferredStartingWindow = false;
1508 addWindow(tStartingWindow);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001509
Peter Visontay3556a3b2017-11-01 17:23:17 +00001510 // Propagate other interesting state between the tokens. If the old token is displayed,
1511 // we should immediately force the new one to be displayed. If it is animating, we need
1512 // to move that animation to the new one.
1513 if (fromToken.allDrawn) {
1514 allDrawn = true;
1515 deferClearAllDrawn = fromToken.deferClearAllDrawn;
1516 }
1517 if (fromToken.firstWindowDrawn) {
1518 firstWindowDrawn = true;
1519 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001520 if (!fromToken.isHidden()) {
1521 setHidden(false);
Peter Visontay3556a3b2017-11-01 17:23:17 +00001522 hiddenRequested = false;
1523 mHiddenSetFromTransferredStartingWindow = true;
1524 }
1525 setClientHidden(fromToken.mClientHidden);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001526
Jorim Jaggi980c9de2017-11-17 01:41:37 +01001527 transferAnimation(fromToken);
1528
1529 // When transferring an animation, we no longer need to apply an animation to the
1530 // the token we transfer the animation over. Thus, remove the animation from
1531 // pending opening apps.
lumark588a3e82018-07-20 18:53:54 +08001532 getDisplayContent().mOpeningApps.remove(this);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001533
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001534 mWmService.updateFocusedWindowLocked(
Peter Visontay3556a3b2017-11-01 17:23:17 +00001535 UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/);
1536 getDisplayContent().setLayoutNeeded();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001537 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001538 } finally {
1539 Binder.restoreCallingIdentity(origId);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001540 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001541 return true;
1542 } else if (fromToken.startingData != null) {
1543 // The previous app was getting ready to show a
1544 // starting window, but hasn't yet done so. Steal it!
1545 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
1546 "Moving pending starting from " + fromToken + " to " + this);
1547 startingData = fromToken.startingData;
1548 fromToken.startingData = null;
1549 fromToken.startingMoved = true;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001550 scheduleAddStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001551 return true;
1552 }
1553
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001554 // TODO: Transfer thumbnail
1555
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001556 return false;
1557 }
1558
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001559 boolean isLastWindow(WindowState win) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001560 return mChildren.size() == 1 && mChildren.get(0) == win;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001561 }
1562
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001563 @Override
1564 void onAppTransitionDone() {
1565 sendingToBottom = false;
1566 }
1567
Wale Ogunwale51362492016-09-08 17:49:17 -07001568 /**
1569 * We override because this class doesn't want its children affecting its reported orientation
1570 * in anyway.
1571 */
1572 @Override
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001573 int getOrientation(int candidate) {
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001574 if (candidate == SCREEN_ORIENTATION_BEHIND) {
1575 // Allow app to specify orientation regardless of its visibility state if the current
1576 // candidate want us to use orientation behind. I.e. the visible app on-top of this one
1577 // wants us to use the orientation of the app behind it.
1578 return mOrientation;
1579 }
1580
Bryce Lee61fbcbc2017-03-10 14:14:03 -08001581 // The {@link AppWindowToken} should only specify an orientation when it is not closing or
1582 // going to the bottom. Allowing closing {@link AppWindowToken} to participate can lead to
1583 // an Activity in another task being started in the wrong orientation during the transition.
lumark588a3e82018-07-20 18:53:54 +08001584 if (!(sendingToBottom || getDisplayContent().mClosingApps.contains(this))
1585 && (isVisible() || getDisplayContent().mOpeningApps.contains(this))) {
Bryce Leea163b762017-01-24 11:05:01 -08001586 return mOrientation;
Wale Ogunwale51362492016-09-08 17:49:17 -07001587 }
Bryce Leea163b762017-01-24 11:05:01 -08001588
1589 return SCREEN_ORIENTATION_UNSET;
Wale Ogunwale51362492016-09-08 17:49:17 -07001590 }
1591
Wale Ogunwaleb198b742016-12-01 08:44:09 -08001592 /** Returns the app's preferred orientation regardless of its currently visibility state. */
1593 int getOrientationIgnoreVisibility() {
1594 return mOrientation;
1595 }
1596
Riddle Hsub398da32019-01-21 21:48:16 +08001597 /** @return {@code true} if the compatibility bounds is taking effect. */
1598 boolean inSizeCompatMode() {
1599 return mSizeCompatBounds != null;
1600 }
1601
1602 @Override
1603 float getSizeCompatScale() {
1604 return inSizeCompatMode() ? mSizeCompatScale : super.getSizeCompatScale();
1605 }
1606
1607 /**
1608 * @return Non-empty bounds if the activity has override bounds.
1609 * @see ActivityRecord#resolveOverrideConfiguration(Configuration)
1610 */
1611 Rect getResolvedOverrideBounds() {
1612 // Get bounds from resolved override configuration because it is computed with orientation.
1613 return getResolvedOverrideConfiguration().windowConfiguration.getBounds();
1614 }
1615
Craig Mautnerdbb79912012-03-01 18:59:14 -08001616 @Override
Winson Chunge55c0192017-08-24 14:50:48 -07001617 public void onConfigurationChanged(Configuration newParentConfig) {
1618 final int prevWinMode = getWindowingMode();
Evan Rosky2289ba12018-11-19 18:28:18 -08001619 mTmpPrevBounds.set(getBounds());
Winson Chunge55c0192017-08-24 14:50:48 -07001620 super.onConfigurationChanged(newParentConfig);
Riddle Hsub398da32019-01-21 21:48:16 +08001621
1622 final Task task = getTask();
1623 final Rect overrideBounds = getResolvedOverrideBounds();
1624 if (task != null && !overrideBounds.isEmpty()
1625 // If the changes come from change-listener, the incoming parent configuration is
1626 // still the old one. Make sure their orientations are the same to reduce computing
1627 // the compatibility bounds for the intermediate state.
Riddle Hsu04164182019-03-07 18:03:27 +08001628 && (task.mTaskRecord == null || task.mTaskRecord
1629 .getConfiguration().orientation == newParentConfig.orientation)) {
Riddle Hsub398da32019-01-21 21:48:16 +08001630 final Rect taskBounds = task.getBounds();
1631 // Since we only center the activity horizontally, if only the fixed height is smaller
1632 // than its container, the override bounds don't need to take effect.
1633 if ((overrideBounds.width() != taskBounds.width()
1634 || overrideBounds.height() > taskBounds.height())) {
1635 calculateCompatBoundsTransformation(newParentConfig);
1636 updateSurfacePosition();
1637 } else if (mSizeCompatBounds != null) {
1638 mSizeCompatBounds = null;
1639 mSizeCompatScale = 1f;
1640 updateSurfacePosition();
1641 }
1642 }
1643
Winson Chunge55c0192017-08-24 14:50:48 -07001644 final int winMode = getWindowingMode();
1645
1646 if (prevWinMode == winMode) {
1647 return;
1648 }
1649
1650 if (prevWinMode != WINDOWING_MODE_UNDEFINED && winMode == WINDOWING_MODE_PINNED) {
1651 // Entering PiP from fullscreen, reset the snap fraction
1652 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(this);
Winson Chung82267ce2018-04-06 16:38:26 -07001653 } else if (prevWinMode == WINDOWING_MODE_PINNED && winMode != WINDOWING_MODE_UNDEFINED
1654 && !isHidden()) {
Winson Chunge55c0192017-08-24 14:50:48 -07001655 // Leaving PiP to fullscreen, save the snap fraction based on the pre-animation bounds
1656 // for the next re-entry into PiP (assuming the activity is not hidden or destroyed)
1657 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
1658 if (pinnedStack != null) {
Winson Chung8efa1652018-06-06 09:34:23 -07001659 final Rect stackBounds;
1660 if (pinnedStack.lastAnimatingBoundsWasToFullscreen()) {
1661 // We are animating the bounds, use the pre-animation bounds to save the snap
1662 // fraction
1663 stackBounds = pinnedStack.mPreAnimationBounds;
1664 } else {
1665 // We skip the animation if the fullscreen configuration is not compatible, so
1666 // use the current bounds to calculate the saved snap fraction instead
1667 // (see PinnedActivityStack.skipResizeAnimation())
1668 stackBounds = mTmpRect;
1669 pinnedStack.getBounds(stackBounds);
1670 }
Winson Chunge55c0192017-08-24 14:50:48 -07001671 mDisplayContent.mPinnedStackControllerLocked.saveReentrySnapFraction(this,
Winson Chung8efa1652018-06-06 09:34:23 -07001672 stackBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001673 }
Evan Rosky2289ba12018-11-19 18:28:18 -08001674 } else if (shouldStartChangeTransition(prevWinMode, winMode)) {
1675 initializeChangeTransition(mTmpPrevBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001676 }
1677 }
1678
Evan Rosky2289ba12018-11-19 18:28:18 -08001679 private boolean shouldStartChangeTransition(int prevWinMode, int newWinMode) {
Evan Rosky25b56192019-02-06 16:10:56 -08001680 if (mWmService.mDisableTransitionAnimation
1681 || !isVisible()
1682 || getDisplayContent().mAppTransition.isTransitionSet()
1683 || getSurfaceControl() == null) {
Evan Rosky2289ba12018-11-19 18:28:18 -08001684 return false;
1685 }
1686 // Only do an animation into and out-of freeform mode for now. Other mode
1687 // transition animations are currently handled by system-ui.
1688 return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
1689 }
1690
1691 /**
1692 * Initializes a change transition. Because the app is visible already, there is a small period
1693 * of time where the user can see the app content/window update before the transition starts.
1694 * To prevent this, we immediately take a snapshot and place the app/snapshot into a leash which
1695 * "freezes" the location/crop until the transition starts.
1696 * <p>
1697 * Here's a walk-through of the process:
1698 * 1. Create a temporary leash ("interim-change-leash") and reparent the app to it.
1699 * 2. Set the temporary leash's position/crop to the current state.
1700 * 3. Create a snapshot and place that at the top of the leash to cover up content changes.
1701 * 4. Once the transition is ready, it will reparent the app to the animation leash.
1702 * 5. Detach the interim-change-leash.
1703 */
1704 private void initializeChangeTransition(Rect startBounds) {
1705 mDisplayContent.prepareAppTransition(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
1706 false /* alwaysKeepCurrent */, 0, false /* forceOverride */);
1707 mDisplayContent.mChangingApps.add(this);
1708 mTransitStartRect.set(startBounds);
1709
1710 final SurfaceControl.Builder builder = makeAnimationLeash()
1711 .setParent(getAnimationLeashParent())
1712 .setName(getSurfaceControl() + " - interim-change-leash");
1713 mTransitChangeLeash = builder.build();
1714 Transaction t = getPendingTransaction();
1715 t.setWindowCrop(mTransitChangeLeash, startBounds.width(), startBounds.height());
1716 t.setPosition(mTransitChangeLeash, startBounds.left, startBounds.top);
1717 t.show(mTransitChangeLeash);
1718 t.reparent(getSurfaceControl(), mTransitChangeLeash);
1719 onAnimationLeashCreated(t, mTransitChangeLeash);
1720
Evan Rosky966759f2019-01-15 10:33:58 -08001721 // Skip creating snapshot if this transition is controlled by a remote animator which
1722 // doesn't need it.
1723 ArraySet<Integer> activityTypes = new ArraySet<>();
1724 activityTypes.add(getActivityType());
1725 RemoteAnimationAdapter adapter =
1726 mDisplayContent.mAppTransitionController.getRemoteAnimationOverride(
1727 this, TRANSIT_TASK_CHANGE_WINDOWING_MODE, activityTypes);
1728 if (adapter != null && !adapter.getChangeNeedsSnapshot()) {
1729 return;
1730 }
1731
Evan Rosky2289ba12018-11-19 18:28:18 -08001732 if (mThumbnail == null && getTask() != null) {
1733 final TaskSnapshotController snapshotCtrl = mWmService.mTaskSnapshotController;
1734 final ArraySet<Task> tasks = new ArraySet<>();
1735 tasks.add(getTask());
1736 snapshotCtrl.snapshotTasks(tasks);
1737 snapshotCtrl.addSkipClosingAppSnapshotTasks(tasks);
1738 final ActivityManager.TaskSnapshot snapshot = snapshotCtrl.getSnapshot(
1739 getTask().mTaskId, getTask().mUserId, false /* restoreFromDisk */,
1740 false /* reducedResolution */);
Yunfan Chendcb1fcf2019-02-07 19:08:41 +09001741 if (snapshot != null) {
1742 mThumbnail = new AppWindowThumbnail(t, this, snapshot.getSnapshot(),
1743 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();
1763 final Rect viewportBounds = parentAppBounds != null
1764 ? parentAppBounds : newParentConfig.windowConfiguration.getBounds();
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 Hsu04164182019-03-07 18:03:27 +08001783 // The decor inset is included in height.
1784 mSizeCompatBounds.bottom += viewportBounds.top;
Riddle Hsub398da32019-01-21 21:48:16 +08001785 mSizeCompatBounds.left += offsetX;
1786 mSizeCompatBounds.right += offsetX;
1787 }
1788
1789 @Override
1790 public Rect getBounds() {
1791 if (mSizeCompatBounds != null) {
1792 return mSizeCompatBounds;
1793 }
1794 return super.getBounds();
1795 }
1796
1797 @Override
1798 public boolean matchParentBounds() {
1799 if (super.matchParentBounds()) {
1800 return true;
1801 }
1802 // An activity in size compatibility mode may have override bounds which equals to its
1803 // parent bounds, so the exact bounds should also be checked.
1804 final WindowContainer parent = getParent();
1805 return parent == null || parent.getBounds().equals(getResolvedOverrideBounds());
1806 }
1807
Winson Chunge55c0192017-08-24 14:50:48 -07001808 @Override
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001809 void checkAppWindowsReadyToShow() {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001810 if (allDrawn == mLastAllDrawn) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001811 return;
1812 }
1813
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001814 mLastAllDrawn = allDrawn;
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001815 if (!allDrawn) {
1816 return;
1817 }
1818
1819 // The token has now changed state to having all windows shown... what to do, what to do?
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001820 if (mFreezingScreen) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001821 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001822 stopFreezingScreen(false, true);
1823 if (DEBUG_ORIENTATION) Slog.i(TAG,
1824 "Setting mOrientationChangeComplete=true because wtoken " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001825 + " numInteresting=" + mNumInterestingWindows + " numDrawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001826 // This will set mOrientationChangeComplete and cause a pass through layout.
1827 setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001828 "checkAppWindowsReadyToShow: freezingScreen");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001829 } else {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001830 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001831
1832 // We can now show all of the drawn windows!
lumark588a3e82018-07-20 18:53:54 +08001833 if (!getDisplayContent().mOpeningApps.contains(this) && canShowWindows()) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001834 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001835 }
1836 }
1837 }
1838
Matthew Ng5d23afa2017-06-21 16:16:24 -07001839 /**
Bryce Leed390deb2017-06-22 13:14:28 -07001840 * Returns whether the drawn window states of this {@link AppWindowToken} has considered every
1841 * child {@link WindowState}. A child is considered if it has been passed into
1842 * {@link #updateDrawnWindowStates(WindowState)} after being added. This is used to determine
1843 * whether states, such as {@code allDrawn}, can be set, which relies on state variables such as
1844 * {@code mNumInterestingWindows}, which depend on all {@link WindowState}s being considered.
1845 *
1846 * @return {@code true} If all children have been considered, {@code false}.
1847 */
1848 private boolean allDrawnStatesConsidered() {
Bryce Lee6311c4b2017-07-06 14:09:29 -07001849 for (int i = mChildren.size() - 1; i >= 0; --i) {
1850 final WindowState child = mChildren.get(i);
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001851 if (child.mightAffectAllDrawn() && !child.getDrawnStateEvaluated()) {
Bryce Leed390deb2017-06-22 13:14:28 -07001852 return false;
1853 }
1854 }
1855 return true;
1856 }
1857
1858 /**
Matthew Ng5d23afa2017-06-21 16:16:24 -07001859 * Determines if the token has finished drawing. This should only be called from
1860 * {@link DisplayContent#applySurfaceChangesTransaction}
1861 */
Matthew Ng498c71d2017-04-18 13:55:45 -07001862 void updateAllDrawn() {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001863 if (!allDrawn) {
Matthew Ng498c71d2017-04-18 13:55:45 -07001864 // Number of drawn windows can be less when a window is being relaunched, wait for
Bryce Leed390deb2017-06-22 13:14:28 -07001865 // all windows to be launched and drawn for this token be considered all drawn.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001866 final int numInteresting = mNumInterestingWindows;
Bryce Leed390deb2017-06-22 13:14:28 -07001867
1868 // We must make sure that all present children have been considered (determined by
1869 // {@link #allDrawnStatesConsidered}) before evaluating whether everything has been
1870 // drawn.
1871 if (numInteresting > 0 && allDrawnStatesConsidered()
1872 && mNumDrawnWindows >= numInteresting && !isRelaunching()) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001873 if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawn: " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001874 + " interesting=" + numInteresting + " drawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001875 allDrawn = true;
1876 // Force an additional layout pass where
1877 // WindowStateAnimator#commitFinishDrawingLocked() will call performShowLocked().
Matthew Ng498c71d2017-04-18 13:55:45 -07001878 if (mDisplayContent != null) {
1879 mDisplayContent.setLayoutNeeded();
1880 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001881 mWmService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
Robert Carrecc06b32017-04-18 14:25:10 -07001882
Winson Chunge7ba6862017-05-24 12:13:33 -07001883 // Notify the pinned stack upon all windows drawn. If there was an animation in
1884 // progress then this signal will resume that animation.
Wale Ogunwale61911492017-10-11 08:50:50 -07001885 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
Winson Chunge7ba6862017-05-24 12:13:33 -07001886 if (pinnedStack != null) {
1887 pinnedStack.onAllWindowsDrawn();
Robert Carrecc06b32017-04-18 14:25:10 -07001888 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001889 }
1890 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001891 }
1892
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001893 boolean keyDispatchingTimedOut(String reason, int windowPid) {
1894 return mActivityRecord != null && mActivityRecord.keyDispatchingTimedOut(reason, windowPid);
1895 }
1896
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001897 /**
1898 * Updated this app token tracking states for interesting and drawn windows based on the window.
1899 *
1900 * @return Returns true if the input window is considered interesting and drawn while all the
1901 * windows in this app token where not considered drawn as of the last pass.
1902 */
1903 boolean updateDrawnWindowStates(WindowState w) {
Bryce Leed390deb2017-06-22 13:14:28 -07001904 w.setDrawnStateEvaluated(true /*evaluated*/);
1905
Jorim Jaggie4b0f282017-05-17 15:10:29 +02001906 if (DEBUG_STARTING_WINDOW_VERBOSE && w == startingWindow) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001907 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + w.isOnScreen()
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001908 + " allDrawn=" + allDrawn + " freezingScreen=" + mFreezingScreen);
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001909 }
1910
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001911 if (allDrawn && !mFreezingScreen) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001912 return false;
1913 }
1914
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001915 if (mLastTransactionSequence != mWmService.mTransactionSequence) {
1916 mLastTransactionSequence = mWmService.mTransactionSequence;
Matthew Ng53e66b22018-01-12 17:13:13 -08001917 mNumDrawnWindows = 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001918 startingDisplayed = false;
Matthew Ng53e66b22018-01-12 17:13:13 -08001919
1920 // There is the main base application window, even if it is exiting, wait for it
1921 mNumInterestingWindows = findMainWindow(false /* includeStartingApp */) != null ? 1 : 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001922 }
1923
1924 final WindowStateAnimator winAnimator = w.mWinAnimator;
1925
1926 boolean isInterestingAndDrawn = false;
1927
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001928 if (!allDrawn && w.mightAffectAllDrawn()) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001929 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
1930 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001931 + ", isAnimationSet=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001932 if (!w.isDrawnLw()) {
1933 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController
1934 + " pv=" + w.mPolicyVisibility
1935 + " mDrawState=" + winAnimator.drawStateToString()
1936 + " ph=" + w.isParentWindowHidden() + " th=" + hiddenRequested
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001937 + " a=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001938 }
1939 }
1940
1941 if (w != startingWindow) {
1942 if (w.isInteresting()) {
Matthew Ng53e66b22018-01-12 17:13:13 -08001943 // Add non-main window as interesting since the main app has already been added
1944 if (findMainWindow(false /* includeStartingApp */) != w) {
1945 mNumInterestingWindows++;
1946 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001947 if (w.isDrawnLw()) {
1948 mNumDrawnWindows++;
1949
1950 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, "tokenMayBeDrawn: "
1951 + this + " w=" + w + " numInteresting=" + mNumInterestingWindows
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001952 + " freezingScreen=" + mFreezingScreen
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001953 + " mAppFreezing=" + w.mAppFreezing);
1954
1955 isInterestingAndDrawn = true;
1956 }
1957 }
1958 } else if (w.isDrawnLw()) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001959 if (mActivityRecord != null) {
1960 mActivityRecord.onStartingWindowDrawn(SystemClock.uptimeMillis());
Jorim Jaggi3878ca32017-02-02 17:13:05 -08001961 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001962 startingDisplayed = true;
1963 }
1964 }
1965
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001966 return isInterestingAndDrawn;
1967 }
1968
Adrian Roos23df3a32018-03-15 15:41:13 +01001969 void layoutLetterbox(WindowState winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001970 final WindowState w = findMainWindow();
Adrian Roosf93b6d22018-03-21 13:48:26 +01001971 if (w == null || winHint != null && w != winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001972 return;
1973 }
Jorim Jaggia32da382018-03-28 18:01:22 +02001974 final boolean surfaceReady = w.isDrawnLw() // Regular case
Adrian Roosf93b6d22018-03-21 13:48:26 +01001975 || w.mWinAnimator.mSurfaceDestroyDeferred // The preserved surface is still ready.
1976 || w.isDragResizeChanged(); // Waiting for relayoutWindow to call preserveSurface.
Jorim Jaggi4981f152019-03-26 18:58:45 +01001977 final boolean needsLetterbox = surfaceReady && w.isLetterboxedAppWindow() && fillsParent();
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001978 if (needsLetterbox) {
1979 if (mLetterbox == null) {
1980 mLetterbox = new Letterbox(() -> makeChildSurface(null));
Riddle Hsu192fe762019-01-15 23:41:57 +08001981 mLetterbox.attachInput(w);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001982 }
Adrian Roos7af9d972018-11-30 15:26:27 +01001983 getPosition(mTmpPoint);
Evan Rosky4fb1e912019-03-06 13:54:43 -08001984 // Get the bounds of the "space-to-fill". We union the Task and the Stack bounds here
1985 // to handle both split window (where task-bounds can be larger) and orientation
1986 // letterbox (where the task is letterboxed within stack).
1987 Rect spaceToFill = getTask().getBounds();
1988 if (getStack() != null) {
1989 spaceToFill.union(getStack().getBounds());
1990 }
1991 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()) {
2004 mLetterbox.applySurfaceChanges(mPendingTransaction);
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
2046 if (startingData != null) {
2047 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");
2127 startingData = new SplashScreenStartingData(mWmService, pkg,
2128 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");
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002141 startingData = 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() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002160 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002161 // There can only be one adding request, silly caller!
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002162 mWmService.mAnimationHandler.removeCallbacks(this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002163 }
2164
2165 if (startingData == null) {
2166 // Animation has been canceled... do nothing.
2167 if (DEBUG_STARTING_WINDOW) {
2168 Slog.v(TAG, "startingData was nulled out before handling"
2169 + " mAddStartingWindow: " + AppWindowToken.this);
2170 }
2171 return;
2172 }
2173
2174 if (DEBUG_STARTING_WINDOW) {
2175 Slog.v(TAG, "Add starting " + this + ": startingData=" + startingData);
2176 }
2177
2178 WindowManagerPolicy.StartingSurface surface = null;
2179 try {
2180 surface = startingData.createStartingSurface(AppWindowToken.this);
2181 } catch (Exception e) {
2182 Slog.w(TAG, "Exception when adding starting window", e);
2183 }
2184 if (surface != null) {
2185 boolean abort = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002186 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002187 // If the window was successfully added, then
2188 // we need to remove it.
2189 if (removed || startingData == null) {
2190 if (DEBUG_STARTING_WINDOW) {
2191 Slog.v(TAG, "Aborted starting " + AppWindowToken.this
2192 + ": removed=" + removed + " startingData=" + startingData);
2193 }
2194 startingWindow = null;
2195 startingData = null;
2196 abort = true;
2197 } else {
2198 startingSurface = surface;
2199 }
2200 if (DEBUG_STARTING_WINDOW && !abort) {
2201 Slog.v(TAG, "Added starting " + AppWindowToken.this + ": startingWindow="
2202 + startingWindow + " startingView=" + startingSurface);
2203 }
2204 }
2205 if (abort) {
2206 surface.remove();
2207 }
2208 } else if (DEBUG_STARTING_WINDOW) {
2209 Slog.v(TAG, "Surface returned was null: " + AppWindowToken.this);
2210 }
2211 }
2212 };
2213
2214 private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
2215 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents,
2216 ActivityManager.TaskSnapshot snapshot) {
2217 if (getDisplayContent().mAppTransition.getAppTransition()
2218 == TRANSIT_DOCK_TASK_FROM_RECENTS) {
2219 // TODO(b/34099271): Remove this statement to add back the starting window and figure
2220 // out why it causes flickering, the starting window appears over the thumbnail while
2221 // the docked from recents transition occurs
2222 return STARTING_WINDOW_TYPE_NONE;
2223 } else if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
2224 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2225 } else if (taskSwitch && allowTaskSnapshot) {
Kevin716a9db2018-12-18 16:53:39 -08002226 if (mWmService.mLowRamTaskSnapshotsAndRecents) {
Kevin58b47f12018-12-17 14:09:01 -08002227 // For low RAM devices, we use the splash screen starting window instead of the
2228 // task snapshot starting window.
2229 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2230 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002231 return snapshot == null ? STARTING_WINDOW_TYPE_NONE
2232 : snapshotOrientationSameAsTask(snapshot) || fromRecents
2233 ? STARTING_WINDOW_TYPE_SNAPSHOT : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2234 } else {
2235 return STARTING_WINDOW_TYPE_NONE;
2236 }
2237 }
2238
2239
2240 private boolean snapshotOrientationSameAsTask(ActivityManager.TaskSnapshot snapshot) {
2241 if (snapshot == null) {
2242 return false;
2243 }
2244 return getTask().getConfiguration().orientation == snapshot.getOrientation();
2245 }
2246
2247 void removeStartingWindow() {
2248 if (startingWindow == null) {
2249 if (startingData != null) {
2250 // Starting window has not been added yet, but it is scheduled to be added.
2251 // Go ahead and cancel the request.
2252 if (DEBUG_STARTING_WINDOW) {
2253 Slog.v(TAG_WM, "Clearing startingData for token=" + this);
2254 }
2255 startingData = null;
2256 }
2257 return;
2258 }
2259
2260 final WindowManagerPolicy.StartingSurface surface;
2261 if (startingData != null) {
2262 surface = startingSurface;
2263 startingData = null;
2264 startingSurface = null;
2265 startingWindow = null;
2266 startingDisplayed = false;
2267 if (surface == null) {
2268 if (DEBUG_STARTING_WINDOW) {
2269 Slog.v(TAG_WM, "startingWindow was set but startingSurface==null, couldn't "
2270 + "remove");
2271 }
2272 return;
2273 }
2274 } else {
2275 if (DEBUG_STARTING_WINDOW) {
2276 Slog.v(TAG_WM, "Tried to remove starting window but startingWindow was null:"
2277 + this);
2278 }
2279 return;
2280 }
2281
2282 if (DEBUG_STARTING_WINDOW) {
2283 Slog.v(TAG_WM, "Schedule remove starting " + this
2284 + " startingWindow=" + startingWindow
2285 + " startingView=" + startingSurface
2286 + " Callers=" + Debug.getCallers(5));
2287 }
2288
2289 // Use the same thread to remove the window as we used to add it, as otherwise we end up
2290 // with things in the view hierarchy being called from different threads.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002291 mWmService.mAnimationHandler.post(() -> {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002292 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Removing startingView=" + surface);
2293 try {
2294 surface.remove();
2295 } catch (Exception e) {
2296 Slog.w(TAG_WM, "Exception when removing starting window", e);
2297 }
2298 });
2299 }
2300
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002301 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -07002302 boolean fillsParent() {
2303 return mFillsParent;
2304 }
2305
2306 void setFillsParent(boolean fillsParent) {
2307 mFillsParent = fillsParent;
2308 }
2309
Jorim Jaggife762342016-10-13 14:33:27 +02002310 boolean containsDismissKeyguardWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002311 // Window state is transient during relaunch. We are not guaranteed to be frozen during the
2312 // entirety of the relaunch.
2313 if (isRelaunching()) {
2314 return mLastContainsDismissKeyguardWindow;
2315 }
2316
Jorim Jaggife762342016-10-13 14:33:27 +02002317 for (int i = mChildren.size() - 1; i >= 0; i--) {
2318 if ((mChildren.get(i).mAttrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
2319 return true;
2320 }
2321 }
2322 return false;
2323 }
2324
2325 boolean containsShowWhenLockedWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002326 // When we are relaunching, it is possible for us to be unfrozen before our previous
2327 // windows have been added back. Using the cached value ensures that our previous
2328 // showWhenLocked preference is honored until relaunching is complete.
2329 if (isRelaunching()) {
2330 return mLastContainsShowWhenLockedWindow;
2331 }
2332
Jorim Jaggife762342016-10-13 14:33:27 +02002333 for (int i = mChildren.size() - 1; i >= 0; i--) {
2334 if ((mChildren.get(i).mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
2335 return true;
2336 }
2337 }
Bryce Lee081554b2017-05-25 07:52:12 -07002338
Jorim Jaggife762342016-10-13 14:33:27 +02002339 return false;
2340 }
2341
2342 void checkKeyguardFlagsChanged() {
2343 final boolean containsDismissKeyguard = containsDismissKeyguardWindow();
2344 final boolean containsShowWhenLocked = containsShowWhenLockedWindow();
2345 if (containsDismissKeyguard != mLastContainsDismissKeyguardWindow
2346 || containsShowWhenLocked != mLastContainsShowWhenLockedWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002347 mWmService.notifyKeyguardFlagsChanged(null /* callback */,
lumark588a3e82018-07-20 18:53:54 +08002348 getDisplayContent().getDisplayId());
Jorim Jaggife762342016-10-13 14:33:27 +02002349 }
2350 mLastContainsDismissKeyguardWindow = containsDismissKeyguard;
2351 mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
2352 }
2353
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002354 WindowState getImeTargetBelowWindow(WindowState w) {
2355 final int index = mChildren.indexOf(w);
2356 if (index > 0) {
2357 final WindowState target = mChildren.get(index - 1);
2358 if (target.canBeImeTarget()) {
2359 return target;
2360 }
2361 }
2362 return null;
2363 }
2364
2365 WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
2366 WindowState candidate = null;
2367 for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
2368 final WindowState w = mChildren.get(i);
2369 if (w.mRemoved) {
2370 continue;
2371 }
Jorim Jaggi35d328a2018-08-14 17:00:20 +02002372 if (candidate == null) {
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002373 candidate = w;
2374 }
2375 }
2376 return candidate;
2377 }
2378
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002379 /**
2380 * See {@link Activity#setDisablePreviewScreenshots}.
2381 */
2382 void setDisablePreviewScreenshots(boolean disable) {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002383 mDisablePreviewScreenshots = disable;
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002384 }
2385
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002386 /**
chaviwd3bf08d2017-08-01 17:24:59 -07002387 * Sets whether the current launch can turn the screen on. See {@link #canTurnScreenOn()}
2388 */
2389 void setCanTurnScreenOn(boolean canTurnScreenOn) {
2390 mCanTurnScreenOn = canTurnScreenOn;
2391 }
2392
2393 /**
2394 * Indicates whether the current launch can turn the screen on. This is to prevent multiple
2395 * relayouts from turning the screen back on. The screen should only turn on at most
2396 * once per activity resume.
2397 *
2398 * @return true if the screen can be turned on.
2399 */
2400 boolean canTurnScreenOn() {
2401 return mCanTurnScreenOn;
2402 }
2403
2404 /**
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002405 * Retrieves whether we'd like to generate a snapshot that's based solely on the theme. This is
2406 * the case when preview screenshots are disabled {@link #setDisablePreviewScreenshots} or when
2407 * we can't take a snapshot for other reasons, for example, if we have a secure window.
2408 *
2409 * @return True if we need to generate an app theme snapshot, false if we'd like to take a real
2410 * screenshot.
2411 */
2412 boolean shouldUseAppThemeSnapshot() {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002413 return mDisablePreviewScreenshots || forAllWindows(w -> (w.mAttrs.flags & FLAG_SECURE) != 0,
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002414 true /* topToBottom */);
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002415 }
2416
Jorim Jaggibe418292018-03-26 16:14:12 +02002417 SurfaceControl getAppAnimationLayer() {
Jorim Jaggi391790622018-04-18 15:30:44 +02002418 return getAppAnimationLayer(isActivityTypeHome() ? ANIMATION_LAYER_HOME
2419 : needsZBoost() ? ANIMATION_LAYER_BOOSTED
2420 : ANIMATION_LAYER_STANDARD);
Jorim Jaggibe418292018-03-26 16:14:12 +02002421 }
2422
chaviw23ee71c2017-12-18 11:29:41 -08002423 @Override
Jorim Jaggi596a1992017-12-29 14:48:02 +01002424 public SurfaceControl getAnimationLeashParent() {
Robert Carrb9506032018-02-13 13:54:00 -08002425 // All normal app transitions take place in an animation layer which is below the pinned
2426 // stack but may be above the parent stacks of the given animating apps.
2427 // For transitions in the pinned stack (menu activity) we just let them occur as a child
2428 // of the pinned stack.
2429 if (!inPinnedWindowingMode()) {
2430 return getAppAnimationLayer();
2431 } else {
2432 return getStack().getSurfaceControl();
2433 }
chaviw23ee71c2017-12-18 11:29:41 -08002434 }
2435
Jorim Jaggic6976f02018-04-18 16:31:07 +02002436 private boolean shouldAnimate(int transit) {
2437 final boolean isSplitScreenPrimary =
2438 getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
2439 final boolean allowSplitScreenPrimaryAnimation = transit != TRANSIT_WALLPAPER_OPEN;
2440
lumark54284462019-03-05 20:44:27 +08002441 // Don't animate when the task runs recents animation.
2442 final RecentsAnimationController controller = mWmService.getRecentsAnimationController();
2443 if (controller != null && controller.isAnimatingTask(getTask())) {
2444 return false;
2445 }
2446
Jorim Jaggic6976f02018-04-18 16:31:07 +02002447 // We animate always if it's not split screen primary, and only some special cases in split
2448 // screen primary because it causes issues with stack clipping when we run an un-minimize
2449 // animation at the same time.
2450 return !isSplitScreenPrimary || allowSplitScreenPrimaryAnimation;
2451 }
2452
Vishnu Naira2977262018-07-26 13:31:26 -07002453 /**
2454 * Creates a layer to apply crop to an animation.
2455 */
2456 private SurfaceControl createAnimationBoundsLayer(Transaction t) {
2457 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.i(TAG, "Creating animation bounds layer");
2458 final SurfaceControl.Builder builder = makeAnimationLeash()
2459 .setParent(getAnimationLeashParent())
Vishnu Naire86bd982018-11-28 13:23:17 -08002460 .setName(getSurfaceControl() + " - animation-bounds");
Vishnu Naira2977262018-07-26 13:31:26 -07002461 final SurfaceControl boundsLayer = builder.build();
2462 t.show(boundsLayer);
2463 return boundsLayer;
2464 }
2465
Evan Roskyed6767f2018-10-26 17:21:06 -07002466 @Override
2467 Rect getDisplayedBounds() {
2468 final Task task = getTask();
2469 if (task != null) {
2470 final Rect overrideDisplayedBounds = task.getOverrideDisplayedBounds();
2471 if (!overrideDisplayedBounds.isEmpty()) {
2472 return overrideDisplayedBounds;
2473 }
2474 }
2475 return getBounds();
2476 }
2477
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002478 boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter,
2479 boolean isVoiceInteraction) {
2480
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002481 if (mWmService.mDisableTransitionAnimation || !shouldAnimate(transit)) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002482 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
Jorim Jaggic6976f02018-04-18 16:31:07 +02002483 Slog.v(TAG_WM, "applyAnimation: transition animation is disabled or skipped."
2484 + " atoken=" + this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002485 }
2486 cancelAnimation();
2487 return false;
2488 }
2489
2490 // Only apply an animation if the display isn't frozen. If it is frozen, there is no reason
2491 // to animate and it can cause strange artifacts when we unfreeze the display if some
2492 // different animation is running.
2493 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#applyAnimationLocked");
2494 if (okToAnimate()) {
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002495 final AnimationAdapter adapter;
Evan Rosky2289ba12018-11-19 18:28:18 -08002496 AnimationAdapter thumbnailAdapter = null;
Evan Rosky4fb1e912019-03-06 13:54:43 -08002497
2498 // Separate position and size for use in animators. Use task-bounds for now so
2499 // that activity-level letterbox (maxAspectRatio) is included in the animation.
2500 mTmpRect.set(getTask() != null ? getTask().getBounds() : getBounds());
2501 mTmpPoint.set(mTmpRect.left, mTmpRect.top);
2502 mTmpRect.offsetTo(0, 0);
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002503
Evan Roskyec9488c2019-03-01 19:32:12 -08002504 final boolean isChanging = AppTransition.isChangeTransit(transit) && enter
2505 && getDisplayContent().mChangingApps.contains(this);
Evan Rosky2289ba12018-11-19 18:28:18 -08002506
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002507 // Delaying animation start isn't compatible with remote animations at all.
lumark588a3e82018-07-20 18:53:54 +08002508 if (getDisplayContent().mAppTransition.getRemoteAnimationController() != null
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002509 && !mSurfaceAnimator.isAnimationStartDelayed()) {
Evan Rosky2289ba12018-11-19 18:28:18 -08002510 RemoteAnimationRecord adapters =
2511 getDisplayContent().mAppTransition.getRemoteAnimationController()
2512 .createRemoteAnimationRecord(this, mTmpPoint, mTmpRect,
2513 (isChanging ? mTransitStartRect : null));
2514 adapter = adapters.mAdapter;
2515 thumbnailAdapter = adapters.mThumbnailAdapter;
2516 } else if (isChanging) {
Evan Roskycf76bed2019-01-15 10:33:58 -08002517 final float durationScale = mWmService.getTransitionAnimationScaleLocked();
Evan Rosky2289ba12018-11-19 18:28:18 -08002518 mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y);
2519 adapter = new LocalAnimationAdapter(
2520 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
Evan Roskycf76bed2019-01-15 10:33:58 -08002521 getDisplayContent().getDisplayInfo(), durationScale,
Evan Rosky2289ba12018-11-19 18:28:18 -08002522 true /* isAppAnimation */, false /* isThumbnail */),
2523 mWmService.mSurfaceAnimationRunner);
Evan Rosky966759f2019-01-15 10:33:58 -08002524 if (mThumbnail != null) {
2525 thumbnailAdapter = new LocalAnimationAdapter(
2526 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
Evan Roskycf76bed2019-01-15 10:33:58 -08002527 getDisplayContent().getDisplayInfo(), durationScale,
Evan Rosky966759f2019-01-15 10:33:58 -08002528 true /* isAppAnimation */, true /* isThumbnail */),
2529 mWmService.mSurfaceAnimationRunner);
2530 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002531 mTransit = transit;
2532 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002533 } else {
lumark588a3e82018-07-20 18:53:54 +08002534 final int appStackClipMode =
2535 getDisplayContent().mAppTransition.getAppStackClipMode();
Vishnu Naira2977262018-07-26 13:31:26 -07002536 mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM);
2537
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002538 final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
2539 if (a != null) {
2540 adapter = new LocalAnimationAdapter(
2541 new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
lumark588a3e82018-07-20 18:53:54 +08002542 getDisplayContent().mAppTransition.canSkipFirstFrame(),
Vishnu Naira2977262018-07-26 13:31:26 -07002543 appStackClipMode,
Lucas Dupin3e1dc202018-12-02 15:14:20 -08002544 true /* isAppAnimation */,
2545 mWmService.mWindowCornerRadius),
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002546 mWmService.mSurfaceAnimationRunner);
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002547 if (a.getZAdjustment() == Animation.ZORDER_TOP) {
2548 mNeedsZBoost = true;
2549 }
2550 mTransit = transit;
lumark588a3e82018-07-20 18:53:54 +08002551 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002552 } else {
2553 adapter = null;
chaviw23ee71c2017-12-18 11:29:41 -08002554 }
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002555 }
2556 if (adapter != null) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002557 startAnimation(getPendingTransaction(), adapter, !isVisible());
Jorim Jaggi82c17862018-02-21 17:50:18 +01002558 if (adapter.getShowWallpaper()) {
2559 mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2560 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002561 if (thumbnailAdapter != null) {
2562 mThumbnail.startAnimation(
2563 getPendingTransaction(), thumbnailAdapter, !isVisible());
2564 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002565 }
2566 } else {
2567 cancelAnimation();
2568 }
2569 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2570
2571 return isReallyAnimating();
2572 }
2573
2574 private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
2575 boolean isVoiceInteraction) {
2576 final DisplayContent displayContent = getTask().getDisplayContent();
2577 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2578 final int width = displayInfo.appWidth;
2579 final int height = displayInfo.appHeight;
2580 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG_WM,
2581 "applyAnimation: atoken=" + this);
2582
2583 // Determine the visible rect to calculate the thumbnail clip
2584 final WindowState win = findMainWindow();
2585 final Rect frame = new Rect(0, 0, width, height);
2586 final Rect displayFrame = new Rect(0, 0,
2587 displayInfo.logicalWidth, displayInfo.logicalHeight);
2588 final Rect insets = new Rect();
2589 final Rect stableInsets = new Rect();
2590 Rect surfaceInsets = null;
2591 final boolean freeform = win != null && win.inFreeformWindowingMode();
2592 if (win != null) {
2593 // Containing frame will usually cover the whole screen, including dialog windows.
2594 // For freeform workspace windows it will not cover the whole screen and it also
2595 // won't exactly match the final freeform window frame (e.g. when overlapping with
2596 // the status bar). In that case we need to use the final frame.
2597 if (freeform) {
chaviw492139a2018-07-16 16:07:35 -07002598 frame.set(win.getFrameLw());
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002599 } else if (win.isLetterboxedAppWindow()) {
2600 frame.set(getTask().getBounds());
Winson Chungc1674272018-02-21 10:15:17 -08002601 } else if (win.isDockedResizing()) {
2602 // If we are animating while docked resizing, then use the stack bounds as the
2603 // animation target (which will be different than the task bounds)
2604 frame.set(getTask().getParent().getBounds());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002605 } else {
chaviw553b0212018-07-12 13:37:01 -07002606 frame.set(win.getContainingFrame());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002607 }
2608 surfaceInsets = win.getAttrs().surfaceInsets;
Adrian Roos20e07892018-02-23 19:12:01 +01002609 // XXX(b/72757033): These are insets relative to the window frame, but we're really
2610 // interested in the insets relative to the frame we chose in the if-blocks above.
chaviw9c81e632018-07-31 11:17:52 -07002611 win.getContentInsets(insets);
2612 win.getStableInsets(stableInsets);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002613 }
2614
2615 if (mLaunchTaskBehind) {
2616 // Differentiate the two animations. This one which is briefly on the screen
2617 // gets the !enter animation, and the other activity which remains on the
2618 // screen gets the enter animation. Both appear in the mOpeningApps set.
2619 enter = false;
2620 }
2621 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "Loading animation for app transition."
2622 + " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter
2623 + " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets);
2624 final Configuration displayConfig = displayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08002625 final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002626 displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
2627 surfaceInsets, stableInsets, isVoiceInteraction, freeform, getTask().mTaskId);
2628 if (a != null) {
2629 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
2630 final int containingWidth = frame.width();
2631 final int containingHeight = frame.height();
2632 a.initialize(containingWidth, containingHeight, width, height);
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002633 a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002634 }
2635 return a;
2636 }
2637
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002638 @Override
Jorim Jaggi6de61012018-03-19 14:53:23 +01002639 public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
2640 return mAnimatingAppWindowTokenRegistry != null
2641 && mAnimatingAppWindowTokenRegistry.notifyAboutToFinish(
2642 this, endDeferFinishCallback);
2643 }
2644
2645 @Override
2646 public void onAnimationLeashDestroyed(Transaction t) {
2647 super.onAnimationLeashDestroyed(t);
Vishnu Naira2977262018-07-26 13:31:26 -07002648 if (mAnimationBoundsLayer != null) {
Robert Carr71200f22019-02-05 09:44:53 -08002649 t.remove(mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002650 mAnimationBoundsLayer = null;
2651 }
2652
Jorim Jaggi6de61012018-03-19 14:53:23 +01002653 if (mAnimatingAppWindowTokenRegistry != null) {
2654 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
2655 }
2656 }
2657
2658 @Override
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002659 protected void setLayer(Transaction t, int layer) {
2660 if (!mSurfaceAnimator.hasLeash()) {
2661 t.setLayer(mSurfaceControl, layer);
2662 }
2663 }
2664
2665 @Override
2666 protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
2667 if (!mSurfaceAnimator.hasLeash()) {
2668 t.setRelativeLayer(mSurfaceControl, relativeTo, layer);
2669 }
2670 }
2671
2672 @Override
2673 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
2674 if (!mSurfaceAnimator.hasLeash()) {
Robert Carr10584fa2019-01-14 15:55:19 -08002675 t.reparent(mSurfaceControl, newParent);
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002676 }
2677 }
2678
2679 @Override
2680 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002681 // The leash is parented to the animation layer. We need to preserve the z-order by using
2682 // the prefix order index, but we boost if necessary.
Robert Carrb9506032018-02-13 13:54:00 -08002683 int layer = 0;
2684 if (!inPinnedWindowingMode()) {
2685 layer = getPrefixOrderIndex();
2686 } else {
2687 // Pinned stacks have animations take place within themselves rather than an animation
2688 // layer so we need to preserve the order relative to the stack (e.g. the order of our
2689 // task/parent).
2690 layer = getParent().getPrefixOrderIndex();
2691 }
2692
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002693 if (mNeedsZBoost) {
2694 layer += Z_BOOST_BASE;
2695 }
Jorim Jaggi9cd99132019-04-24 17:41:35 +02002696 if (!mNeedsAnimationBoundsLayer) {
2697 leash.setLayer(layer);
2698 }
Robert Carr2f8aa392018-01-31 14:46:51 -08002699
2700 final DisplayContent dc = getDisplayContent();
Jorim Jaggibe418292018-03-26 16:14:12 +02002701 dc.assignStackOrdering();
Evan Rosky2289ba12018-11-19 18:28:18 -08002702
2703 if (leash == mTransitChangeLeash) {
2704 // This is a temporary state so skip any animation notifications
2705 return;
2706 } else if (mTransitChangeLeash != null) {
2707 // unparent mTransitChangeLeash for clean-up
Evan Rosky25b56192019-02-06 16:10:56 -08002708 clearChangeLeash(t, false /* cancel */);
Evan Rosky2289ba12018-11-19 18:28:18 -08002709 }
2710
Jorim Jaggi6de61012018-03-19 14:53:23 +01002711 if (mAnimatingAppWindowTokenRegistry != null) {
2712 mAnimatingAppWindowTokenRegistry.notifyStarting(this);
2713 }
Vishnu Naira2977262018-07-26 13:31:26 -07002714
2715 // If the animation needs to be cropped then an animation bounds layer is created as a child
2716 // of the pinned stack or animation layer. The leash is then reparented to this new layer.
2717 if (mNeedsAnimationBoundsLayer) {
Evan Rosky7735d352019-03-18 17:27:27 -07002718 mTmpRect.setEmpty();
2719 final Task task = getTask();
2720 if (getDisplayContent().mAppTransitionController.isTransitWithinTask(
2721 getTransit(), task)) {
2722 task.getBounds(mTmpRect);
2723 } else {
2724 final TaskStack stack = getStack();
2725 if (stack == null) {
2726 return;
2727 }
2728 // Set clip rect to stack bounds.
2729 stack.getBounds(mTmpRect);
Vishnu Naira2977262018-07-26 13:31:26 -07002730 }
2731 mAnimationBoundsLayer = createAnimationBoundsLayer(t);
2732
Vishnu Naira2977262018-07-26 13:31:26 -07002733 // Crop to stack bounds.
2734 t.setWindowCrop(mAnimationBoundsLayer, mTmpRect);
Jorim Jaggi9cd99132019-04-24 17:41:35 +02002735 t.setLayer(mAnimationBoundsLayer, layer);
Vishnu Naira2977262018-07-26 13:31:26 -07002736
2737 // Reparent leash to animation bounds layer.
Robert Carr10584fa2019-01-14 15:55:19 -08002738 t.reparent(leash, mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002739 }
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002740 }
2741
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002742 /**
2743 * This must be called while inside a transaction.
2744 */
2745 void showAllWindowsLocked() {
2746 forAllWindows(windowState -> {
2747 if (DEBUG_VISIBILITY) Slog.v(TAG, "performing show on: " + windowState);
2748 windowState.performShowLocked();
2749 }, false /* traverseTopToBottom */);
Jorim Jaggia5e10572017-11-15 14:36:26 +01002750 }
2751
2752 @Override
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002753 protected void onAnimationFinished() {
2754 super.onAnimationFinished();
2755
2756 mTransit = TRANSIT_UNSET;
2757 mTransitFlags = 0;
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002758 mNeedsZBoost = false;
Vishnu Naira2977262018-07-26 13:31:26 -07002759 mNeedsAnimationBoundsLayer = false;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002760
2761 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER,
2762 "AppWindowToken");
2763
Jorim Jaggi988f6682017-11-17 17:46:43 +01002764 clearThumbnail();
Jorim Jaggi752cd822018-03-29 16:29:18 +02002765 setClientHidden(isHidden() && hiddenRequested);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002766
lumarkff0ab692018-11-05 20:32:30 +08002767 getDisplayContent().computeImeTargetIfNeeded(this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002768
2769 if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + this
2770 + ": reportedVisible=" + reportedVisible
2771 + " okToDisplay=" + okToDisplay()
2772 + " okToAnimate=" + okToAnimate()
2773 + " startingDisplayed=" + startingDisplayed);
2774
Evan Rosky2289ba12018-11-19 18:28:18 -08002775 // clean up thumbnail window
2776 if (mThumbnail != null) {
2777 mThumbnail.destroy();
2778 mThumbnail = null;
2779 }
2780
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002781 // WindowState.onExitAnimationDone might modify the children list, so make a copy and then
2782 // traverse the copy.
2783 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
2784 children.forEach(WindowState::onExitAnimationDone);
2785
lumark588a3e82018-07-20 18:53:54 +08002786 getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002787 scheduleAnimation();
Jorim Jaggi9b5e3312019-03-01 18:08:00 +01002788
2789 mActivityRecord.onAnimationFinished();
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002790 }
2791
2792 @Override
2793 boolean isAppAnimating() {
2794 return isSelfAnimating();
2795 }
2796
2797 @Override
2798 boolean isSelfAnimating() {
2799 // If we are about to start a transition, we also need to be considered animating.
2800 return isWaitingForTransitionStart() || isReallyAnimating();
2801 }
2802
2803 /**
2804 * @return True if and only if we are actually running an animation. Note that
2805 * {@link #isSelfAnimating} also returns true if we are waiting for an animation to
2806 * start.
2807 */
2808 private boolean isReallyAnimating() {
2809 return super.isSelfAnimating();
2810 }
2811
Evan Rosky25b56192019-02-06 16:10:56 -08002812 /**
2813 * @param cancel {@code true} if clearing the leash due to cancelling instead of transferring
2814 * to another leash.
2815 */
2816 private void clearChangeLeash(Transaction t, boolean cancel) {
2817 if (mTransitChangeLeash == null) {
2818 return;
2819 }
2820 if (cancel) {
2821 clearThumbnail();
2822 SurfaceControl sc = getSurfaceControl();
2823 SurfaceControl parentSc = getParentSurfaceControl();
2824 // Don't reparent if surface is getting destroyed
2825 if (parentSc != null && sc != null) {
2826 t.reparent(sc, getParentSurfaceControl());
2827 }
2828 }
2829 t.hide(mTransitChangeLeash);
2830 t.reparent(mTransitChangeLeash, null);
2831 mTransitChangeLeash = null;
2832 if (cancel) {
2833 onAnimationLeashDestroyed(t);
2834 }
2835 }
2836
Jorim Jaggi988f6682017-11-17 17:46:43 +01002837 @Override
2838 void cancelAnimation() {
Evan Rosky2289ba12018-11-19 18:28:18 -08002839 cancelAnimationOnly();
Jorim Jaggi988f6682017-11-17 17:46:43 +01002840 clearThumbnail();
Evan Rosky25b56192019-02-06 16:10:56 -08002841 clearChangeLeash(getPendingTransaction(), true /* cancel */);
Evan Rosky2289ba12018-11-19 18:28:18 -08002842 }
2843
2844 /**
2845 * This only cancels the animation. It doesn't do other teardown like cleaning-up thumbnail
2846 * or interim leashes.
2847 * <p>
2848 * Used when canceling in preparation for starting a new animation.
2849 */
2850 void cancelAnimationOnly() {
2851 super.cancelAnimation();
Jorim Jaggi988f6682017-11-17 17:46:43 +01002852 }
2853
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002854 boolean isWaitingForTransitionStart() {
lumark588a3e82018-07-20 18:53:54 +08002855 return getDisplayContent().mAppTransition.isTransitionSet()
2856 && (getDisplayContent().mOpeningApps.contains(this)
Evan Rosky2289ba12018-11-19 18:28:18 -08002857 || getDisplayContent().mClosingApps.contains(this)
2858 || getDisplayContent().mChangingApps.contains(this));
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002859 }
2860
2861 public int getTransit() {
2862 return mTransit;
2863 }
2864
2865 int getTransitFlags() {
2866 return mTransitFlags;
2867 }
2868
Jorim Jaggi988f6682017-11-17 17:46:43 +01002869 void attachThumbnailAnimation() {
2870 if (!isReallyAnimating()) {
2871 return;
2872 }
2873 final int taskId = getTask().mTaskId;
2874 final GraphicBuffer thumbnailHeader =
lumark588a3e82018-07-20 18:53:54 +08002875 getDisplayContent().mAppTransition.getAppTransitionThumbnailHeader(taskId);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002876 if (thumbnailHeader == null) {
2877 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG, "No thumbnail header bitmap for: " + taskId);
2878 return;
2879 }
2880 clearThumbnail();
2881 mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnailHeader);
2882 mThumbnail.startAnimation(getPendingTransaction(), loadThumbnailAnimation(thumbnailHeader));
2883 }
2884
Tony Mak64b8d562017-12-28 17:44:02 +00002885 /**
2886 * Attaches a surface with a thumbnail for the
2887 * {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation.
2888 */
2889 void attachCrossProfileAppsThumbnailAnimation() {
2890 if (!isReallyAnimating()) {
2891 return;
2892 }
2893 clearThumbnail();
2894
2895 final WindowState win = findMainWindow();
2896 if (win == null) {
2897 return;
2898 }
chaviw492139a2018-07-16 16:07:35 -07002899 final Rect frame = win.getFrameLw();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002900 final int thumbnailDrawableRes = getTask().mUserId == mWmService.mCurrentUserId
Tony Mak64b8d562017-12-28 17:44:02 +00002901 ? R.drawable.ic_account_circle
Tony Makda4af232018-04-27 11:01:10 +01002902 : R.drawable.ic_corp_badge;
Tony Mak64b8d562017-12-28 17:44:02 +00002903 final GraphicBuffer thumbnail =
lumark588a3e82018-07-20 18:53:54 +08002904 getDisplayContent().mAppTransition
Tony Mak64b8d562017-12-28 17:44:02 +00002905 .createCrossProfileAppsThumbnail(thumbnailDrawableRes, frame);
2906 if (thumbnail == null) {
2907 return;
2908 }
2909 mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnail);
2910 final Animation animation =
lumark588a3e82018-07-20 18:53:54 +08002911 getDisplayContent().mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(
chaviw492139a2018-07-16 16:07:35 -07002912 win.getFrameLw());
Tony Mak64b8d562017-12-28 17:44:02 +00002913 mThumbnail.startAnimation(getPendingTransaction(), animation, new Point(frame.left,
2914 frame.top));
2915 }
2916
Jorim Jaggi988f6682017-11-17 17:46:43 +01002917 private Animation loadThumbnailAnimation(GraphicBuffer thumbnailHeader) {
2918 final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
2919
2920 // If this is a multi-window scenario, we use the windows frame as
2921 // destination of the thumbnail header animation. If this is a full screen
2922 // window scenario, we use the whole display as the target.
2923 WindowState win = findMainWindow();
2924 Rect appRect = win != null ? win.getContentFrameLw() :
2925 new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
chaviw9c81e632018-07-31 11:17:52 -07002926 final Rect insets = win != null ? win.getContentInsets() : null;
Jorim Jaggi988f6682017-11-17 17:46:43 +01002927 final Configuration displayConfig = mDisplayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08002928 return getDisplayContent().mAppTransition.createThumbnailAspectScaleAnimationLocked(
Jorim Jaggi988f6682017-11-17 17:46:43 +01002929 appRect, insets, thumbnailHeader, getTask().mTaskId, displayConfig.uiMode,
2930 displayConfig.orientation);
2931 }
2932
2933 private void clearThumbnail() {
2934 if (mThumbnail == null) {
2935 return;
2936 }
2937 mThumbnail.destroy();
2938 mThumbnail = null;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002939 }
2940
Jorim Jaggif84e2f62018-01-16 14:17:59 +01002941 void registerRemoteAnimations(RemoteAnimationDefinition definition) {
2942 mRemoteAnimationDefinition = definition;
2943 }
2944
2945 RemoteAnimationDefinition getRemoteAnimationDefinition() {
2946 return mRemoteAnimationDefinition;
2947 }
2948
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002949 @Override
2950 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
2951 super.dump(pw, prefix, dumpAll);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002952 if (appToken != null) {
Wale Ogunwale72919d22016-12-08 18:58:50 -08002953 pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002954 }
Winson Chung48b25652018-10-22 14:04:30 -07002955 pw.println(prefix + "component=" + mActivityComponent.flattenToShortString());
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08002956 pw.print(prefix); pw.print("task="); pw.println(getTask());
Wale Ogunwale51362492016-09-08 17:49:17 -07002957 pw.print(prefix); pw.print(" mFillsParent="); pw.print(mFillsParent);
2958 pw.print(" mOrientation="); pw.println(mOrientation);
Wale Ogunwale89973222017-04-23 18:39:45 -07002959 pw.println(prefix + "hiddenRequested=" + hiddenRequested + " mClientHidden=" + mClientHidden
2960 + ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "")
2961 + " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible);
Craig Mautner59431632012-04-04 11:56:44 -07002962 if (paused) {
2963 pw.print(prefix); pw.print("paused="); pw.println(paused);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002964 }
Wale Ogunwale9017ec02016-02-25 08:55:25 -08002965 if (mAppStopped) {
2966 pw.print(prefix); pw.print("mAppStopped="); pw.println(mAppStopped);
2967 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002968 if (mNumInterestingWindows != 0 || mNumDrawnWindows != 0
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002969 || allDrawn || mLastAllDrawn) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002970 pw.print(prefix); pw.print("mNumInterestingWindows=");
2971 pw.print(mNumInterestingWindows);
2972 pw.print(" mNumDrawnWindows="); pw.print(mNumDrawnWindows);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002973 pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
Craig Mautner6fbda632012-07-03 09:26:39 -07002974 pw.print(" allDrawn="); pw.print(allDrawn);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002975 pw.print(" lastAllDrawn="); pw.print(mLastAllDrawn);
Craig Mautner6fbda632012-07-03 09:26:39 -07002976 pw.println(")");
2977 }
2978 if (inPendingTransaction) {
2979 pw.print(prefix); pw.print("inPendingTransaction=");
2980 pw.println(inPendingTransaction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002981 }
Craig Mautner799bc1d2015-01-14 10:33:48 -08002982 if (startingData != null || removed || firstWindowDrawn || mIsExiting) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002983 pw.print(prefix); pw.print("startingData="); pw.print(startingData);
2984 pw.print(" removed="); pw.print(removed);
Craig Mautner3d7ca312015-01-08 10:56:00 -08002985 pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
Craig Mautner799bc1d2015-01-14 10:33:48 -08002986 pw.print(" mIsExiting="); pw.println(mIsExiting);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002987 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08002988 if (startingWindow != null || startingSurface != null
Wale Ogunwale6c459212017-05-17 08:56:03 -07002989 || startingDisplayed || startingMoved || mHiddenSetFromTransferredStartingWindow) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002990 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08002991 pw.print(" startingSurface="); pw.print(startingSurface);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002992 pw.print(" startingDisplayed="); pw.print(startingDisplayed);
Wale Ogunwale6c459212017-05-17 08:56:03 -07002993 pw.print(" startingMoved="); pw.print(startingMoved);
2994 pw.println(" mHiddenSetFromTransferredStartingWindow="
2995 + mHiddenSetFromTransferredStartingWindow);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002996 }
Jorim Jaggi0429f352015-12-22 16:29:16 +01002997 if (!mFrozenBounds.isEmpty()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08002998 pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
Jorim Jaggi26c8c422016-05-09 19:57:25 -07002999 pw.print(prefix); pw.print("mFrozenMergedConfig="); pw.println(mFrozenMergedConfig);
Chong Zhangd78ddb42016-03-02 17:01:14 -08003000 }
3001 if (mPendingRelaunchCount != 0) {
3002 pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount);
Jorim Jaggi0429f352015-12-22 16:29:16 +01003003 }
Riddle Hsub398da32019-01-21 21:48:16 +08003004 if (mSizeCompatScale != 1f || mSizeCompatBounds != null) {
3005 pw.println(prefix + "mSizeCompatScale=" + mSizeCompatScale + " mSizeCompatBounds="
3006 + mSizeCompatBounds);
3007 }
Wale Ogunwalee287e192017-04-21 09:30:12 -07003008 if (mRemovingFromDisplay) {
3009 pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay);
3010 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003011 }
3012
3013 @Override
3014 void setHidden(boolean hidden) {
3015 super.setHidden(hidden);
Winson Chunge55c0192017-08-24 14:50:48 -07003016
3017 if (hidden) {
3018 // Once the app window is hidden, reset the last saved PiP snap fraction
3019 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(this);
3020 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003021 scheduleAnimation();
3022 }
3023
3024 @Override
3025 void prepareSurfaces() {
3026 // isSelfAnimating also returns true when we are about to start a transition, so we need
3027 // to check super here.
3028 final boolean reallyAnimating = super.isSelfAnimating();
3029 final boolean show = !isHidden() || reallyAnimating;
Robert Carrd8e4fb72019-01-31 11:14:30 -08003030
3031 if (mSurfaceControl != null) {
3032 if (show && !mLastSurfaceShowing) {
3033 mPendingTransaction.show(mSurfaceControl);
3034 } else if (!show && mLastSurfaceShowing) {
3035 mPendingTransaction.hide(mSurfaceControl);
3036 }
Jorim Jaggi4d1835d2017-08-31 17:28:27 +02003037 }
Jorim Jaggi988f6682017-11-17 17:46:43 +01003038 if (mThumbnail != null) {
3039 mThumbnail.setShowing(mPendingTransaction, show);
3040 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003041 mLastSurfaceShowing = show;
3042 super.prepareSurfaces();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003043 }
3044
Jorim Jaggi77d0f36c2018-03-16 17:49:49 +01003045 /**
3046 * @return Whether our {@link #getSurfaceControl} is currently showing.
3047 */
3048 boolean isSurfaceShowing() {
3049 return mLastSurfaceShowing;
3050 }
3051
Jorim Jaggib0fc8172017-11-23 17:04:08 +00003052 boolean isFreezingScreen() {
3053 return mFreezingScreen;
3054 }
3055
3056 @Override
3057 boolean needsZBoost() {
3058 return mNeedsZBoost || super.needsZBoost();
3059 }
3060
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07003061 @CallSuper
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003062 @Override
Nataniel Borges023ecb52019-01-16 14:15:43 -08003063 public void writeToProto(ProtoOutputStream proto, long fieldId,
3064 @WindowTraceLogLevel int logLevel) {
3065 // Critical log level logs only visible elements to mitigate performance overheard
3066 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
3067 return;
3068 }
3069
Steven Timotiusaf03df62017-07-18 16:56:43 -07003070 final long token = proto.start(fieldId);
3071 writeNameToProto(proto, NAME);
Nataniel Borges023ecb52019-01-16 14:15:43 -08003072 super.writeToProto(proto, WINDOW_TOKEN, logLevel);
Vishnu Nair04ab4392018-01-10 11:00:06 -08003073 proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing);
3074 proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart());
3075 proto.write(IS_REALLY_ANIMATING, isReallyAnimating());
3076 if (mThumbnail != null){
3077 mThumbnail.writeToProto(proto, THUMBNAIL);
3078 }
3079 proto.write(FILLS_PARENT, mFillsParent);
3080 proto.write(APP_STOPPED, mAppStopped);
3081 proto.write(HIDDEN_REQUESTED, hiddenRequested);
3082 proto.write(CLIENT_HIDDEN, mClientHidden);
3083 proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient);
3084 proto.write(REPORTED_DRAWN, reportedDrawn);
3085 proto.write(REPORTED_VISIBLE, reportedVisible);
3086 proto.write(NUM_INTERESTING_WINDOWS, mNumInterestingWindows);
3087 proto.write(NUM_DRAWN_WINDOWS, mNumDrawnWindows);
3088 proto.write(ALL_DRAWN, allDrawn);
3089 proto.write(LAST_ALL_DRAWN, mLastAllDrawn);
3090 proto.write(REMOVED, removed);
Nataniel Borges023ecb52019-01-16 14:15:43 -08003091 if (startingWindow != null) {
Vishnu Nair04ab4392018-01-10 11:00:06 -08003092 startingWindow.writeIdentifierToProto(proto, STARTING_WINDOW);
3093 }
3094 proto.write(STARTING_DISPLAYED, startingDisplayed);
3095 proto.write(STARTING_MOVED, startingMoved);
3096 proto.write(HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW,
3097 mHiddenSetFromTransferredStartingWindow);
3098 for (Rect bounds : mFrozenBounds) {
3099 bounds.writeToProto(proto, FROZEN_BOUNDS);
3100 }
Steven Timotiusaf03df62017-07-18 16:56:43 -07003101 proto.end(token);
3102 }
3103
3104 void writeNameToProto(ProtoOutputStream proto, long fieldId) {
3105 if (appToken == null) {
3106 return;
3107 }
3108 try {
3109 proto.write(fieldId, appToken.getName());
3110 } catch (RemoteException e) {
3111 // This shouldn't happen, but in this case fall back to outputting nothing
3112 Slog.e(TAG, e.toString());
3113 }
3114 }
3115
3116 @Override
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003117 public String toString() {
3118 if (stringName == null) {
3119 StringBuilder sb = new StringBuilder();
3120 sb.append("AppWindowToken{");
3121 sb.append(Integer.toHexString(System.identityHashCode(this)));
3122 sb.append(" token="); sb.append(token); sb.append('}');
3123 stringName = sb.toString();
3124 }
Wale Ogunwaleba51ca22016-09-23 06:06:54 -07003125 return stringName + ((mIsExiting) ? " mIsExiting=" : "");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003126 }
Adrian Roos20e07892018-02-23 19:12:01 +01003127
3128 Rect getLetterboxInsets() {
3129 if (mLetterbox != null) {
3130 return mLetterbox.getInsets();
3131 } else {
3132 return new Rect();
3133 }
3134 }
Adrian Roos23df3a32018-03-15 15:41:13 +01003135
Riddle Hsu69de5fb2019-02-23 01:19:50 +08003136 /** Gets the inner bounds of letterbox. The bounds will be empty if there is no letterbox. */
3137 void getLetterboxInnerBounds(Rect outBounds) {
3138 if (mLetterbox != null) {
3139 outBounds.set(mLetterbox.getInnerFrame());
3140 } else {
3141 outBounds.setEmpty();
3142 }
3143 }
3144
Adrian Roos23df3a32018-03-15 15:41:13 +01003145 /**
Riddle Hsu69de5fb2019-02-23 01:19:50 +08003146 * @return {@code true} if there is a letterbox and any part of that letterbox overlaps with
Adrian Roos23df3a32018-03-15 15:41:13 +01003147 * the given {@code rect}.
3148 */
3149 boolean isLetterboxOverlappingWith(Rect rect) {
3150 return mLetterbox != null && mLetterbox.isOverlappingWith(rect);
3151 }
chaviw4ad54912018-05-30 11:05:44 -07003152
3153 /**
3154 * Sets if this AWT is in the process of closing or entering PIP.
3155 * {@link #mWillCloseOrEnterPip}}
3156 */
3157 void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
3158 mWillCloseOrEnterPip = willCloseOrEnterPip;
3159 }
3160
3161 /**
3162 * Returns whether this AWT is considered closing. Conditions are either
3163 * 1. Is this app animating and was requested to be hidden
3164 * 2. App is delayed closing since it might enter PIP.
3165 */
3166 boolean isClosingOrEnteringPip() {
3167 return (isAnimating() && hiddenRequested) || mWillCloseOrEnterPip;
3168 }
Jorim Jaggiaf0d6d22018-06-08 15:25:35 +02003169
3170 /**
3171 * @return Whether we are allowed to show non-starting windows at the moment. We disallow
3172 * showing windows during transitions in case we have windows that have wide-color-gamut
3173 * color mode set to avoid jank in the middle of the transition.
3174 */
3175 boolean canShowWindows() {
3176 return allDrawn && !(isReallyAnimating() && hasNonDefaultColorWindow());
3177 }
3178
3179 /**
3180 * @return true if we have a window that has a non-default color mode set; false otherwise.
3181 */
3182 private boolean hasNonDefaultColorWindow() {
3183 return forAllWindows(ws -> ws.mAttrs.getColorMode() != COLOR_MODE_DEFAULT,
3184 true /* topToBottom */);
3185 }
lumark588a3e82018-07-20 18:53:54 +08003186
3187 void removeFromPendingTransition() {
3188 if (isWaitingForTransitionStart() && mDisplayContent != null) {
3189 mDisplayContent.mOpeningApps.remove(this);
Evan Rosky25b56192019-02-06 16:10:56 -08003190 if (mDisplayContent.mChangingApps.remove(this)) {
3191 clearChangeLeash(getPendingTransaction(), true /* cancel */);
3192 }
lumark588a3e82018-07-20 18:53:54 +08003193 mDisplayContent.mClosingApps.remove(this);
3194 }
3195 }
chaviwdcf76ec2019-01-11 16:48:46 -08003196
3197 private void updateColorTransform() {
3198 if (mSurfaceControl != null && mLastAppSaturationInfo != null) {
3199 mPendingTransaction.setColorTransform(mSurfaceControl, mLastAppSaturationInfo.mMatrix,
3200 mLastAppSaturationInfo.mTranslation);
3201 mWmService.scheduleAnimationLocked();
3202 }
3203 }
3204
3205 private static class AppSaturationInfo {
3206 float[] mMatrix = new float[9];
3207 float[] mTranslation = new float[3];
3208
3209 void setSaturation(@Size(9) float[] matrix, @Size(3) float[] translation) {
3210 System.arraycopy(matrix, 0, mMatrix, 0, mMatrix.length);
3211 System.arraycopy(translation, 0, mTranslation, 0, mTranslation.length);
3212 }
3213 }
Jeff Browne9bdb312012-04-05 15:30:10 -07003214}