blob: 004c39d7c033ddf1f96cdfacc1caae51ffda33c9 [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 */
147 private static final int Z_BOOST_BASE = 800570000;
148
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;
Craig Mautner4c5eb222013-11-18 12:59:05 -0800156 boolean layoutConfigChanges;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800157 boolean mShowForAllUsers;
158 int mTargetSdk;
Craig Mautnera2c77052012-03-26 12:14:43 -0700159
Bryce Lee6d410262017-02-28 15:30:17 -0800160 // Flag set while reparenting to prevent actions normally triggered by an individual parent
161 // change.
162 private boolean mReparenting;
163
Wale Ogunwalee287e192017-04-21 09:30:12 -0700164 // True if we are current in the process of removing this app token from the display
165 private boolean mRemovingFromDisplay = false;
166
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800167 // The input dispatching timeout for this application token in nanoseconds.
Wale Ogunwale72919d22016-12-08 18:58:50 -0800168 long mInputDispatchingTimeoutNanos;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800169
170 // These are used for determining when all windows associated with
171 // an activity have been drawn, so they can be made visible together
172 // at the same time.
Craig Mautner764983d2012-03-22 11:37:36 -0700173 // initialize so that it doesn't match mTransactionSequence which is an int.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700174 private long mLastTransactionSequence = Long.MIN_VALUE;
175 private int mNumInterestingWindows;
176 private int mNumDrawnWindows;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800177 boolean inPendingTransaction;
178 boolean allDrawn;
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000179 private boolean mLastAllDrawn;
180
Craig Mautner7636dfb2012-11-16 15:24:11 -0800181 // Set to true when this app creates a surface while in the middle of an animation. In that
182 // case do not clear allDrawn until the animation completes.
183 boolean deferClearAllDrawn;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800184
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800185 // Is this window's surface needed? This is almost like hidden, except
186 // it will sometimes be true a little earlier: when the token has
187 // been shown, but is still waiting for its app transition to execute
188 // before making its windows shown.
189 boolean hiddenRequested;
190
191 // Have we told the window clients to hide themselves?
Wale Ogunwale89973222017-04-23 18:39:45 -0700192 private boolean mClientHidden;
193
194 // If true we will defer setting mClientHidden to true and reporting to the client that it is
195 // hidden.
196 boolean mDeferHidingClient;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800197
198 // Last visibility state we reported to the app token.
199 boolean reportedVisible;
200
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700201 // Last drawn state we reported to the app token.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700202 private boolean reportedDrawn;
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700203
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800204 // Set to true when the token has been removed from the window mgr.
205 boolean removed;
206
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800207 // Information about an application starting window if displayed.
208 StartingData startingData;
209 WindowState startingWindow;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800210 StartingSurface startingSurface;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800211 boolean startingDisplayed;
212 boolean startingMoved;
Jorim Jaggi60f9c972018-02-01 19:21:07 +0100213
Wale Ogunwale6c459212017-05-17 08:56:03 -0700214 // True if the hidden state of this token was forced to false due to a transferred starting
215 // window.
216 private boolean mHiddenSetFromTransferredStartingWindow;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800217 boolean firstWindowDrawn;
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700218 private final WindowState.UpdateReportedVisibilityResults mReportedVisibilityResults =
219 new WindowState.UpdateReportedVisibilityResults();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800220
221 // Input application handle used by the input dispatcher.
Jeff Brown9302c872011-07-13 22:51:29 -0700222 final InputApplicationHandle mInputApplicationHandle;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800223
Wale Ogunwale571771c2016-08-26 13:18:50 -0700224 // TODO: Have a WindowContainer state for tracking exiting/deferred removal.
Craig Mautner799bc1d2015-01-14 10:33:48 -0800225 boolean mIsExiting;
Craig Mautner9ef471f2014-02-07 13:11:47 -0800226
Craig Mautnerbb742462014-07-07 15:28:55 -0700227 boolean mLaunchTaskBehind;
Craig Mautner8746a472014-07-24 15:12:54 -0700228 boolean mEnteringAnimation;
Craig Mautnerbb742462014-07-07 15:28:55 -0700229
Wale Ogunwale72919d22016-12-08 18:58:50 -0800230 private boolean mAlwaysFocusable;
Wale Ogunwale6cae7652015-12-26 07:36:26 -0800231
Robert Carre12aece2016-02-02 22:43:27 -0800232 boolean mAppStopped;
Robert Carrfd10cd12016-06-29 16:41:50 -0700233 int mRotationAnimationHint;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700234 private int mPendingRelaunchCount;
Robert Carre12aece2016-02-02 22:43:27 -0800235
Jorim Jaggife762342016-10-13 14:33:27 +0200236 private boolean mLastContainsShowWhenLockedWindow;
237 private boolean mLastContainsDismissKeyguardWindow;
238
Jorim Jaggi0429f352015-12-22 16:29:16 +0100239 ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
Jorim Jaggi26c8c422016-05-09 19:57:25 -0700240 ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
Jorim Jaggi0429f352015-12-22 16:29:16 +0100241
Riddle Hsub398da32019-01-21 21:48:16 +0800242 /**
243 * The scale to fit at least one side of the activity to its parent. If the activity uses
244 * 1920x1080, and the actually size on the screen is 960x540, then the scale is 0.5.
245 */
246 private float mSizeCompatScale = 1f;
247 /**
248 * The bounds in global coordinates for activity in size compatibility mode.
249 * @see ActivityRecord#inSizeCompatMode
250 */
251 private Rect mSizeCompatBounds;
252
Wale Ogunwale6c459212017-05-17 08:56:03 -0700253 private boolean mDisablePreviewScreenshots;
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +0100254
Wale Ogunwale034a8ec2017-09-02 17:14:40 -0700255 private Task mLastParent;
Robert Carred3e83b2017-04-21 13:26:55 -0700256
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800257 // TODO: Remove after unification
258 ActivityRecord mActivityRecord;
259
chaviwd3bf08d2017-08-01 17:24:59 -0700260 /**
261 * See {@link #canTurnScreenOn()}
262 */
263 private boolean mCanTurnScreenOn = true;
264
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200265 /**
266 * If we are running an animation, this determines the transition type. Must be one of
267 * AppTransition.TRANSIT_* constants.
268 */
269 private int mTransit;
270
271 /**
272 * If we are running an animation, this determines the flags during this animation. Must be a
273 * bitwise combination of AppTransition.TRANSIT_FLAG_* constants.
274 */
275 private int mTransitFlags;
276
277 /** Whether our surface was set to be showing in the last call to {@link #prepareSurfaces} */
Jorim Jaggifd1891462017-12-29 15:41:36 +0100278 private boolean mLastSurfaceShowing = true;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200279
Evan Rosky2289ba12018-11-19 18:28:18 -0800280 /**
281 * This gets used during some open/close transitions as well as during a change transition
282 * where it represents the starting-state snapshot.
283 */
Jorim Jaggi988f6682017-11-17 17:46:43 +0100284 private AppWindowThumbnail mThumbnail;
Evan Rosky2289ba12018-11-19 18:28:18 -0800285 private final Rect mTransitStartRect = new Rect();
286
287 /**
288 * This leash is used to "freeze" the app surface in place after the state change, but before
289 * the animation is ready to start.
290 */
291 private SurfaceControl mTransitChangeLeash = null;
Jorim Jaggi988f6682017-11-17 17:46:43 +0100292
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000293 /** Have we been asked to have this token keep the screen frozen? */
294 private boolean mFreezingScreen;
295
296 /** Whether this token should be boosted at the top of all app window tokens. */
297 private boolean mNeedsZBoost;
Adrian Roos4d18a2e2017-12-19 19:08:05 +0100298 private Letterbox mLetterbox;
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000299
chaviw23ee71c2017-12-18 11:29:41 -0800300 private final Point mTmpPoint = new Point();
chaviw23012112017-12-20 15:29:04 -0800301 private final Rect mTmpRect = new Rect();
Evan Rosky2289ba12018-11-19 18:28:18 -0800302 private final Rect mTmpPrevBounds = new Rect();
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100303 private RemoteAnimationDefinition mRemoteAnimationDefinition;
Jorim Jaggi6de61012018-03-19 14:53:23 +0100304 private AnimatingAppWindowTokenRegistry mAnimatingAppWindowTokenRegistry;
chaviw23ee71c2017-12-18 11:29:41 -0800305
chaviw4ad54912018-05-30 11:05:44 -0700306 /**
307 * A flag to determine if this AWT is in the process of closing or entering PIP. This is needed
308 * to help AWT know that the app is in the process of closing but hasn't yet started closing on
309 * the WM side.
310 */
311 private boolean mWillCloseOrEnterPip;
312
Vishnu Naira2977262018-07-26 13:31:26 -0700313 /** Layer used to constrain the animation to a token's stack bounds. */
314 SurfaceControl mAnimationBoundsLayer;
315
316 /** Whether this token needs to create mAnimationBoundsLayer for cropping animations. */
317 boolean mNeedsAnimationBoundsLayer;
318
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800319 private static final int STARTING_WINDOW_TYPE_NONE = 0;
320 private static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
321 private static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
322
chaviwdcf76ec2019-01-11 16:48:46 -0800323 private AppSaturationInfo mLastAppSaturationInfo;
324
325 private final ColorDisplayService.ColorTransformController mColorTransformController =
326 (matrix, translation) -> mWmService.mH.post(() -> {
327 synchronized (mWmService.mGlobalLock) {
328 if (mLastAppSaturationInfo == null) {
329 mLastAppSaturationInfo = new AppSaturationInfo();
330 }
331
332 mLastAppSaturationInfo.setSaturation(matrix, translation);
333 updateColorTransform();
334 }
335 });
336
Winson Chung48b25652018-10-22 14:04:30 -0700337 AppWindowToken(WindowManagerService service, IApplicationToken token,
338 ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
339 long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers,
340 int targetSdk, int orientation, int rotationAnimationHint, int configChanges,
341 boolean launchTaskBehind, boolean alwaysFocusable,
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800342 ActivityRecord activityRecord) {
Winson Chung48b25652018-10-22 14:04:30 -0700343 this(service, token, activityComponent, voiceInteraction, dc, fullscreen);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800344 // TODO: remove after unification
345 mActivityRecord = activityRecord;
346 mActivityRecord.registerConfigurationChangeListener(this);
Wale Ogunwale72919d22016-12-08 18:58:50 -0800347 mInputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800348 mShowForAllUsers = showForAllUsers;
349 mTargetSdk = targetSdk;
350 mOrientation = orientation;
351 layoutConfigChanges = (configChanges & (CONFIG_SCREEN_SIZE | CONFIG_ORIENTATION)) != 0;
352 mLaunchTaskBehind = launchTaskBehind;
353 mAlwaysFocusable = alwaysFocusable;
354 mRotationAnimationHint = rotationAnimationHint;
355
356 // Application tokens start out hidden.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200357 setHidden(true);
Wale Ogunwale72919d22016-12-08 18:58:50 -0800358 hiddenRequested = true;
chaviwdcf76ec2019-01-11 16:48:46 -0800359
360 ColorDisplayService.ColorDisplayServiceInternal cds = LocalServices.getService(
361 ColorDisplayService.ColorDisplayServiceInternal.class);
362 cds.attachColorTransformController(activityRecord.packageName, activityRecord.mUserId,
363 new WeakReference<>(mColorTransformController));
Wale Ogunwale72919d22016-12-08 18:58:50 -0800364 }
365
Winson Chung48b25652018-10-22 14:04:30 -0700366 AppWindowToken(WindowManagerService service, IApplicationToken token,
367 ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
368 boolean fillsParent) {
Wale Ogunwale5cd907d2017-01-26 14:14:08 -0800369 super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true, dc,
370 false /* ownerCanManageAppTokens */);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700371 appToken = token;
Winson Chung48b25652018-10-22 14:04:30 -0700372 mActivityComponent = activityComponent;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800373 mVoiceInteraction = voiceInteraction;
Wale Ogunwale17f175c2017-02-07 16:54:10 -0800374 mFillsParent = fillsParent;
Robert Carr0bcbe642018-10-11 19:07:43 -0700375 mInputApplicationHandle = new InputApplicationHandle(appToken.asBinder());
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800376 }
377
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800378 void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
379 firstWindowDrawn = true;
380
381 // We now have a good window to show, remove dead placeholders
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700382 removeDeadWindows();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800383
Jorim Jaggi02886a82016-12-06 09:10:06 -0800384 if (startingWindow != null) {
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800385 if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Slog.v(TAG, "Finish starting "
386 + win.mToken + ": first real window is shown, no animation");
387 // If this initial window is animating, stop it -- we will do an animation to reveal
388 // it from behind the starting window, so there is no need for it to also be doing its
389 // own stuff.
Jorim Jaggia5e10572017-11-15 14:36:26 +0100390 win.cancelAnimation();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800391 removeStartingWindow();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800392 }
393 updateReportedVisibilityLocked();
394 }
395
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800396 void updateReportedVisibilityLocked() {
397 if (appToken == null) {
398 return;
399 }
400
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700401 if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700402 final int count = mChildren.size();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800403
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700404 mReportedVisibilityResults.reset();
405
406 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700407 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700408 win.updateReportedVisibility(mReportedVisibilityResults);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800409 }
410
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700411 int numInteresting = mReportedVisibilityResults.numInteresting;
412 int numVisible = mReportedVisibilityResults.numVisible;
413 int numDrawn = mReportedVisibilityResults.numDrawn;
414 boolean nowGone = mReportedVisibilityResults.nowGone;
415
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700416 boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200417 boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting && !isHidden();
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700418 if (!nowGone) {
419 // If the app is not yet gone, then it can only become visible/drawn.
420 if (!nowDrawn) {
421 nowDrawn = reportedDrawn;
422 }
423 if (!nowVisible) {
424 nowVisible = reportedVisible;
425 }
426 }
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800427 if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800428 + numInteresting + " visible=" + numVisible);
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700429 if (nowDrawn != reportedDrawn) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800430 if (mActivityRecord != null) {
431 mActivityRecord.onWindowsDrawn(nowDrawn, SystemClock.uptimeMillis());
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700432 }
433 reportedDrawn = nowDrawn;
434 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800435 if (nowVisible != reportedVisible) {
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700436 if (DEBUG_VISIBILITY) Slog.v(TAG,
437 "Visibility changed in " + this + ": vis=" + nowVisible);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800438 reportedVisible = nowVisible;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800439 if (mActivityRecord != null) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800440 if (nowVisible) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800441 onWindowsVisible();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800442 } else {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800443 onWindowsGone();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800444 }
445 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800446 }
447 }
448
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800449 private void onWindowsGone() {
450 if (mActivityRecord == null) {
451 return;
452 }
453 if (DEBUG_VISIBILITY) {
454 Slog.v(TAG_WM, "Reporting gone in " + mActivityRecord.appToken);
455 }
456 mActivityRecord.onWindowsGone();
457 }
458
459 private void onWindowsVisible() {
460 if (mActivityRecord == null) {
461 return;
462 }
463 if (DEBUG_VISIBILITY) {
464 Slog.v(TAG_WM, "Reporting visible in " + mActivityRecord.appToken);
465 }
466 mActivityRecord.onWindowsVisible();
467 }
468
Wale Ogunwale89973222017-04-23 18:39:45 -0700469 boolean isClientHidden() {
470 return mClientHidden;
471 }
472
473 void setClientHidden(boolean hideClient) {
474 if (mClientHidden == hideClient || (hideClient && mDeferHidingClient)) {
475 return;
476 }
Jorim Jaggi067b5bf2018-02-23 17:42:39 +0100477 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "setClientHidden: " + this
478 + " clientHidden=" + hideClient + " Callers=" + Debug.getCallers(5));
Wale Ogunwale89973222017-04-23 18:39:45 -0700479 mClientHidden = hideClient;
480 sendAppVisibilityToClients();
481 }
482
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800483 void setVisibility(boolean visible, boolean deferHidingClient) {
484 final AppTransition appTransition = getDisplayContent().mAppTransition;
485
486 // Don't set visibility to false if we were already not visible. This prevents WM from
487 // adding the app to the closing app list which doesn't make sense for something that is
488 // already not visible. However, set visibility to true even if we are already visible.
489 // This makes sure the app is added to the opening apps list so that the right
490 // transition can be selected.
491 // TODO: Probably a good idea to separate the concept of opening/closing apps from the
492 // concept of setting visibility...
493 if (!visible && hiddenRequested) {
494
495 if (!deferHidingClient && mDeferHidingClient) {
496 // We previously deferred telling the client to hide itself when visibility was
497 // initially set to false. Now we would like it to hide, so go ahead and set it.
498 mDeferHidingClient = deferHidingClient;
499 setClientHidden(true);
500 }
501 return;
502 }
503
504 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) {
505 Slog.v(TAG_WM, "setAppVisibility("
506 + appToken + ", visible=" + visible + "): " + appTransition
507 + " hidden=" + isHidden() + " hiddenRequested="
508 + hiddenRequested + " Callers=" + Debug.getCallers(6));
509 }
510
511 final DisplayContent displayContent = getDisplayContent();
512 displayContent.mOpeningApps.remove(this);
513 displayContent.mClosingApps.remove(this);
514 waitingToShow = false;
515 hiddenRequested = !visible;
516 mDeferHidingClient = deferHidingClient;
517
518 if (!visible) {
519 // If the app is dead while it was visible, we kept its dead window on screen.
520 // Now that the app is going invisible, we can remove it. It will be restarted
521 // if made visible again.
522 removeDeadWindows();
523 } else {
524 if (!appTransition.isTransitionSet()
525 && appTransition.isReady()) {
526 // Add the app mOpeningApps if transition is unset but ready. This means
527 // we're doing a screen freeze, and the unfreeze will wait for all opening
528 // apps to be ready.
529 displayContent.mOpeningApps.add(this);
530 }
531 startingMoved = false;
532 // If the token is currently hidden (should be the common case), or has been
533 // stopped, then we need to set up to wait for its windows to be ready.
534 if (isHidden() || mAppStopped) {
535 clearAllDrawn();
536
537 // If the app was already visible, don't reset the waitingToShow state.
538 if (isHidden()) {
539 waitingToShow = true;
540 }
541 }
542
543 // In the case where we are making an app visible but holding off for a transition,
544 // we still need to tell the client to make its windows visible so they get drawn.
545 // Otherwise, we will wait on performing the transition until all windows have been
546 // drawn, they never will be, and we are sad.
547 setClientHidden(false);
548
549 requestUpdateWallpaperIfNeeded();
550
551 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "No longer Stopped: " + this);
552 mAppStopped = false;
553
554 transferStartingWindowFromHiddenAboveTokenIfNeeded();
555 }
556
557 // If we are preparing an app transition, then delay changing
558 // the visibility of this token until we execute that transition.
559 if (okToAnimate() && appTransition.isTransitionSet()) {
560 inPendingTransaction = true;
561 if (visible) {
562 displayContent.mOpeningApps.add(this);
563 mEnteringAnimation = true;
564 } else {
565 displayContent.mClosingApps.add(this);
566 mEnteringAnimation = false;
567 }
568 if (appTransition.getAppTransition()
569 == WindowManager.TRANSIT_TASK_OPEN_BEHIND) {
570 // We're launchingBehind, add the launching activity to mOpeningApps.
571 final WindowState win = getDisplayContent().findFocusedWindow();
572 if (win != null) {
573 final AppWindowToken focusedToken = win.mAppToken;
574 if (focusedToken != null) {
575 if (DEBUG_APP_TRANSITIONS) {
576 Slog.d(TAG_WM, "TRANSIT_TASK_OPEN_BEHIND, "
577 + " adding " + focusedToken + " to mOpeningApps");
578 }
579 // Force animation to be loaded.
580 focusedToken.setHidden(true);
581 displayContent.mOpeningApps.add(focusedToken);
582 }
583 }
584 }
Garfield Tanb6776602019-02-20 14:44:26 -0800585 // Changes in opening apps and closing apps may cause orientation change.
586 reportDescendantOrientationChangeIfNeeded();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800587 return;
588 }
589
590 commitVisibility(null, visible, TRANSIT_UNSET, true, mVoiceInteraction);
591 updateReportedVisibilityLocked();
592 }
593
594 boolean commitVisibility(WindowManager.LayoutParams lp,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700595 boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
596
597 boolean delayed = false;
598 inPendingTransaction = false;
Wale Ogunwale9e4721f2017-05-23 19:37:30 -0700599 // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually
600 // been set by the app now.
601 mHiddenSetFromTransferredStartingWindow = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700602
603 // Allow for state changes and animation to be applied if:
604 // * token is transitioning visibility state
605 // * or the token was marked as hidden and is exiting before we had a chance to play the
606 // transition animation
607 // * or this is an opening app and windows are being replaced.
608 boolean visibilityChanged = false;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200609 if (isHidden() == visible || (isHidden() && mIsExiting) || (visible && waitingForReplacement())) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800610 final AccessibilityController accessibilityController =
611 mWmService.mAccessibilityController;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700612 boolean changed = false;
613 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM,
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200614 "Changing app " + this + " hidden=" + isHidden() + " performLayout=" + performLayout);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700615
616 boolean runningAppAnimation = false;
617
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100618 if (transit != WindowManager.TRANSIT_UNSET) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200619 if (applyAnimationLocked(lp, transit, visible, isVoiceInteraction)) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700620 delayed = runningAppAnimation = true;
621 }
622 final WindowState window = findMainWindow();
Rhed Jao02655dc2018-10-30 20:44:52 +0800623 if (window != null && accessibilityController != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700624 accessibilityController.onAppWindowTransitionLocked(window, transit);
625 }
626 changed = true;
627 }
628
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700629 final int windowsCount = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700630 for (int i = 0; i < windowsCount; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700631 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700632 changed |= win.onAppVisibilityChanged(visible, runningAppAnimation);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700633 }
634
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200635 setHidden(!visible);
636 hiddenRequested = !visible;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700637 visibilityChanged = true;
638 if (!visible) {
639 stopFreezingScreen(true, true);
640 } else {
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700641 // If we are being set visible, and the starting window is not yet displayed,
642 // then make sure it doesn't get displayed.
643 if (startingWindow != null && !startingWindow.isDrawnLw()) {
644 startingWindow.mPolicyVisibility = false;
645 startingWindow.mPolicyVisibilityAfterAnim = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700646 }
Jorim Jaggi38d44ec2017-06-14 16:04:59 -0700647
648 // We are becoming visible, so better freeze the screen with the windows that are
649 // getting visible so we also wait for them.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800650 forAllWindows(mWmService::makeWindowFreezingScreenIfNeededLocked, true);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700651 }
652
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800653 if (DEBUG_APP_TRANSITIONS) {
654 Slog.v(TAG_WM, "commitVisibility: " + this
655 + ": hidden=" + isHidden() + " hiddenRequested=" + hiddenRequested);
656 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700657
658 if (changed) {
Arthur Hung95b38a92018-07-20 18:56:12 +0800659 getDisplayContent().getInputMonitor().setUpdateInputWindowsNeededLw();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700660 if (performLayout) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800661 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700662 false /*updateInputWindows*/);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800663 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700664 }
Arthur Hung95b38a92018-07-20 18:56:12 +0800665 getDisplayContent().getInputMonitor().updateInputWindowsLw(false /*force*/);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700666 }
667 }
668
lumarkd14173e2019-03-27 19:14:33 +0800669 if (isReallyAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700670 delayed = true;
Jorim Jaggiab9fcb22018-03-15 23:46:12 +0100671 } else {
672
673 // We aren't animating anything, but exiting windows rely on the animation finished
674 // callback being called in case the AppWindowToken was pretending to be animating,
675 // which we might have done because we were in closing/opening apps list.
676 onAnimationFinished();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700677 }
678
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700679 for (int i = mChildren.size() - 1; i >= 0 && !delayed; i--) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100680 if ((mChildren.get(i)).isSelfOrChildAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700681 delayed = true;
682 }
683 }
684
685 if (visibilityChanged) {
686 if (visible && !delayed) {
687 // The token was made immediately visible, there will be no entrance animation.
688 // We need to inform the client the enter animation was finished.
689 mEnteringAnimation = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800690 mWmService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(
691 token);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700692 }
Robert Carr61b81112017-07-17 18:08:15 -0700693
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800694 // If we're becoming visible, immediately change client visibility as well. there seem
695 // to be some edge cases where we change our visibility but client visibility never gets
696 // updated.
Jorim Jaggi110839b2018-01-22 12:49:04 +0100697 // If we're becoming invisible, update the client visibility if we are not running an
698 // animation. Otherwise, we'll update client visibility in onAnimationFinished.
Jorim Jaggi3cad57f2018-02-20 18:32:01 +0100699 if (visible || !isReallyAnimating()) {
Jorim Jaggi110839b2018-01-22 12:49:04 +0100700 setClientHidden(!visible);
Jorim Jaggi4876b4a2018-01-11 15:43:49 +0100701 }
702
lumark588a3e82018-07-20 18:53:54 +0800703 if (!getDisplayContent().mClosingApps.contains(this)
704 && !getDisplayContent().mOpeningApps.contains(this)) {
chaviwa953fcf2018-03-01 12:00:39 -0800705 // The token is not closing nor opening, so even if there is an animation set, that
706 // doesn't mean that it goes through the normal app transition cycle so we have
707 // to inform the docked controller about visibility change.
708 // TODO(multi-display): notify docked divider on all displays where visibility was
709 // affected.
lumark588a3e82018-07-20 18:53:54 +0800710 getDisplayContent().getDockedDividerController().notifyAppVisibilityChanged();
chaviwa953fcf2018-03-01 12:00:39 -0800711
712 // Take the screenshot before possibly hiding the WSA, otherwise the screenshot
713 // will not be taken.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800714 mWmService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible);
chaviwa953fcf2018-03-01 12:00:39 -0800715 }
716
Robert Carre7cc44d2017-03-20 19:04:30 -0700717 // If we are hidden but there is no delay needed we immediately
718 // apply the Surface transaction so that the ActivityManager
Robert Carr61b81112017-07-17 18:08:15 -0700719 // can have some guarantee on the Surface state following
720 // setting the visibility. This captures cases like dismissing
721 // the docked or pinned stack where there is no app transition.
722 //
723 // In the case of a "Null" animation, there will be
724 // no animation but there will still be a transition set.
725 // We still need to delay hiding the surface such that it
726 // can be synchronized with showing the next surface in the transition.
lumark588a3e82018-07-20 18:53:54 +0800727 if (isHidden() && !delayed && !getDisplayContent().mAppTransition.isTransitionSet()) {
Robert Carr6914f082017-03-20 19:04:30 -0700728 SurfaceControl.openTransaction();
729 for (int i = mChildren.size() - 1; i >= 0; i--) {
730 mChildren.get(i).mWinAnimator.hide("immediately hidden");
731 }
732 SurfaceControl.closeTransaction();
733 }
Garfield Tanb6776602019-02-20 14:44:26 -0800734
735 // Visibility changes may cause orientation request change.
736 reportDescendantOrientationChangeIfNeeded();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700737 }
738
739 return delayed;
740 }
741
Garfield Tanb6776602019-02-20 14:44:26 -0800742 private void reportDescendantOrientationChangeIfNeeded() {
743 // Orientation request is exposed only when we're visible. Therefore visibility change
744 // will change requested orientation. Notify upward the hierarchy ladder to adjust
745 // configuration. This is important to cases where activities with incompatible
746 // orientations launch, or user goes back from an activity of bi-orientation to an
747 // activity with specified orientation.
748 if (mActivityRecord.getRequestedConfigurationOrientation() == getConfiguration().orientation
749 || getOrientationIgnoreVisibility() == SCREEN_ORIENTATION_UNSET) {
750 return;
751 }
752
753 final IBinder freezeToken =
754 mActivityRecord.mayFreezeScreenLocked(mActivityRecord.app)
755 ? mActivityRecord.appToken : null;
756 onDescendantOrientationChanged(freezeToken, mActivityRecord);
757 }
758
Jorim Jaggi87fdbcb2017-08-17 13:41:11 +0200759 /**
760 * @return The to top most child window for which {@link LayoutParams#isFullscreen()} returns
761 * true.
762 */
763 WindowState getTopFullscreenWindow() {
764 for (int i = mChildren.size() - 1; i >= 0; i--) {
765 final WindowState win = mChildren.get(i);
766 if (win != null && win.mAttrs.isFullscreen()) {
767 return win;
768 }
769 }
770 return null;
771 }
772
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800773 WindowState findMainWindow() {
Matthew Ng53e66b22018-01-12 17:13:13 -0800774 return findMainWindow(true);
775 }
776
777 /**
778 * Finds the main window that either has type base application or application starting if
779 * requested.
780 *
781 * @param includeStartingApp Allow to search application-starting windows to also be returned.
782 * @return The main window of type base application or application starting if requested.
783 */
784 WindowState findMainWindow(boolean includeStartingApp) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700785 WindowState candidate = null;
Matthew Ng53e66b22018-01-12 17:13:13 -0800786 for (int j = mChildren.size() - 1; j >= 0; --j) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700787 final WindowState win = mChildren.get(j);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700788 final int type = win.mAttrs.type;
789 // No need to loop through child window as base application and starting types can't be
790 // child windows.
Matthew Ng53e66b22018-01-12 17:13:13 -0800791 if (type == TYPE_BASE_APPLICATION
792 || (includeStartingApp && type == TYPE_APPLICATION_STARTING)) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700793 // In cases where there are multiple windows, we prefer the non-exiting window. This
Sungsoo Lim0d3d1f82015-12-02 14:47:59 +0900794 // happens for example when replacing windows during an activity relaunch. When
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700795 // constructing the animation, we want the new window, not the exiting one.
Wale Ogunwalec48a3542016-02-19 15:18:45 -0800796 if (win.mAnimatingExit) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700797 candidate = win;
798 } else {
799 return win;
800 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800801 }
802 }
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700803 return candidate;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800804 }
805
Wale Ogunwale6cae7652015-12-26 07:36:26 -0800806 boolean windowsAreFocusable() {
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800807 if (mTargetSdk < Build.VERSION_CODES.Q) {
808 final int pid = mActivityRecord != null
809 ? (mActivityRecord.app != null ? mActivityRecord.app.getPid() : 0) : 0;
810 final AppWindowToken topFocusedAppOfMyProcess =
811 mWmService.mRoot.mTopFocusedAppByProcess.get(pid);
812 if (topFocusedAppOfMyProcess != null && topFocusedAppOfMyProcess != this) {
813 // For the apps below Q, there can be only one app which has the focused window per
814 // process, because legacy apps may not be ready for a multi-focus system.
815 return false;
816 }
817 }
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700818 return getWindowConfiguration().canReceiveKeys() || mAlwaysFocusable;
Wale Ogunwaled045c822015-12-02 09:14:28 -0800819 }
820
Wale Ogunwale571771c2016-08-26 13:18:50 -0700821 @Override
Wale Ogunwale44f21802016-09-02 12:49:48 -0700822 boolean isVisible() {
Wale Ogunwalee471be62016-10-03 07:53:55 -0700823 // If the app token isn't hidden then it is considered visible and there is no need to check
824 // its children windows to see if they are visible.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200825 return !isHidden();
Wale Ogunwale44f21802016-09-02 12:49:48 -0700826 }
827
828 @Override
Wale Ogunwalee287e192017-04-21 09:30:12 -0700829 void removeImmediately() {
830 onRemovedFromDisplay();
Yunfan Chen3a77f282018-12-12 15:47:52 -0800831 if (mActivityRecord != null) {
832 mActivityRecord.unregisterConfigurationChangeListener(this);
833 }
Wale Ogunwalee287e192017-04-21 09:30:12 -0700834 super.removeImmediately();
835 }
836
837 @Override
Wale Ogunwale571771c2016-08-26 13:18:50 -0700838 void removeIfPossible() {
Craig Mautnere3119b72015-01-20 15:02:36 -0800839 mIsExiting = false;
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800840 removeAllWindowsIfPossible();
Bryce Lee6d410262017-02-28 15:30:17 -0800841 removeImmediately();
Craig Mautnere3119b72015-01-20 15:02:36 -0800842 }
843
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700844 @Override
845 boolean checkCompleteDeferredRemoval() {
846 if (mIsExiting) {
847 removeIfPossible();
848 }
849 return super.checkCompleteDeferredRemoval();
850 }
851
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700852 void onRemovedFromDisplay() {
Wale Ogunwalee287e192017-04-21 09:30:12 -0700853 if (mRemovingFromDisplay) {
854 return;
855 }
856 mRemovingFromDisplay = true;
857
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700858 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app token: " + this);
859
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800860 boolean delayed = commitVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700861
lumark588a3e82018-07-20 18:53:54 +0800862 getDisplayContent().mOpeningApps.remove(this);
Evan Rosky2289ba12018-11-19 18:28:18 -0800863 getDisplayContent().mChangingApps.remove(this);
lumark588a3e82018-07-20 18:53:54 +0800864 getDisplayContent().mUnknownAppVisibilityController.appRemovedOrHidden(this);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800865 mWmService.mTaskSnapshotController.onAppRemoved(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700866 waitingToShow = false;
lumark588a3e82018-07-20 18:53:54 +0800867 if (getDisplayContent().mClosingApps.contains(this)) {
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700868 delayed = true;
lumark588a3e82018-07-20 18:53:54 +0800869 } else if (getDisplayContent().mAppTransition.isTransitionSet()) {
870 getDisplayContent().mClosingApps.add(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700871 delayed = true;
872 }
873
874 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app " + this + " delayed=" + delayed
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200875 + " animation=" + getAnimation() + " animating=" + isSelfAnimating());
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700876
877 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: "
878 + this + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
879
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800880 if (startingData != null) {
881 removeStartingWindow();
Jorim Jaggi19be6052017-08-03 18:33:43 +0200882 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800883
Winson Chung87e5d552017-04-05 11:49:38 -0700884 // If this window was animating, then we need to ensure that the app transition notifies
lumark588a3e82018-07-20 18:53:54 +0800885 // that animations have completed in DisplayContent.handleAnimatingStoppedAndTransition(),
886 // so add to that list now
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200887 if (isSelfAnimating()) {
lumark588a3e82018-07-20 18:53:54 +0800888 getDisplayContent().mNoAnimationNotifyOnTransitionFinished.add(token);
Winson Chung87e5d552017-04-05 11:49:38 -0700889 }
890
Wale Ogunwalee287e192017-04-21 09:30:12 -0700891 final TaskStack stack = getStack();
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700892 if (delayed && !isEmpty()) {
893 // set the token aside because it has an active animation to be finished
894 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM,
895 "removeAppToken make exiting: " + this);
Wale Ogunwalee287e192017-04-21 09:30:12 -0700896 if (stack != null) {
897 stack.mExitingAppTokens.add(this);
898 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700899 mIsExiting = true;
900 } else {
901 // Make sure there is no animation running on this token, so any windows associated
902 // with it will be removed as soon as their animations are complete
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200903 cancelAnimation();
Wale Ogunwale3106ae012017-05-16 08:56:37 -0700904 if (stack != null) {
905 stack.mExitingAppTokens.remove(this);
906 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700907 removeIfPossible();
908 }
909
910 removed = true;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700911 stopFreezingScreen(true, true);
Bryce Lee6d410262017-02-28 15:30:17 -0800912
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800913 final DisplayContent dc = getDisplayContent();
914 if (dc.mFocusedApp == this) {
915 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + this
916 + " displayId=" + dc.getDisplayId());
917 dc.setFocusedApp(null);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800918 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700919 }
Riddle Hsu192fe762019-01-15 23:41:57 +0800920 if (mLetterbox != null) {
921 mLetterbox.destroy();
922 mLetterbox = null;
923 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700924
925 if (!delayed) {
926 updateReportedVisibilityLocked();
927 }
Wale Ogunwalee287e192017-04-21 09:30:12 -0700928
929 mRemovingFromDisplay = false;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700930 }
931
Chong Zhange05bcb12016-07-26 17:47:29 -0700932 void clearAnimatingFlags() {
Chong Zhangb0d26702016-08-12 16:03:29 -0700933 boolean wallpaperMightChange = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700934 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700935 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700936 wallpaperMightChange |= win.clearAnimatingFlags();
Chong Zhange05bcb12016-07-26 17:47:29 -0700937 }
Chong Zhangb0d26702016-08-12 16:03:29 -0700938 if (wallpaperMightChange) {
939 requestUpdateWallpaperIfNeeded();
940 }
Chong Zhange05bcb12016-07-26 17:47:29 -0700941 }
942
Robert Carre12aece2016-02-02 22:43:27 -0800943 void destroySurfaces() {
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700944 destroySurfaces(false /*cleanupOnResume*/);
945 }
946
947 /**
948 * Destroy surfaces which have been marked as eligible by the animator, taking care to ensure
949 * the client has finished with them.
950 *
951 * @param cleanupOnResume whether this is done when app is resumed without fully stopped. If
952 * set to true, destroy only surfaces of removed windows, and clear relevant flags of the
953 * others so that they are ready to be reused. If set to false (common case), destroy all
954 * surfaces that's eligible, if the app is already stopped.
955 */
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700956 private void destroySurfaces(boolean cleanupOnResume) {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700957 boolean destroyedSomething = false;
Jorim Jaggia5e10572017-11-15 14:36:26 +0100958
959 // Copying to a different list as multiple children can be removed.
Jorim Jaggi59f3e922018-01-05 15:40:32 +0100960 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
Jorim Jaggia5e10572017-11-15 14:36:26 +0100961 for (int i = children.size() - 1; i >= 0; i--) {
962 final WindowState win = children.get(i);
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700963 destroyedSomething |= win.destroySurface(cleanupOnResume, mAppStopped);
Robert Carre12aece2016-02-02 22:43:27 -0800964 }
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700965 if (destroyedSomething) {
966 final DisplayContent dc = getDisplayContent();
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700967 dc.assignWindowLayers(true /*setLayoutNeeded*/);
Adrian Roos23df3a32018-03-15 15:41:13 +0100968 updateLetterboxSurface(null);
Robert Carre12aece2016-02-02 22:43:27 -0800969 }
970 }
971
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800972 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700973 * Notify that the app is now resumed, and it was not stopped before, perform a clean
974 * up of the surfaces
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800975 */
Jorim Jaggibae01b12017-04-11 16:29:10 -0700976 void notifyAppResumed(boolean wasStopped) {
Chong Zhangad24f962016-08-25 12:12:33 -0700977 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppResumed: wasStopped=" + wasStopped
Jorim Jaggibae01b12017-04-11 16:29:10 -0700978 + " " + this);
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700979 mAppStopped = false;
chaviwd3bf08d2017-08-01 17:24:59 -0700980 // Allow the window to turn the screen on once the app is resumed again.
981 setCanTurnScreenOn(true);
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700982 if (!wasStopped) {
983 destroySurfaces(true /*cleanupOnResume*/);
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800984 }
Robert Carre12aece2016-02-02 22:43:27 -0800985 }
986
Chong Zhangbef461f2015-10-27 11:38:24 -0700987 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700988 * Notify that the app has stopped, and it is okay to destroy any surfaces which were
989 * keeping alive in case they were still being used.
990 */
991 void notifyAppStopped() {
992 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: " + this);
993 mAppStopped = true;
994 destroySurfaces();
995 // Remove any starting window that was added for this app if they are still around.
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800996 removeStartingWindow();
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700997 }
998
Chong Zhang92147042016-05-09 12:47:11 -0700999 void clearAllDrawn() {
1000 allDrawn = false;
1001 deferClearAllDrawn = false;
Chong Zhangbef461f2015-10-27 11:38:24 -07001002 }
1003
Bryce Lee6d410262017-02-28 15:30:17 -08001004 Task getTask() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001005 return (Task) getParent();
Bryce Lee6d410262017-02-28 15:30:17 -08001006 }
1007
Jorim Jaggi3878ca32017-02-02 17:13:05 -08001008 TaskStack getStack() {
1009 final Task task = getTask();
1010 if (task != null) {
1011 return task.mStack;
1012 } else {
1013 return null;
1014 }
1015 }
1016
Bryce Lee6d410262017-02-28 15:30:17 -08001017 @Override
Riddle Hsu3a4bb612019-01-31 00:02:22 +08001018 void onParentChanged() {
1019 super.onParentChanged();
Bryce Lee6d410262017-02-28 15:30:17 -08001020
Robert Carred3e83b2017-04-21 13:26:55 -07001021 final Task task = getTask();
1022
Bryce Lee6d410262017-02-28 15:30:17 -08001023 // When the associated task is {@code null}, the {@link AppWindowToken} can no longer
1024 // access visual elements like the {@link DisplayContent}. We must remove any associations
1025 // such as animations.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001026 if (!mReparenting) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001027 if (task == null) {
1028 // It is possible we have been marked as a closing app earlier. We must remove ourselves
1029 // from this list so we do not participate in any future animations.
lumark588a3e82018-07-20 18:53:54 +08001030 getDisplayContent().mClosingApps.remove(this);
Robert Carred3e83b2017-04-21 13:26:55 -07001031 } else if (mLastParent != null && mLastParent.mStack != null) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001032 task.mStack.mExitingAppTokens.remove(this);
1033 }
Bryce Lee6d410262017-02-28 15:30:17 -08001034 }
Jorim Jaggi6de61012018-03-19 14:53:23 +01001035 final TaskStack stack = getStack();
1036
1037 // If we reparent, make sure to remove ourselves from the old animation registry.
1038 if (mAnimatingAppWindowTokenRegistry != null) {
1039 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
1040 }
1041 mAnimatingAppWindowTokenRegistry = stack != null
1042 ? stack.getAnimatingAppWindowTokenRegistry()
1043 : null;
1044
Robert Carred3e83b2017-04-21 13:26:55 -07001045 mLastParent = task;
chaviwdcf76ec2019-01-11 16:48:46 -08001046
1047 updateColorTransform();
Bryce Lee6d410262017-02-28 15:30:17 -08001048 }
1049
Wale Ogunwalefa854eb2016-09-20 13:43:52 -07001050 void postWindowRemoveStartingWindowCleanup(WindowState win) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001051 // TODO: Something smells about the code below...Is there a better way?
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001052 if (startingWindow == win) {
1053 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Notify removed startingWindow " + win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001054 removeStartingWindow();
Wale Ogunwale6c459212017-05-17 08:56:03 -07001055 } else if (mChildren.size() == 0) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001056 // If this is the last window and we had requested a starting transition window,
1057 // well there is no point now.
Jorim Jaggi02886a82016-12-06 09:10:06 -08001058 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Nulling last startingData");
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001059 startingData = null;
Wale Ogunwale6c459212017-05-17 08:56:03 -07001060 if (mHiddenSetFromTransferredStartingWindow) {
1061 // We set the hidden state to false for the token from a transferred starting window.
1062 // We now reset it back to true since the starting window was the last window in the
1063 // token.
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001064 setHidden(true);
Wale Ogunwale6c459212017-05-17 08:56:03 -07001065 }
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01001066 } else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001067 // If this is the last window except for a starting transition window,
1068 // we need to get rid of the starting transition.
Jorim Jaggie4b0f282017-05-17 15:10:29 +02001069 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Last window, removing starting window "
1070 + win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001071 removeStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001072 }
1073 }
1074
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001075 void removeDeadWindows() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001076 for (int winNdx = mChildren.size() - 1; winNdx >= 0; --winNdx) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001077 WindowState win = mChildren.get(winNdx);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001078 if (win.mAppDied) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001079 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.w(TAG,
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001080 "removeDeadWindows: " + win);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001081 // Set mDestroying, we don't want any animation or delayed removal here.
1082 win.mDestroying = true;
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001083 // Also removes child windows.
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001084 win.removeIfPossible();
Chong Zhang112eb8c2015-11-02 11:17:00 -08001085 }
1086 }
1087 }
1088
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001089 boolean hasWindowsAlive() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001090 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001091 // No need to loop through child windows as the answer should be the same as that of the
1092 // parent window.
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001093 if (!(mChildren.get(i)).mAppDied) {
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001094 return true;
1095 }
1096 }
1097 return false;
1098 }
1099
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001100 void setWillReplaceWindows(boolean animate) {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001101 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
1102 "Marking app token " + this + " with replacing windows.");
Robert Carra1eb4392015-12-10 12:43:51 -08001103
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001104 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001105 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001106 w.setWillReplaceWindow(animate);
Robert Carra1eb4392015-12-10 12:43:51 -08001107 }
Robert Carra1eb4392015-12-10 12:43:51 -08001108 }
1109
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001110 void setWillReplaceChildWindows() {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001111 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Marking app token " + this
Robert Carr23fa16b2016-01-13 13:19:58 -08001112 + " with replacing child windows.");
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001113 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001114 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001115 w.setWillReplaceChildWindows();
Robert Carr23fa16b2016-01-13 13:19:58 -08001116 }
1117 }
1118
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001119 void clearWillReplaceWindows() {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001120 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
1121 "Resetting app token " + this + " of replacing window marks.");
Chong Zhangf596cd52016-01-05 13:42:44 -08001122
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001123 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001124 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001125 w.clearWillReplaceWindow();
Chong Zhangf596cd52016-01-05 13:42:44 -08001126 }
1127 }
1128
Chong Zhang4d7369a2016-04-25 16:09:14 -07001129 void requestUpdateWallpaperIfNeeded() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001130 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001131 final WindowState w = mChildren.get(i);
Chong Zhang4d7369a2016-04-25 16:09:14 -07001132 w.requestUpdateWallpaperIfNeeded();
1133 }
1134 }
1135
Chong Zhangd78ddb42016-03-02 17:01:14 -08001136 boolean isRelaunching() {
1137 return mPendingRelaunchCount > 0;
1138 }
1139
Robert Carr68375192017-06-13 12:41:53 -07001140 boolean shouldFreezeBounds() {
1141 final Task task = getTask();
1142
1143 // For freeform windows, we can't freeze the bounds at the moment because this would make
1144 // the resizing unresponsive.
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001145 if (task == null || task.inFreeformWindowingMode()) {
Robert Carr68375192017-06-13 12:41:53 -07001146 return false;
1147 }
1148
1149 // We freeze the bounds while drag resizing to deal with the time between
1150 // the divider/drag handle being released, and the handling it's new
1151 // configuration. If we are relaunched outside of the drag resizing state,
1152 // we need to be careful not to do this.
1153 return getTask().isDragResizing();
1154 }
1155
Chong Zhangd78ddb42016-03-02 17:01:14 -08001156 void startRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001157 if (shouldFreezeBounds()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08001158 freezeBounds();
1159 }
Robert Carrd5c7dd62017-03-08 10:39:30 -08001160
1161 // In the process of tearing down before relaunching, the app will
1162 // try and clean up it's child surfaces. We need to prevent this from
1163 // happening, so we sever the children, transfering their ownership
1164 // from the client it-self to the parent surface (owned by us).
Robert Carr29daa922018-04-27 11:56:48 -07001165 detachChildren();
1166
1167 mPendingRelaunchCount++;
1168 }
1169
1170 void detachChildren() {
Robert Carrfd8e93b2018-05-10 13:40:25 -07001171 SurfaceControl.openTransaction();
Robert Carrd5c7dd62017-03-08 10:39:30 -08001172 for (int i = mChildren.size() - 1; i >= 0; i--) {
1173 final WindowState w = mChildren.get(i);
1174 w.mWinAnimator.detachChildren();
1175 }
Robert Carrfd8e93b2018-05-10 13:40:25 -07001176 SurfaceControl.closeTransaction();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001177 }
1178
1179 void finishRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001180 unfreezeBounds();
1181
Chong Zhangd78ddb42016-03-02 17:01:14 -08001182 if (mPendingRelaunchCount > 0) {
1183 mPendingRelaunchCount--;
Bryce Lee081554b2017-05-25 07:52:12 -07001184 } else {
1185 // Update keyguard flags upon finishing relaunch.
1186 checkKeyguardFlagsChanged();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001187 }
1188 }
1189
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001190 void clearRelaunching() {
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001191 if (mPendingRelaunchCount == 0) {
1192 return;
1193 }
Robert Carr68375192017-06-13 12:41:53 -07001194 unfreezeBounds();
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001195 mPendingRelaunchCount = 0;
1196 }
1197
Wale Ogunwale07bcab72016-10-14 15:30:09 -07001198 /**
1199 * Returns true if the new child window we are adding to this token is considered greater than
1200 * the existing child window in this token in terms of z-order.
1201 */
1202 @Override
1203 protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
1204 WindowState existingWindow) {
1205 final int type1 = newWindow.mAttrs.type;
1206 final int type2 = existingWindow.mAttrs.type;
1207
1208 // Base application windows should be z-ordered BELOW all other windows in the app token.
1209 if (type1 == TYPE_BASE_APPLICATION && type2 != TYPE_BASE_APPLICATION) {
1210 return false;
1211 } else if (type1 != TYPE_BASE_APPLICATION && type2 == TYPE_BASE_APPLICATION) {
1212 return true;
1213 }
1214
1215 // Starting windows should be z-ordered ABOVE all other windows in the app token.
1216 if (type1 == TYPE_APPLICATION_STARTING && type2 != TYPE_APPLICATION_STARTING) {
1217 return true;
1218 } else if (type1 != TYPE_APPLICATION_STARTING && type2 == TYPE_APPLICATION_STARTING) {
1219 return false;
1220 }
1221
1222 // Otherwise the new window is greater than the existing window.
1223 return true;
1224 }
1225
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001226 @Override
Robert Carra1eb4392015-12-10 12:43:51 -08001227 void addWindow(WindowState w) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001228 super.addWindow(w);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001229
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001230 boolean gotReplacementWindow = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001231 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001232 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001233 gotReplacementWindow |= candidate.setReplacementWindowIfNeeded(w);
1234 }
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001235
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001236 // if we got a replacement window, reset the timeout to give drawing more time
1237 if (gotReplacementWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001238 mWmService.scheduleWindowReplacementTimeouts(this);
Robert Carra1eb4392015-12-10 12:43:51 -08001239 }
Jorim Jaggife762342016-10-13 14:33:27 +02001240 checkKeyguardFlagsChanged();
1241 }
1242
1243 @Override
1244 void removeChild(WindowState child) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001245 if (!mChildren.contains(child)) {
1246 // This can be true when testing.
1247 return;
1248 }
Jorim Jaggife762342016-10-13 14:33:27 +02001249 super.removeChild(child);
1250 checkKeyguardFlagsChanged();
Adrian Roos23df3a32018-03-15 15:41:13 +01001251 updateLetterboxSurface(child);
Robert Carra1eb4392015-12-10 12:43:51 -08001252 }
1253
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001254 private boolean waitingForReplacement() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001255 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001256 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001257 if (candidate.waitingForReplacement()) {
Robert Carra1eb4392015-12-10 12:43:51 -08001258 return true;
1259 }
1260 }
1261 return false;
1262 }
1263
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001264 void onWindowReplacementTimeout() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001265 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001266 (mChildren.get(i)).onWindowReplacementTimeout();
Robert Carra1eb4392015-12-10 12:43:51 -08001267 }
1268 }
1269
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001270 void reparent(Task task, int position) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001271 if (DEBUG_ADD_REMOVE) {
1272 Slog.i(TAG_WM, "reparent: moving app token=" + this
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001273 + " to task=" + task.mTaskId + " at " + position);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001274 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001275 if (task == null) {
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001276 throw new IllegalArgumentException("reparent: could not find task");
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001277 }
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001278 final Task currentTask = getTask();
1279 if (task == currentTask) {
Winson Chung30480042017-01-26 10:55:34 -08001280 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001281 "window token=" + this + " already child of task=" + currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001282 }
Bryce Lee6d410262017-02-28 15:30:17 -08001283
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001284 if (currentTask.mStack != task.mStack) {
Bryce Lee6d410262017-02-28 15:30:17 -08001285 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001286 "window token=" + this + " current task=" + currentTask
Bryce Lee6d410262017-02-28 15:30:17 -08001287 + " belongs to a different stack than " + task);
1288 }
1289
Winson Chung30480042017-01-26 10:55:34 -08001290 if (DEBUG_ADD_REMOVE) Slog.i(TAG, "reParentWindowToken: removing window token=" + this
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001291 + " from task=" + currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001292 final DisplayContent prevDisplayContent = getDisplayContent();
1293
Bryce Lee6d410262017-02-28 15:30:17 -08001294 mReparenting = true;
1295
Winson Chung30480042017-01-26 10:55:34 -08001296 getParent().removeChild(this);
1297 task.addChild(this, position);
1298
Bryce Lee6d410262017-02-28 15:30:17 -08001299 mReparenting = false;
1300
Winson Chung30480042017-01-26 10:55:34 -08001301 // Relayout display(s).
1302 final DisplayContent displayContent = task.getDisplayContent();
1303 displayContent.setLayoutNeeded();
1304 if (prevDisplayContent != displayContent) {
1305 onDisplayChanged(displayContent);
1306 prevDisplayContent.setLayoutNeeded();
1307 }
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001308 getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
Winson Chung30480042017-01-26 10:55:34 -08001309 }
1310
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001311 @Override
1312 void onDisplayChanged(DisplayContent dc) {
1313 DisplayContent prevDc = mDisplayContent;
1314 super.onDisplayChanged(dc);
Evan Rosky25b56192019-02-06 16:10:56 -08001315 if (prevDc == null) {
1316 return;
1317 }
1318 if (prevDc.mChangingApps.contains(this)) {
1319 // This gets called *after* the AppWindowToken has been reparented to the new display.
1320 // That reparenting resulted in this window changing modes (eg. FREEFORM -> FULLSCREEN),
1321 // so this token is now "frozen" while waiting for the animation to start on prevDc
1322 // (which will be cancelled since the window is no-longer a child). However, since this
1323 // is no longer a child of prevDc, this won't be notified of the cancelled animation,
1324 // so we need to cancel the change transition here.
1325 clearChangeLeash(getPendingTransaction(), true /* cancel */);
1326 }
1327 if (prevDc.mFocusedApp == this) {
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001328 prevDc.setFocusedApp(null);
lumarkbf844642018-11-23 17:11:36 +08001329 final TaskStack stack = dc.getTopStack();
1330 if (stack != null) {
1331 final Task task = stack.getTopChild();
1332 if (task != null && task.getTopChild() == this) {
1333 dc.setFocusedApp(this);
1334 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001335 }
1336 }
Riddle Hsu192fe762019-01-15 23:41:57 +08001337
1338 if (prevDc != mDisplayContent && mLetterbox != null) {
1339 mLetterbox.onMovedToDisplay(mDisplayContent.getDisplayId());
1340 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001341 }
1342
Jorim Jaggi0429f352015-12-22 16:29:16 +01001343 /**
1344 * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds
1345 * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even
1346 * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen
1347 * with a queue.
1348 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001349 private void freezeBounds() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001350 final Task task = getTask();
1351 mFrozenBounds.offer(new Rect(task.mPreparedFrozenBounds));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001352
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001353 if (task.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001354 // We didn't call prepareFreezingBounds on the task, so use the current value.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001355 mFrozenMergedConfig.offer(new Configuration(task.getConfiguration()));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001356 } else {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001357 mFrozenMergedConfig.offer(new Configuration(task.mPreparedFrozenMergedConfig));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001358 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001359 // Calling unset() to make it equal to Configuration.EMPTY.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001360 task.mPreparedFrozenMergedConfig.unset();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001361 }
1362
1363 /**
1364 * Unfreezes the previously frozen bounds. See {@link #freezeBounds}.
1365 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001366 private void unfreezeBounds() {
Robert Carr68375192017-06-13 12:41:53 -07001367 if (mFrozenBounds.isEmpty()) {
1368 return;
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001369 }
Robert Carr68375192017-06-13 12:41:53 -07001370 mFrozenBounds.remove();
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001371 if (!mFrozenMergedConfig.isEmpty()) {
1372 mFrozenMergedConfig.remove();
1373 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001374 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001375 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001376 win.onUnfreezeBounds();
Jorim Jaggi4846ee32016-01-07 17:39:12 +01001377 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001378 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001379 }
1380
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001381 void setAppLayoutChanges(int changes, String reason) {
1382 if (!mChildren.isEmpty()) {
1383 final DisplayContent dc = getDisplayContent();
1384 dc.pendingLayoutChanges |= changes;
1385 if (DEBUG_LAYOUT_REPEATS) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001386 mWmService.mWindowPlacerLocked.debugLayoutRepeats(reason, dc.pendingLayoutChanges);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001387 }
1388 }
1389 }
1390
1391 void removeReplacedWindowIfNeeded(WindowState replacement) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001392 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001393 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001394 if (win.removeReplacedWindowIfNeeded(replacement)) {
1395 return;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001396 }
1397 }
1398 }
1399
1400 void startFreezingScreen() {
1401 if (DEBUG_ORIENTATION) logWithStack(TAG, "Set freezing of " + appToken + ": hidden="
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001402 + isHidden() + " freezing=" + mFreezingScreen + " hiddenRequested="
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001403 + hiddenRequested);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001404 if (!hiddenRequested) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001405 if (!mFreezingScreen) {
1406 mFreezingScreen = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001407 mWmService.registerAppFreezeListener(this);
1408 mWmService.mAppsFreezingScreen++;
1409 if (mWmService.mAppsFreezingScreen == 1) {
1410 mWmService.startFreezingDisplayLocked(0, 0, getDisplayContent());
1411 mWmService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
1412 mWmService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001413 }
1414 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001415 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001416 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001417 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001418 w.onStartFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001419 }
1420 }
1421 }
1422
1423 void stopFreezingScreen(boolean unfreezeSurfaceNow, boolean force) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001424 if (!mFreezingScreen) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001425 return;
1426 }
1427 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + this + " force=" + force);
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001428 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001429 boolean unfrozeWindows = false;
1430 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001431 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001432 unfrozeWindows |= w.onStopFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001433 }
1434 if (force || unfrozeWindows) {
1435 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "No longer freezing: " + this);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001436 mFreezingScreen = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001437 mWmService.unregisterAppFreezeListener(this);
1438 mWmService.mAppsFreezingScreen--;
1439 mWmService.mLastFinishedFreezeSource = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001440 }
1441 if (unfreezeSurfaceNow) {
1442 if (unfrozeWindows) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001443 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001444 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001445 mWmService.stopFreezingDisplayLocked();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001446 }
1447 }
1448
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001449 @Override
1450 public void onAppFreezeTimeout() {
1451 Slog.w(TAG_WM, "Force clearing freeze: " + this);
1452 stopFreezingScreen(true, true);
1453 }
1454
Jorim Jaggi60f9c972018-02-01 19:21:07 +01001455 /**
1456 * Tries to transfer the starting window from a token that's above ourselves in the task but
1457 * not visible anymore. This is a common scenario apps use: Trampoline activity T start main
1458 * activity M in the same task. Now, when reopening the task, T starts on top of M but then
1459 * immediately finishes after, so we have to transfer T to M.
1460 */
1461 void transferStartingWindowFromHiddenAboveTokenIfNeeded() {
1462 final Task task = getTask();
1463 for (int i = task.mChildren.size() - 1; i >= 0; i--) {
1464 final AppWindowToken fromToken = task.mChildren.get(i);
1465 if (fromToken == this) {
1466 return;
1467 }
1468 if (fromToken.hiddenRequested && transferStartingWindow(fromToken.token)) {
1469 return;
1470 }
1471 }
1472 }
1473
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001474 boolean transferStartingWindow(IBinder transferFrom) {
Wale Ogunwale02319a62016-09-26 15:21:22 -07001475 final AppWindowToken fromToken = getDisplayContent().getAppWindowToken(transferFrom);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001476 if (fromToken == null) {
1477 return false;
1478 }
1479
1480 final WindowState tStartingWindow = fromToken.startingWindow;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08001481 if (tStartingWindow != null && fromToken.startingSurface != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001482 // In this case, the starting icon has already been displayed, so start
1483 // letting windows get shown immediately without any more transitions.
lumark588a3e82018-07-20 18:53:54 +08001484 getDisplayContent().mSkipAppTransitionAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001485
1486 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Moving existing starting " + tStartingWindow
1487 + " from " + fromToken + " to " + this);
1488
1489 final long origId = Binder.clearCallingIdentity();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001490 try {
1491 // Transfer the starting window over to the new token.
1492 startingData = fromToken.startingData;
1493 startingSurface = fromToken.startingSurface;
1494 startingDisplayed = fromToken.startingDisplayed;
1495 fromToken.startingDisplayed = false;
1496 startingWindow = tStartingWindow;
1497 reportedVisible = fromToken.reportedVisible;
1498 fromToken.startingData = null;
1499 fromToken.startingSurface = null;
1500 fromToken.startingWindow = null;
1501 fromToken.startingMoved = true;
1502 tStartingWindow.mToken = this;
1503 tStartingWindow.mAppToken = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001504
Peter Visontay3556a3b2017-11-01 17:23:17 +00001505 if (DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
1506 "Removing starting " + tStartingWindow + " from " + fromToken);
1507 fromToken.removeChild(tStartingWindow);
1508 fromToken.postWindowRemoveStartingWindowCleanup(tStartingWindow);
1509 fromToken.mHiddenSetFromTransferredStartingWindow = false;
1510 addWindow(tStartingWindow);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001511
Peter Visontay3556a3b2017-11-01 17:23:17 +00001512 // Propagate other interesting state between the tokens. If the old token is displayed,
1513 // we should immediately force the new one to be displayed. If it is animating, we need
1514 // to move that animation to the new one.
1515 if (fromToken.allDrawn) {
1516 allDrawn = true;
1517 deferClearAllDrawn = fromToken.deferClearAllDrawn;
1518 }
1519 if (fromToken.firstWindowDrawn) {
1520 firstWindowDrawn = true;
1521 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001522 if (!fromToken.isHidden()) {
1523 setHidden(false);
Peter Visontay3556a3b2017-11-01 17:23:17 +00001524 hiddenRequested = false;
1525 mHiddenSetFromTransferredStartingWindow = true;
1526 }
1527 setClientHidden(fromToken.mClientHidden);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001528
Jorim Jaggi980c9de2017-11-17 01:41:37 +01001529 transferAnimation(fromToken);
1530
1531 // When transferring an animation, we no longer need to apply an animation to the
1532 // the token we transfer the animation over. Thus, remove the animation from
1533 // pending opening apps.
lumark588a3e82018-07-20 18:53:54 +08001534 getDisplayContent().mOpeningApps.remove(this);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001535
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001536 mWmService.updateFocusedWindowLocked(
Peter Visontay3556a3b2017-11-01 17:23:17 +00001537 UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/);
1538 getDisplayContent().setLayoutNeeded();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001539 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001540 } finally {
1541 Binder.restoreCallingIdentity(origId);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001542 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001543 return true;
1544 } else if (fromToken.startingData != null) {
1545 // The previous app was getting ready to show a
1546 // starting window, but hasn't yet done so. Steal it!
1547 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
1548 "Moving pending starting from " + fromToken + " to " + this);
1549 startingData = fromToken.startingData;
1550 fromToken.startingData = null;
1551 fromToken.startingMoved = true;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001552 scheduleAddStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001553 return true;
1554 }
1555
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001556 // TODO: Transfer thumbnail
1557
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001558 return false;
1559 }
1560
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001561 boolean isLastWindow(WindowState win) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001562 return mChildren.size() == 1 && mChildren.get(0) == win;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001563 }
1564
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001565 @Override
1566 void onAppTransitionDone() {
1567 sendingToBottom = false;
1568 }
1569
Wale Ogunwale51362492016-09-08 17:49:17 -07001570 /**
1571 * We override because this class doesn't want its children affecting its reported orientation
1572 * in anyway.
1573 */
1574 @Override
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001575 int getOrientation(int candidate) {
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001576 if (candidate == SCREEN_ORIENTATION_BEHIND) {
1577 // Allow app to specify orientation regardless of its visibility state if the current
1578 // candidate want us to use orientation behind. I.e. the visible app on-top of this one
1579 // wants us to use the orientation of the app behind it.
1580 return mOrientation;
1581 }
1582
Bryce Lee61fbcbc2017-03-10 14:14:03 -08001583 // The {@link AppWindowToken} should only specify an orientation when it is not closing or
1584 // going to the bottom. Allowing closing {@link AppWindowToken} to participate can lead to
1585 // an Activity in another task being started in the wrong orientation during the transition.
lumark588a3e82018-07-20 18:53:54 +08001586 if (!(sendingToBottom || getDisplayContent().mClosingApps.contains(this))
1587 && (isVisible() || getDisplayContent().mOpeningApps.contains(this))) {
Bryce Leea163b762017-01-24 11:05:01 -08001588 return mOrientation;
Wale Ogunwale51362492016-09-08 17:49:17 -07001589 }
Bryce Leea163b762017-01-24 11:05:01 -08001590
1591 return SCREEN_ORIENTATION_UNSET;
Wale Ogunwale51362492016-09-08 17:49:17 -07001592 }
1593
Wale Ogunwaleb198b742016-12-01 08:44:09 -08001594 /** Returns the app's preferred orientation regardless of its currently visibility state. */
1595 int getOrientationIgnoreVisibility() {
1596 return mOrientation;
1597 }
1598
Riddle Hsub398da32019-01-21 21:48:16 +08001599 /** @return {@code true} if the compatibility bounds is taking effect. */
1600 boolean inSizeCompatMode() {
1601 return mSizeCompatBounds != null;
1602 }
1603
1604 @Override
1605 float getSizeCompatScale() {
1606 return inSizeCompatMode() ? mSizeCompatScale : super.getSizeCompatScale();
1607 }
1608
1609 /**
1610 * @return Non-empty bounds if the activity has override bounds.
1611 * @see ActivityRecord#resolveOverrideConfiguration(Configuration)
1612 */
1613 Rect getResolvedOverrideBounds() {
1614 // Get bounds from resolved override configuration because it is computed with orientation.
1615 return getResolvedOverrideConfiguration().windowConfiguration.getBounds();
1616 }
1617
Craig Mautnerdbb79912012-03-01 18:59:14 -08001618 @Override
Winson Chunge55c0192017-08-24 14:50:48 -07001619 public void onConfigurationChanged(Configuration newParentConfig) {
1620 final int prevWinMode = getWindowingMode();
Evan Rosky2289ba12018-11-19 18:28:18 -08001621 mTmpPrevBounds.set(getBounds());
Winson Chunge55c0192017-08-24 14:50:48 -07001622 super.onConfigurationChanged(newParentConfig);
Riddle Hsub398da32019-01-21 21:48:16 +08001623
1624 final Task task = getTask();
1625 final Rect overrideBounds = getResolvedOverrideBounds();
1626 if (task != null && !overrideBounds.isEmpty()
1627 // If the changes come from change-listener, the incoming parent configuration is
1628 // still the old one. Make sure their orientations are the same to reduce computing
1629 // the compatibility bounds for the intermediate state.
Riddle Hsu04164182019-03-07 18:03:27 +08001630 && (task.mTaskRecord == null || task.mTaskRecord
1631 .getConfiguration().orientation == newParentConfig.orientation)) {
Riddle Hsub398da32019-01-21 21:48:16 +08001632 final Rect taskBounds = task.getBounds();
1633 // Since we only center the activity horizontally, if only the fixed height is smaller
1634 // than its container, the override bounds don't need to take effect.
1635 if ((overrideBounds.width() != taskBounds.width()
1636 || overrideBounds.height() > taskBounds.height())) {
1637 calculateCompatBoundsTransformation(newParentConfig);
1638 updateSurfacePosition();
1639 } else if (mSizeCompatBounds != null) {
1640 mSizeCompatBounds = null;
1641 mSizeCompatScale = 1f;
1642 updateSurfacePosition();
1643 }
1644 }
1645
Winson Chunge55c0192017-08-24 14:50:48 -07001646 final int winMode = getWindowingMode();
1647
1648 if (prevWinMode == winMode) {
1649 return;
1650 }
1651
1652 if (prevWinMode != WINDOWING_MODE_UNDEFINED && winMode == WINDOWING_MODE_PINNED) {
1653 // Entering PiP from fullscreen, reset the snap fraction
1654 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(this);
Winson Chung82267ce2018-04-06 16:38:26 -07001655 } else if (prevWinMode == WINDOWING_MODE_PINNED && winMode != WINDOWING_MODE_UNDEFINED
1656 && !isHidden()) {
Winson Chunge55c0192017-08-24 14:50:48 -07001657 // Leaving PiP to fullscreen, save the snap fraction based on the pre-animation bounds
1658 // for the next re-entry into PiP (assuming the activity is not hidden or destroyed)
1659 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
1660 if (pinnedStack != null) {
Winson Chung8efa1652018-06-06 09:34:23 -07001661 final Rect stackBounds;
1662 if (pinnedStack.lastAnimatingBoundsWasToFullscreen()) {
1663 // We are animating the bounds, use the pre-animation bounds to save the snap
1664 // fraction
1665 stackBounds = pinnedStack.mPreAnimationBounds;
1666 } else {
1667 // We skip the animation if the fullscreen configuration is not compatible, so
1668 // use the current bounds to calculate the saved snap fraction instead
1669 // (see PinnedActivityStack.skipResizeAnimation())
1670 stackBounds = mTmpRect;
1671 pinnedStack.getBounds(stackBounds);
1672 }
Winson Chunge55c0192017-08-24 14:50:48 -07001673 mDisplayContent.mPinnedStackControllerLocked.saveReentrySnapFraction(this,
Winson Chung8efa1652018-06-06 09:34:23 -07001674 stackBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001675 }
Evan Rosky2289ba12018-11-19 18:28:18 -08001676 } else if (shouldStartChangeTransition(prevWinMode, winMode)) {
1677 initializeChangeTransition(mTmpPrevBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001678 }
1679 }
1680
Evan Rosky2289ba12018-11-19 18:28:18 -08001681 private boolean shouldStartChangeTransition(int prevWinMode, int newWinMode) {
Evan Rosky25b56192019-02-06 16:10:56 -08001682 if (mWmService.mDisableTransitionAnimation
1683 || !isVisible()
1684 || getDisplayContent().mAppTransition.isTransitionSet()
1685 || getSurfaceControl() == null) {
Evan Rosky2289ba12018-11-19 18:28:18 -08001686 return false;
1687 }
1688 // Only do an animation into and out-of freeform mode for now. Other mode
1689 // transition animations are currently handled by system-ui.
1690 return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
1691 }
1692
1693 /**
1694 * Initializes a change transition. Because the app is visible already, there is a small period
1695 * of time where the user can see the app content/window update before the transition starts.
1696 * To prevent this, we immediately take a snapshot and place the app/snapshot into a leash which
1697 * "freezes" the location/crop until the transition starts.
1698 * <p>
1699 * Here's a walk-through of the process:
1700 * 1. Create a temporary leash ("interim-change-leash") and reparent the app to it.
1701 * 2. Set the temporary leash's position/crop to the current state.
1702 * 3. Create a snapshot and place that at the top of the leash to cover up content changes.
1703 * 4. Once the transition is ready, it will reparent the app to the animation leash.
1704 * 5. Detach the interim-change-leash.
1705 */
1706 private void initializeChangeTransition(Rect startBounds) {
1707 mDisplayContent.prepareAppTransition(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
1708 false /* alwaysKeepCurrent */, 0, false /* forceOverride */);
1709 mDisplayContent.mChangingApps.add(this);
1710 mTransitStartRect.set(startBounds);
1711
1712 final SurfaceControl.Builder builder = makeAnimationLeash()
1713 .setParent(getAnimationLeashParent())
1714 .setName(getSurfaceControl() + " - interim-change-leash");
1715 mTransitChangeLeash = builder.build();
1716 Transaction t = getPendingTransaction();
1717 t.setWindowCrop(mTransitChangeLeash, startBounds.width(), startBounds.height());
1718 t.setPosition(mTransitChangeLeash, startBounds.left, startBounds.top);
1719 t.show(mTransitChangeLeash);
1720 t.reparent(getSurfaceControl(), mTransitChangeLeash);
1721 onAnimationLeashCreated(t, mTransitChangeLeash);
1722
Evan Rosky966759f2019-01-15 10:33:58 -08001723 // Skip creating snapshot if this transition is controlled by a remote animator which
1724 // doesn't need it.
1725 ArraySet<Integer> activityTypes = new ArraySet<>();
1726 activityTypes.add(getActivityType());
1727 RemoteAnimationAdapter adapter =
1728 mDisplayContent.mAppTransitionController.getRemoteAnimationOverride(
1729 this, TRANSIT_TASK_CHANGE_WINDOWING_MODE, activityTypes);
1730 if (adapter != null && !adapter.getChangeNeedsSnapshot()) {
1731 return;
1732 }
1733
Evan Rosky2289ba12018-11-19 18:28:18 -08001734 if (mThumbnail == null && getTask() != null) {
1735 final TaskSnapshotController snapshotCtrl = mWmService.mTaskSnapshotController;
1736 final ArraySet<Task> tasks = new ArraySet<>();
1737 tasks.add(getTask());
1738 snapshotCtrl.snapshotTasks(tasks);
1739 snapshotCtrl.addSkipClosingAppSnapshotTasks(tasks);
1740 final ActivityManager.TaskSnapshot snapshot = snapshotCtrl.getSnapshot(
1741 getTask().mTaskId, getTask().mUserId, false /* restoreFromDisk */,
1742 false /* reducedResolution */);
Yunfan Chendcb1fcf2019-02-07 19:08:41 +09001743 if (snapshot != null) {
1744 mThumbnail = new AppWindowThumbnail(t, this, snapshot.getSnapshot(),
1745 true /* relative */);
1746 }
Evan Rosky2289ba12018-11-19 18:28:18 -08001747 }
1748 }
1749
1750 boolean isInChangeTransition() {
Evan Roskyec9488c2019-03-01 19:32:12 -08001751 return mTransitChangeLeash != null || AppTransition.isChangeTransit(mTransit);
Evan Rosky2289ba12018-11-19 18:28:18 -08001752 }
1753
Evan Rosky966759f2019-01-15 10:33:58 -08001754 @VisibleForTesting
1755 AppWindowThumbnail getThumbnail() {
1756 return mThumbnail;
1757 }
1758
Riddle Hsub398da32019-01-21 21:48:16 +08001759 /**
1760 * Calculates the scale and offset to horizontal center the size compatibility bounds into the
1761 * region which is available to application.
1762 */
1763 private void calculateCompatBoundsTransformation(Configuration newParentConfig) {
1764 final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds();
1765 final Rect viewportBounds = parentAppBounds != null
1766 ? parentAppBounds : newParentConfig.windowConfiguration.getBounds();
Riddle Hsu04164182019-03-07 18:03:27 +08001767 final Rect appBounds = getWindowConfiguration().getAppBounds();
1768 final Rect contentBounds = appBounds != null ? appBounds : getResolvedOverrideBounds();
Riddle Hsub398da32019-01-21 21:48:16 +08001769 final float contentW = contentBounds.width();
1770 final float contentH = contentBounds.height();
1771 final float viewportW = viewportBounds.width();
1772 final float viewportH = viewportBounds.height();
1773 // Only allow to scale down.
1774 mSizeCompatScale = (contentW <= viewportW && contentH <= viewportH)
1775 ? 1 : Math.min(viewportW / contentW, viewportH / contentH);
1776 final int offsetX = (int) ((viewportW - contentW * mSizeCompatScale + 1) * 0.5f)
1777 + viewportBounds.left;
1778
1779 if (mSizeCompatBounds == null) {
1780 mSizeCompatBounds = new Rect();
1781 }
1782 mSizeCompatBounds.set(contentBounds);
1783 mSizeCompatBounds.offsetTo(0, 0);
1784 mSizeCompatBounds.scale(mSizeCompatScale);
Riddle Hsu04164182019-03-07 18:03:27 +08001785 // The decor inset is included in height.
1786 mSizeCompatBounds.bottom += viewportBounds.top;
Riddle Hsub398da32019-01-21 21:48:16 +08001787 mSizeCompatBounds.left += offsetX;
1788 mSizeCompatBounds.right += offsetX;
1789 }
1790
1791 @Override
1792 public Rect getBounds() {
1793 if (mSizeCompatBounds != null) {
1794 return mSizeCompatBounds;
1795 }
1796 return super.getBounds();
1797 }
1798
1799 @Override
1800 public boolean matchParentBounds() {
1801 if (super.matchParentBounds()) {
1802 return true;
1803 }
1804 // An activity in size compatibility mode may have override bounds which equals to its
1805 // parent bounds, so the exact bounds should also be checked.
1806 final WindowContainer parent = getParent();
1807 return parent == null || parent.getBounds().equals(getResolvedOverrideBounds());
1808 }
1809
Winson Chunge55c0192017-08-24 14:50:48 -07001810 @Override
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001811 void checkAppWindowsReadyToShow() {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001812 if (allDrawn == mLastAllDrawn) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001813 return;
1814 }
1815
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001816 mLastAllDrawn = allDrawn;
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001817 if (!allDrawn) {
1818 return;
1819 }
1820
1821 // The token has now changed state to having all windows shown... what to do, what to do?
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001822 if (mFreezingScreen) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001823 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001824 stopFreezingScreen(false, true);
1825 if (DEBUG_ORIENTATION) Slog.i(TAG,
1826 "Setting mOrientationChangeComplete=true because wtoken " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001827 + " numInteresting=" + mNumInterestingWindows + " numDrawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001828 // This will set mOrientationChangeComplete and cause a pass through layout.
1829 setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001830 "checkAppWindowsReadyToShow: freezingScreen");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001831 } else {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001832 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001833
1834 // We can now show all of the drawn windows!
lumark588a3e82018-07-20 18:53:54 +08001835 if (!getDisplayContent().mOpeningApps.contains(this) && canShowWindows()) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001836 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001837 }
1838 }
1839 }
1840
Matthew Ng5d23afa2017-06-21 16:16:24 -07001841 /**
Bryce Leed390deb2017-06-22 13:14:28 -07001842 * Returns whether the drawn window states of this {@link AppWindowToken} has considered every
1843 * child {@link WindowState}. A child is considered if it has been passed into
1844 * {@link #updateDrawnWindowStates(WindowState)} after being added. This is used to determine
1845 * whether states, such as {@code allDrawn}, can be set, which relies on state variables such as
1846 * {@code mNumInterestingWindows}, which depend on all {@link WindowState}s being considered.
1847 *
1848 * @return {@code true} If all children have been considered, {@code false}.
1849 */
1850 private boolean allDrawnStatesConsidered() {
Bryce Lee6311c4b2017-07-06 14:09:29 -07001851 for (int i = mChildren.size() - 1; i >= 0; --i) {
1852 final WindowState child = mChildren.get(i);
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001853 if (child.mightAffectAllDrawn() && !child.getDrawnStateEvaluated()) {
Bryce Leed390deb2017-06-22 13:14:28 -07001854 return false;
1855 }
1856 }
1857 return true;
1858 }
1859
1860 /**
Matthew Ng5d23afa2017-06-21 16:16:24 -07001861 * Determines if the token has finished drawing. This should only be called from
1862 * {@link DisplayContent#applySurfaceChangesTransaction}
1863 */
Matthew Ng498c71d2017-04-18 13:55:45 -07001864 void updateAllDrawn() {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001865 if (!allDrawn) {
Matthew Ng498c71d2017-04-18 13:55:45 -07001866 // Number of drawn windows can be less when a window is being relaunched, wait for
Bryce Leed390deb2017-06-22 13:14:28 -07001867 // all windows to be launched and drawn for this token be considered all drawn.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001868 final int numInteresting = mNumInterestingWindows;
Bryce Leed390deb2017-06-22 13:14:28 -07001869
1870 // We must make sure that all present children have been considered (determined by
1871 // {@link #allDrawnStatesConsidered}) before evaluating whether everything has been
1872 // drawn.
1873 if (numInteresting > 0 && allDrawnStatesConsidered()
1874 && mNumDrawnWindows >= numInteresting && !isRelaunching()) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001875 if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawn: " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001876 + " interesting=" + numInteresting + " drawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001877 allDrawn = true;
1878 // Force an additional layout pass where
1879 // WindowStateAnimator#commitFinishDrawingLocked() will call performShowLocked().
Matthew Ng498c71d2017-04-18 13:55:45 -07001880 if (mDisplayContent != null) {
1881 mDisplayContent.setLayoutNeeded();
1882 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001883 mWmService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
Robert Carrecc06b32017-04-18 14:25:10 -07001884
Winson Chunge7ba6862017-05-24 12:13:33 -07001885 // Notify the pinned stack upon all windows drawn. If there was an animation in
1886 // progress then this signal will resume that animation.
Wale Ogunwale61911492017-10-11 08:50:50 -07001887 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
Winson Chunge7ba6862017-05-24 12:13:33 -07001888 if (pinnedStack != null) {
1889 pinnedStack.onAllWindowsDrawn();
Robert Carrecc06b32017-04-18 14:25:10 -07001890 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001891 }
1892 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001893 }
1894
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001895 boolean keyDispatchingTimedOut(String reason, int windowPid) {
1896 return mActivityRecord != null && mActivityRecord.keyDispatchingTimedOut(reason, windowPid);
1897 }
1898
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001899 /**
1900 * Updated this app token tracking states for interesting and drawn windows based on the window.
1901 *
1902 * @return Returns true if the input window is considered interesting and drawn while all the
1903 * windows in this app token where not considered drawn as of the last pass.
1904 */
1905 boolean updateDrawnWindowStates(WindowState w) {
Bryce Leed390deb2017-06-22 13:14:28 -07001906 w.setDrawnStateEvaluated(true /*evaluated*/);
1907
Jorim Jaggie4b0f282017-05-17 15:10:29 +02001908 if (DEBUG_STARTING_WINDOW_VERBOSE && w == startingWindow) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001909 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + w.isOnScreen()
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001910 + " allDrawn=" + allDrawn + " freezingScreen=" + mFreezingScreen);
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001911 }
1912
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001913 if (allDrawn && !mFreezingScreen) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001914 return false;
1915 }
1916
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001917 if (mLastTransactionSequence != mWmService.mTransactionSequence) {
1918 mLastTransactionSequence = mWmService.mTransactionSequence;
Matthew Ng53e66b22018-01-12 17:13:13 -08001919 mNumDrawnWindows = 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001920 startingDisplayed = false;
Matthew Ng53e66b22018-01-12 17:13:13 -08001921
1922 // There is the main base application window, even if it is exiting, wait for it
1923 mNumInterestingWindows = findMainWindow(false /* includeStartingApp */) != null ? 1 : 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001924 }
1925
1926 final WindowStateAnimator winAnimator = w.mWinAnimator;
1927
1928 boolean isInterestingAndDrawn = false;
1929
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001930 if (!allDrawn && w.mightAffectAllDrawn()) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001931 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
1932 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001933 + ", isAnimationSet=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001934 if (!w.isDrawnLw()) {
1935 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController
1936 + " pv=" + w.mPolicyVisibility
1937 + " mDrawState=" + winAnimator.drawStateToString()
1938 + " ph=" + w.isParentWindowHidden() + " th=" + hiddenRequested
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001939 + " a=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001940 }
1941 }
1942
1943 if (w != startingWindow) {
1944 if (w.isInteresting()) {
Matthew Ng53e66b22018-01-12 17:13:13 -08001945 // Add non-main window as interesting since the main app has already been added
1946 if (findMainWindow(false /* includeStartingApp */) != w) {
1947 mNumInterestingWindows++;
1948 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001949 if (w.isDrawnLw()) {
1950 mNumDrawnWindows++;
1951
1952 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, "tokenMayBeDrawn: "
1953 + this + " w=" + w + " numInteresting=" + mNumInterestingWindows
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001954 + " freezingScreen=" + mFreezingScreen
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001955 + " mAppFreezing=" + w.mAppFreezing);
1956
1957 isInterestingAndDrawn = true;
1958 }
1959 }
1960 } else if (w.isDrawnLw()) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001961 if (mActivityRecord != null) {
1962 mActivityRecord.onStartingWindowDrawn(SystemClock.uptimeMillis());
Jorim Jaggi3878ca32017-02-02 17:13:05 -08001963 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001964 startingDisplayed = true;
1965 }
1966 }
1967
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001968 return isInterestingAndDrawn;
1969 }
1970
Adrian Roos23df3a32018-03-15 15:41:13 +01001971 void layoutLetterbox(WindowState winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001972 final WindowState w = findMainWindow();
Adrian Roosf93b6d22018-03-21 13:48:26 +01001973 if (w == null || winHint != null && w != winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001974 return;
1975 }
Jorim Jaggia32da382018-03-28 18:01:22 +02001976 final boolean surfaceReady = w.isDrawnLw() // Regular case
Adrian Roosf93b6d22018-03-21 13:48:26 +01001977 || w.mWinAnimator.mSurfaceDestroyDeferred // The preserved surface is still ready.
1978 || w.isDragResizeChanged(); // Waiting for relayoutWindow to call preserveSurface.
1979 final boolean needsLetterbox = w.isLetterboxedAppWindow() && fillsParent() && surfaceReady;
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001980 if (needsLetterbox) {
1981 if (mLetterbox == null) {
1982 mLetterbox = new Letterbox(() -> makeChildSurface(null));
Riddle Hsu192fe762019-01-15 23:41:57 +08001983 mLetterbox.attachInput(w);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001984 }
Adrian Roos7af9d972018-11-30 15:26:27 +01001985 getPosition(mTmpPoint);
Evan Rosky4fb1e912019-03-06 13:54:43 -08001986 // Get the bounds of the "space-to-fill". We union the Task and the Stack bounds here
1987 // to handle both split window (where task-bounds can be larger) and orientation
1988 // letterbox (where the task is letterboxed within stack).
1989 Rect spaceToFill = getTask().getBounds();
1990 if (getStack() != null) {
1991 spaceToFill.union(getStack().getBounds());
1992 }
1993 mLetterbox.layout(spaceToFill, w.getFrameLw(), mTmpPoint);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001994 } else if (mLetterbox != null) {
Adrian Roos23df3a32018-03-15 15:41:13 +01001995 mLetterbox.hide();
1996 }
1997 }
1998
1999 void updateLetterboxSurface(WindowState winHint) {
2000 final WindowState w = findMainWindow();
2001 if (w != winHint && winHint != null && w != null) {
2002 return;
2003 }
2004 layoutLetterbox(winHint);
2005 if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) {
2006 mLetterbox.applySurfaceChanges(mPendingTransaction);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002007 }
2008 }
2009
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07002010 @Override
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002011 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002012 // For legacy reasons we process the TaskStack.mExitingAppTokens first in DisplayContent
2013 // before the non-exiting app tokens. So, we skip the exiting app tokens here.
2014 // TODO: Investigate if we need to continue to do this or if we can just process them
2015 // in-order.
2016 if (mIsExiting && !waitingForReplacement()) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002017 return false;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002018 }
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002019 return forAllWindowsUnchecked(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002020 }
2021
lumark588a3e82018-07-20 18:53:54 +08002022 @Override
2023 void forAllAppWindows(Consumer<AppWindowToken> callback) {
2024 callback.accept(this);
2025 }
2026
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002027 boolean forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback,
2028 boolean traverseTopToBottom) {
2029 return super.forAllWindows(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002030 }
2031
2032 @Override
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002033 AppWindowToken asAppWindowToken() {
2034 // I am an app window token!
2035 return this;
2036 }
2037
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002038 boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
2039 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
2040 IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
2041 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
2042 // If the display is frozen, we won't do anything until the actual window is
2043 // displayed so there is no reason to put in the starting window.
2044 if (!okToDisplay()) {
2045 return false;
2046 }
2047
2048 if (startingData != null) {
2049 return false;
2050 }
2051
2052 final WindowState mainWin = findMainWindow();
2053 if (mainWin != null && mainWin.mWinAnimator.getShown()) {
2054 // App already has a visible window...why would you want a starting window?
2055 return false;
2056 }
2057
2058 final ActivityManager.TaskSnapshot snapshot =
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002059 mWmService.mTaskSnapshotController.getSnapshot(
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002060 getTask().mTaskId, getTask().mUserId,
2061 false /* restoreFromDisk */, false /* reducedResolution */);
2062 final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
2063 allowTaskSnapshot, activityCreated, fromRecents, snapshot);
2064
2065 if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
2066 return createSnapshot(snapshot);
2067 }
2068
2069 // If this is a translucent window, then don't show a starting window -- the current
2070 // effect (a full-screen opaque starting window that fades away to the real contents
2071 // when it is ready) does not work for this.
2072 if (DEBUG_STARTING_WINDOW) {
2073 Slog.v(TAG, "Checking theme of starting window: 0x" + Integer.toHexString(theme));
2074 }
2075 if (theme != 0) {
2076 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
2077 com.android.internal.R.styleable.Window,
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002078 mWmService.mCurrentUserId);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002079 if (ent == null) {
2080 // Whoops! App doesn't exist. Um. Okay. We'll just pretend like we didn't
2081 // see that.
2082 return false;
2083 }
2084 final boolean windowIsTranslucent = ent.array.getBoolean(
2085 com.android.internal.R.styleable.Window_windowIsTranslucent, false);
2086 final boolean windowIsFloating = ent.array.getBoolean(
2087 com.android.internal.R.styleable.Window_windowIsFloating, false);
2088 final boolean windowShowWallpaper = ent.array.getBoolean(
2089 com.android.internal.R.styleable.Window_windowShowWallpaper, false);
2090 final boolean windowDisableStarting = ent.array.getBoolean(
2091 com.android.internal.R.styleable.Window_windowDisablePreview, false);
2092 if (DEBUG_STARTING_WINDOW) {
2093 Slog.v(TAG, "Translucent=" + windowIsTranslucent
2094 + " Floating=" + windowIsFloating
2095 + " ShowWallpaper=" + windowShowWallpaper);
2096 }
2097 if (windowIsTranslucent) {
2098 return false;
2099 }
2100 if (windowIsFloating || windowDisableStarting) {
2101 return false;
2102 }
2103 if (windowShowWallpaper) {
2104 if (getDisplayContent().mWallpaperController
2105 .getWallpaperTarget() == null) {
2106 // If this theme is requesting a wallpaper, and the wallpaper
2107 // is not currently visible, then this effectively serves as
2108 // an opaque window and our starting window transition animation
2109 // can still work. We just need to make sure the starting window
2110 // is also showing the wallpaper.
2111 windowFlags |= FLAG_SHOW_WALLPAPER;
2112 } else {
2113 return false;
2114 }
2115 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002116 }
Yunfan Chen8a8c0ed2018-12-18 16:46:32 -08002117
2118 if (transferStartingWindow(transferFrom)) {
2119 return true;
2120 }
2121
2122 // There is no existing starting window, and we don't want to create a splash screen, so
2123 // that's it!
2124 if (type != STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
2125 return false;
2126 }
2127
2128 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SplashScreenStartingData");
2129 startingData = new SplashScreenStartingData(mWmService, pkg,
2130 theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
2131 getMergedOverrideConfiguration());
2132 scheduleAddStartingWindow();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002133 return true;
2134 }
2135
2136
2137 private boolean createSnapshot(ActivityManager.TaskSnapshot snapshot) {
2138 if (snapshot == null) {
2139 return false;
2140 }
2141
2142 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SnapshotStartingData");
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002143 startingData = new SnapshotStartingData(mWmService, snapshot);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002144 scheduleAddStartingWindow();
2145 return true;
2146 }
2147
2148 void scheduleAddStartingWindow() {
2149 // Note: we really want to do sendMessageAtFrontOfQueue() because we
2150 // want to process the message ASAP, before any other queued
2151 // messages.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002152 if (!mWmService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002153 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING");
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002154 mWmService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002155 }
2156 }
2157
2158 private final Runnable mAddStartingWindow = new Runnable() {
2159
2160 @Override
2161 public void run() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002162 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002163 // There can only be one adding request, silly caller!
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002164 mWmService.mAnimationHandler.removeCallbacks(this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002165 }
2166
2167 if (startingData == null) {
2168 // Animation has been canceled... do nothing.
2169 if (DEBUG_STARTING_WINDOW) {
2170 Slog.v(TAG, "startingData was nulled out before handling"
2171 + " mAddStartingWindow: " + AppWindowToken.this);
2172 }
2173 return;
2174 }
2175
2176 if (DEBUG_STARTING_WINDOW) {
2177 Slog.v(TAG, "Add starting " + this + ": startingData=" + startingData);
2178 }
2179
2180 WindowManagerPolicy.StartingSurface surface = null;
2181 try {
2182 surface = startingData.createStartingSurface(AppWindowToken.this);
2183 } catch (Exception e) {
2184 Slog.w(TAG, "Exception when adding starting window", e);
2185 }
2186 if (surface != null) {
2187 boolean abort = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002188 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002189 // If the window was successfully added, then
2190 // we need to remove it.
2191 if (removed || startingData == null) {
2192 if (DEBUG_STARTING_WINDOW) {
2193 Slog.v(TAG, "Aborted starting " + AppWindowToken.this
2194 + ": removed=" + removed + " startingData=" + startingData);
2195 }
2196 startingWindow = null;
2197 startingData = null;
2198 abort = true;
2199 } else {
2200 startingSurface = surface;
2201 }
2202 if (DEBUG_STARTING_WINDOW && !abort) {
2203 Slog.v(TAG, "Added starting " + AppWindowToken.this + ": startingWindow="
2204 + startingWindow + " startingView=" + startingSurface);
2205 }
2206 }
2207 if (abort) {
2208 surface.remove();
2209 }
2210 } else if (DEBUG_STARTING_WINDOW) {
2211 Slog.v(TAG, "Surface returned was null: " + AppWindowToken.this);
2212 }
2213 }
2214 };
2215
2216 private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
2217 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents,
2218 ActivityManager.TaskSnapshot snapshot) {
2219 if (getDisplayContent().mAppTransition.getAppTransition()
2220 == TRANSIT_DOCK_TASK_FROM_RECENTS) {
2221 // TODO(b/34099271): Remove this statement to add back the starting window and figure
2222 // out why it causes flickering, the starting window appears over the thumbnail while
2223 // the docked from recents transition occurs
2224 return STARTING_WINDOW_TYPE_NONE;
2225 } else if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
2226 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2227 } else if (taskSwitch && allowTaskSnapshot) {
Kevin716a9db2018-12-18 16:53:39 -08002228 if (mWmService.mLowRamTaskSnapshotsAndRecents) {
Kevin58b47f12018-12-17 14:09:01 -08002229 // For low RAM devices, we use the splash screen starting window instead of the
2230 // task snapshot starting window.
2231 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2232 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002233 return snapshot == null ? STARTING_WINDOW_TYPE_NONE
2234 : snapshotOrientationSameAsTask(snapshot) || fromRecents
2235 ? STARTING_WINDOW_TYPE_SNAPSHOT : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2236 } else {
2237 return STARTING_WINDOW_TYPE_NONE;
2238 }
2239 }
2240
2241
2242 private boolean snapshotOrientationSameAsTask(ActivityManager.TaskSnapshot snapshot) {
2243 if (snapshot == null) {
2244 return false;
2245 }
2246 return getTask().getConfiguration().orientation == snapshot.getOrientation();
2247 }
2248
2249 void removeStartingWindow() {
2250 if (startingWindow == null) {
2251 if (startingData != null) {
2252 // Starting window has not been added yet, but it is scheduled to be added.
2253 // Go ahead and cancel the request.
2254 if (DEBUG_STARTING_WINDOW) {
2255 Slog.v(TAG_WM, "Clearing startingData for token=" + this);
2256 }
2257 startingData = null;
2258 }
2259 return;
2260 }
2261
2262 final WindowManagerPolicy.StartingSurface surface;
2263 if (startingData != null) {
2264 surface = startingSurface;
2265 startingData = null;
2266 startingSurface = null;
2267 startingWindow = null;
2268 startingDisplayed = false;
2269 if (surface == null) {
2270 if (DEBUG_STARTING_WINDOW) {
2271 Slog.v(TAG_WM, "startingWindow was set but startingSurface==null, couldn't "
2272 + "remove");
2273 }
2274 return;
2275 }
2276 } else {
2277 if (DEBUG_STARTING_WINDOW) {
2278 Slog.v(TAG_WM, "Tried to remove starting window but startingWindow was null:"
2279 + this);
2280 }
2281 return;
2282 }
2283
2284 if (DEBUG_STARTING_WINDOW) {
2285 Slog.v(TAG_WM, "Schedule remove starting " + this
2286 + " startingWindow=" + startingWindow
2287 + " startingView=" + startingSurface
2288 + " Callers=" + Debug.getCallers(5));
2289 }
2290
2291 // Use the same thread to remove the window as we used to add it, as otherwise we end up
2292 // with things in the view hierarchy being called from different threads.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002293 mWmService.mAnimationHandler.post(() -> {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002294 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Removing startingView=" + surface);
2295 try {
2296 surface.remove();
2297 } catch (Exception e) {
2298 Slog.w(TAG_WM, "Exception when removing starting window", e);
2299 }
2300 });
2301 }
2302
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002303 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -07002304 boolean fillsParent() {
2305 return mFillsParent;
2306 }
2307
2308 void setFillsParent(boolean fillsParent) {
2309 mFillsParent = fillsParent;
2310 }
2311
Jorim Jaggife762342016-10-13 14:33:27 +02002312 boolean containsDismissKeyguardWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002313 // Window state is transient during relaunch. We are not guaranteed to be frozen during the
2314 // entirety of the relaunch.
2315 if (isRelaunching()) {
2316 return mLastContainsDismissKeyguardWindow;
2317 }
2318
Jorim Jaggife762342016-10-13 14:33:27 +02002319 for (int i = mChildren.size() - 1; i >= 0; i--) {
2320 if ((mChildren.get(i).mAttrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
2321 return true;
2322 }
2323 }
2324 return false;
2325 }
2326
2327 boolean containsShowWhenLockedWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002328 // When we are relaunching, it is possible for us to be unfrozen before our previous
2329 // windows have been added back. Using the cached value ensures that our previous
2330 // showWhenLocked preference is honored until relaunching is complete.
2331 if (isRelaunching()) {
2332 return mLastContainsShowWhenLockedWindow;
2333 }
2334
Jorim Jaggife762342016-10-13 14:33:27 +02002335 for (int i = mChildren.size() - 1; i >= 0; i--) {
2336 if ((mChildren.get(i).mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
2337 return true;
2338 }
2339 }
Bryce Lee081554b2017-05-25 07:52:12 -07002340
Jorim Jaggife762342016-10-13 14:33:27 +02002341 return false;
2342 }
2343
2344 void checkKeyguardFlagsChanged() {
2345 final boolean containsDismissKeyguard = containsDismissKeyguardWindow();
2346 final boolean containsShowWhenLocked = containsShowWhenLockedWindow();
2347 if (containsDismissKeyguard != mLastContainsDismissKeyguardWindow
2348 || containsShowWhenLocked != mLastContainsShowWhenLockedWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002349 mWmService.notifyKeyguardFlagsChanged(null /* callback */,
lumark588a3e82018-07-20 18:53:54 +08002350 getDisplayContent().getDisplayId());
Jorim Jaggife762342016-10-13 14:33:27 +02002351 }
2352 mLastContainsDismissKeyguardWindow = containsDismissKeyguard;
2353 mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
2354 }
2355
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002356 WindowState getImeTargetBelowWindow(WindowState w) {
2357 final int index = mChildren.indexOf(w);
2358 if (index > 0) {
2359 final WindowState target = mChildren.get(index - 1);
2360 if (target.canBeImeTarget()) {
2361 return target;
2362 }
2363 }
2364 return null;
2365 }
2366
2367 WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
2368 WindowState candidate = null;
2369 for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
2370 final WindowState w = mChildren.get(i);
2371 if (w.mRemoved) {
2372 continue;
2373 }
Jorim Jaggi35d328a2018-08-14 17:00:20 +02002374 if (candidate == null) {
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002375 candidate = w;
2376 }
2377 }
2378 return candidate;
2379 }
2380
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002381 /**
2382 * See {@link Activity#setDisablePreviewScreenshots}.
2383 */
2384 void setDisablePreviewScreenshots(boolean disable) {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002385 mDisablePreviewScreenshots = disable;
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002386 }
2387
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002388 /**
chaviwd3bf08d2017-08-01 17:24:59 -07002389 * Sets whether the current launch can turn the screen on. See {@link #canTurnScreenOn()}
2390 */
2391 void setCanTurnScreenOn(boolean canTurnScreenOn) {
2392 mCanTurnScreenOn = canTurnScreenOn;
2393 }
2394
2395 /**
2396 * Indicates whether the current launch can turn the screen on. This is to prevent multiple
2397 * relayouts from turning the screen back on. The screen should only turn on at most
2398 * once per activity resume.
2399 *
2400 * @return true if the screen can be turned on.
2401 */
2402 boolean canTurnScreenOn() {
2403 return mCanTurnScreenOn;
2404 }
2405
2406 /**
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002407 * Retrieves whether we'd like to generate a snapshot that's based solely on the theme. This is
2408 * the case when preview screenshots are disabled {@link #setDisablePreviewScreenshots} or when
2409 * we can't take a snapshot for other reasons, for example, if we have a secure window.
2410 *
2411 * @return True if we need to generate an app theme snapshot, false if we'd like to take a real
2412 * screenshot.
2413 */
2414 boolean shouldUseAppThemeSnapshot() {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002415 return mDisablePreviewScreenshots || forAllWindows(w -> (w.mAttrs.flags & FLAG_SECURE) != 0,
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002416 true /* topToBottom */);
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002417 }
2418
Jorim Jaggibe418292018-03-26 16:14:12 +02002419 SurfaceControl getAppAnimationLayer() {
Jorim Jaggi391790622018-04-18 15:30:44 +02002420 return getAppAnimationLayer(isActivityTypeHome() ? ANIMATION_LAYER_HOME
2421 : needsZBoost() ? ANIMATION_LAYER_BOOSTED
2422 : ANIMATION_LAYER_STANDARD);
Jorim Jaggibe418292018-03-26 16:14:12 +02002423 }
2424
chaviw23ee71c2017-12-18 11:29:41 -08002425 @Override
Jorim Jaggi596a1992017-12-29 14:48:02 +01002426 public SurfaceControl getAnimationLeashParent() {
Robert Carrb9506032018-02-13 13:54:00 -08002427 // All normal app transitions take place in an animation layer which is below the pinned
2428 // stack but may be above the parent stacks of the given animating apps.
2429 // For transitions in the pinned stack (menu activity) we just let them occur as a child
2430 // of the pinned stack.
2431 if (!inPinnedWindowingMode()) {
2432 return getAppAnimationLayer();
2433 } else {
2434 return getStack().getSurfaceControl();
2435 }
chaviw23ee71c2017-12-18 11:29:41 -08002436 }
2437
Jorim Jaggic6976f02018-04-18 16:31:07 +02002438 private boolean shouldAnimate(int transit) {
2439 final boolean isSplitScreenPrimary =
2440 getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
2441 final boolean allowSplitScreenPrimaryAnimation = transit != TRANSIT_WALLPAPER_OPEN;
2442
lumark54284462019-03-05 20:44:27 +08002443 // Don't animate when the task runs recents animation.
2444 final RecentsAnimationController controller = mWmService.getRecentsAnimationController();
2445 if (controller != null && controller.isAnimatingTask(getTask())) {
2446 return false;
2447 }
2448
Jorim Jaggic6976f02018-04-18 16:31:07 +02002449 // We animate always if it's not split screen primary, and only some special cases in split
2450 // screen primary because it causes issues with stack clipping when we run an un-minimize
2451 // animation at the same time.
2452 return !isSplitScreenPrimary || allowSplitScreenPrimaryAnimation;
2453 }
2454
Vishnu Naira2977262018-07-26 13:31:26 -07002455 /**
2456 * Creates a layer to apply crop to an animation.
2457 */
2458 private SurfaceControl createAnimationBoundsLayer(Transaction t) {
2459 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.i(TAG, "Creating animation bounds layer");
2460 final SurfaceControl.Builder builder = makeAnimationLeash()
2461 .setParent(getAnimationLeashParent())
Vishnu Naire86bd982018-11-28 13:23:17 -08002462 .setName(getSurfaceControl() + " - animation-bounds");
Vishnu Naira2977262018-07-26 13:31:26 -07002463 final SurfaceControl boundsLayer = builder.build();
2464 t.show(boundsLayer);
2465 return boundsLayer;
2466 }
2467
Evan Roskyed6767f2018-10-26 17:21:06 -07002468 @Override
2469 Rect getDisplayedBounds() {
2470 final Task task = getTask();
2471 if (task != null) {
2472 final Rect overrideDisplayedBounds = task.getOverrideDisplayedBounds();
2473 if (!overrideDisplayedBounds.isEmpty()) {
2474 return overrideDisplayedBounds;
2475 }
2476 }
2477 return getBounds();
2478 }
2479
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002480 boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter,
2481 boolean isVoiceInteraction) {
2482
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002483 if (mWmService.mDisableTransitionAnimation || !shouldAnimate(transit)) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002484 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
Jorim Jaggic6976f02018-04-18 16:31:07 +02002485 Slog.v(TAG_WM, "applyAnimation: transition animation is disabled or skipped."
2486 + " atoken=" + this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002487 }
2488 cancelAnimation();
2489 return false;
2490 }
2491
2492 // Only apply an animation if the display isn't frozen. If it is frozen, there is no reason
2493 // to animate and it can cause strange artifacts when we unfreeze the display if some
2494 // different animation is running.
2495 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#applyAnimationLocked");
2496 if (okToAnimate()) {
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002497 final AnimationAdapter adapter;
Evan Rosky2289ba12018-11-19 18:28:18 -08002498 AnimationAdapter thumbnailAdapter = null;
Evan Rosky4fb1e912019-03-06 13:54:43 -08002499
2500 // Separate position and size for use in animators. Use task-bounds for now so
2501 // that activity-level letterbox (maxAspectRatio) is included in the animation.
2502 mTmpRect.set(getTask() != null ? getTask().getBounds() : getBounds());
2503 mTmpPoint.set(mTmpRect.left, mTmpRect.top);
2504 mTmpRect.offsetTo(0, 0);
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002505
Evan Roskyec9488c2019-03-01 19:32:12 -08002506 final boolean isChanging = AppTransition.isChangeTransit(transit) && enter
2507 && getDisplayContent().mChangingApps.contains(this);
Evan Rosky2289ba12018-11-19 18:28:18 -08002508
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002509 // Delaying animation start isn't compatible with remote animations at all.
lumark588a3e82018-07-20 18:53:54 +08002510 if (getDisplayContent().mAppTransition.getRemoteAnimationController() != null
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002511 && !mSurfaceAnimator.isAnimationStartDelayed()) {
Evan Rosky2289ba12018-11-19 18:28:18 -08002512 RemoteAnimationRecord adapters =
2513 getDisplayContent().mAppTransition.getRemoteAnimationController()
2514 .createRemoteAnimationRecord(this, mTmpPoint, mTmpRect,
2515 (isChanging ? mTransitStartRect : null));
2516 adapter = adapters.mAdapter;
2517 thumbnailAdapter = adapters.mThumbnailAdapter;
2518 } else if (isChanging) {
Evan Roskycf76bed2019-01-15 10:33:58 -08002519 final float durationScale = mWmService.getTransitionAnimationScaleLocked();
Evan Rosky2289ba12018-11-19 18:28:18 -08002520 mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y);
2521 adapter = new LocalAnimationAdapter(
2522 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
Evan Roskycf76bed2019-01-15 10:33:58 -08002523 getDisplayContent().getDisplayInfo(), durationScale,
Evan Rosky2289ba12018-11-19 18:28:18 -08002524 true /* isAppAnimation */, false /* isThumbnail */),
2525 mWmService.mSurfaceAnimationRunner);
Evan Rosky966759f2019-01-15 10:33:58 -08002526 if (mThumbnail != null) {
2527 thumbnailAdapter = new LocalAnimationAdapter(
2528 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
Evan Roskycf76bed2019-01-15 10:33:58 -08002529 getDisplayContent().getDisplayInfo(), durationScale,
Evan Rosky966759f2019-01-15 10:33:58 -08002530 true /* isAppAnimation */, true /* isThumbnail */),
2531 mWmService.mSurfaceAnimationRunner);
2532 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002533 mTransit = transit;
2534 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002535 } else {
lumark588a3e82018-07-20 18:53:54 +08002536 final int appStackClipMode =
2537 getDisplayContent().mAppTransition.getAppStackClipMode();
Vishnu Naira2977262018-07-26 13:31:26 -07002538 mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM);
2539
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002540 final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
2541 if (a != null) {
2542 adapter = new LocalAnimationAdapter(
2543 new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
lumark588a3e82018-07-20 18:53:54 +08002544 getDisplayContent().mAppTransition.canSkipFirstFrame(),
Vishnu Naira2977262018-07-26 13:31:26 -07002545 appStackClipMode,
Lucas Dupin3e1dc202018-12-02 15:14:20 -08002546 true /* isAppAnimation */,
2547 mWmService.mWindowCornerRadius),
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002548 mWmService.mSurfaceAnimationRunner);
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002549 if (a.getZAdjustment() == Animation.ZORDER_TOP) {
2550 mNeedsZBoost = true;
2551 }
2552 mTransit = transit;
lumark588a3e82018-07-20 18:53:54 +08002553 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002554 } else {
2555 adapter = null;
chaviw23ee71c2017-12-18 11:29:41 -08002556 }
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002557 }
2558 if (adapter != null) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002559 startAnimation(getPendingTransaction(), adapter, !isVisible());
Jorim Jaggi82c17862018-02-21 17:50:18 +01002560 if (adapter.getShowWallpaper()) {
2561 mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2562 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002563 if (thumbnailAdapter != null) {
2564 mThumbnail.startAnimation(
2565 getPendingTransaction(), thumbnailAdapter, !isVisible());
2566 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002567 }
2568 } else {
2569 cancelAnimation();
2570 }
2571 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2572
2573 return isReallyAnimating();
2574 }
2575
2576 private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
2577 boolean isVoiceInteraction) {
2578 final DisplayContent displayContent = getTask().getDisplayContent();
2579 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2580 final int width = displayInfo.appWidth;
2581 final int height = displayInfo.appHeight;
2582 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG_WM,
2583 "applyAnimation: atoken=" + this);
2584
2585 // Determine the visible rect to calculate the thumbnail clip
2586 final WindowState win = findMainWindow();
2587 final Rect frame = new Rect(0, 0, width, height);
2588 final Rect displayFrame = new Rect(0, 0,
2589 displayInfo.logicalWidth, displayInfo.logicalHeight);
2590 final Rect insets = new Rect();
2591 final Rect stableInsets = new Rect();
2592 Rect surfaceInsets = null;
2593 final boolean freeform = win != null && win.inFreeformWindowingMode();
2594 if (win != null) {
2595 // Containing frame will usually cover the whole screen, including dialog windows.
2596 // For freeform workspace windows it will not cover the whole screen and it also
2597 // won't exactly match the final freeform window frame (e.g. when overlapping with
2598 // the status bar). In that case we need to use the final frame.
2599 if (freeform) {
chaviw492139a2018-07-16 16:07:35 -07002600 frame.set(win.getFrameLw());
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002601 } else if (win.isLetterboxedAppWindow()) {
2602 frame.set(getTask().getBounds());
Winson Chungc1674272018-02-21 10:15:17 -08002603 } else if (win.isDockedResizing()) {
2604 // If we are animating while docked resizing, then use the stack bounds as the
2605 // animation target (which will be different than the task bounds)
2606 frame.set(getTask().getParent().getBounds());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002607 } else {
chaviw553b0212018-07-12 13:37:01 -07002608 frame.set(win.getContainingFrame());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002609 }
2610 surfaceInsets = win.getAttrs().surfaceInsets;
Adrian Roos20e07892018-02-23 19:12:01 +01002611 // XXX(b/72757033): These are insets relative to the window frame, but we're really
2612 // interested in the insets relative to the frame we chose in the if-blocks above.
chaviw9c81e632018-07-31 11:17:52 -07002613 win.getContentInsets(insets);
2614 win.getStableInsets(stableInsets);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002615 }
2616
2617 if (mLaunchTaskBehind) {
2618 // Differentiate the two animations. This one which is briefly on the screen
2619 // gets the !enter animation, and the other activity which remains on the
2620 // screen gets the enter animation. Both appear in the mOpeningApps set.
2621 enter = false;
2622 }
2623 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "Loading animation for app transition."
2624 + " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter
2625 + " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets);
2626 final Configuration displayConfig = displayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08002627 final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002628 displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
2629 surfaceInsets, stableInsets, isVoiceInteraction, freeform, getTask().mTaskId);
2630 if (a != null) {
2631 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
2632 final int containingWidth = frame.width();
2633 final int containingHeight = frame.height();
2634 a.initialize(containingWidth, containingHeight, width, height);
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002635 a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002636 }
2637 return a;
2638 }
2639
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002640 @Override
Jorim Jaggi6de61012018-03-19 14:53:23 +01002641 public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
2642 return mAnimatingAppWindowTokenRegistry != null
2643 && mAnimatingAppWindowTokenRegistry.notifyAboutToFinish(
2644 this, endDeferFinishCallback);
2645 }
2646
2647 @Override
2648 public void onAnimationLeashDestroyed(Transaction t) {
2649 super.onAnimationLeashDestroyed(t);
Vishnu Naira2977262018-07-26 13:31:26 -07002650 if (mAnimationBoundsLayer != null) {
Robert Carr71200f22019-02-05 09:44:53 -08002651 t.remove(mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002652 mAnimationBoundsLayer = null;
2653 }
2654
Jorim Jaggi6de61012018-03-19 14:53:23 +01002655 if (mAnimatingAppWindowTokenRegistry != null) {
2656 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
2657 }
2658 }
2659
2660 @Override
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002661 protected void setLayer(Transaction t, int layer) {
2662 if (!mSurfaceAnimator.hasLeash()) {
2663 t.setLayer(mSurfaceControl, layer);
2664 }
2665 }
2666
2667 @Override
2668 protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
2669 if (!mSurfaceAnimator.hasLeash()) {
2670 t.setRelativeLayer(mSurfaceControl, relativeTo, layer);
2671 }
2672 }
2673
2674 @Override
2675 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
2676 if (!mSurfaceAnimator.hasLeash()) {
Robert Carr10584fa2019-01-14 15:55:19 -08002677 t.reparent(mSurfaceControl, newParent);
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002678 }
2679 }
2680
2681 @Override
2682 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002683 // The leash is parented to the animation layer. We need to preserve the z-order by using
2684 // the prefix order index, but we boost if necessary.
Robert Carrb9506032018-02-13 13:54:00 -08002685 int layer = 0;
2686 if (!inPinnedWindowingMode()) {
2687 layer = getPrefixOrderIndex();
2688 } else {
2689 // Pinned stacks have animations take place within themselves rather than an animation
2690 // layer so we need to preserve the order relative to the stack (e.g. the order of our
2691 // task/parent).
2692 layer = getParent().getPrefixOrderIndex();
2693 }
2694
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002695 if (mNeedsZBoost) {
2696 layer += Z_BOOST_BASE;
2697 }
2698 leash.setLayer(layer);
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);
2735
2736 // Reparent leash to animation bounds layer.
Robert Carr10584fa2019-01-14 15:55:19 -08002737 t.reparent(leash, mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002738 }
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002739 }
2740
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002741 /**
2742 * This must be called while inside a transaction.
2743 */
2744 void showAllWindowsLocked() {
2745 forAllWindows(windowState -> {
2746 if (DEBUG_VISIBILITY) Slog.v(TAG, "performing show on: " + windowState);
2747 windowState.performShowLocked();
2748 }, false /* traverseTopToBottom */);
Jorim Jaggia5e10572017-11-15 14:36:26 +01002749 }
2750
2751 @Override
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002752 protected void onAnimationFinished() {
2753 super.onAnimationFinished();
2754
2755 mTransit = TRANSIT_UNSET;
2756 mTransitFlags = 0;
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002757 mNeedsZBoost = false;
Vishnu Naira2977262018-07-26 13:31:26 -07002758 mNeedsAnimationBoundsLayer = false;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002759
2760 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER,
2761 "AppWindowToken");
2762
Jorim Jaggi988f6682017-11-17 17:46:43 +01002763 clearThumbnail();
Jorim Jaggi752cd822018-03-29 16:29:18 +02002764 setClientHidden(isHidden() && hiddenRequested);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002765
lumarkff0ab692018-11-05 20:32:30 +08002766 getDisplayContent().computeImeTargetIfNeeded(this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002767
2768 if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + this
2769 + ": reportedVisible=" + reportedVisible
2770 + " okToDisplay=" + okToDisplay()
2771 + " okToAnimate=" + okToAnimate()
2772 + " startingDisplayed=" + startingDisplayed);
2773
Evan Rosky2289ba12018-11-19 18:28:18 -08002774 // clean up thumbnail window
2775 if (mThumbnail != null) {
2776 mThumbnail.destroy();
2777 mThumbnail = null;
2778 }
2779
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002780 // WindowState.onExitAnimationDone might modify the children list, so make a copy and then
2781 // traverse the copy.
2782 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
2783 children.forEach(WindowState::onExitAnimationDone);
2784
lumark588a3e82018-07-20 18:53:54 +08002785 getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002786 scheduleAnimation();
Jorim Jaggi9b5e3312019-03-01 18:08:00 +01002787
2788 mActivityRecord.onAnimationFinished();
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002789 }
2790
2791 @Override
2792 boolean isAppAnimating() {
2793 return isSelfAnimating();
2794 }
2795
2796 @Override
2797 boolean isSelfAnimating() {
2798 // If we are about to start a transition, we also need to be considered animating.
2799 return isWaitingForTransitionStart() || isReallyAnimating();
2800 }
2801
2802 /**
2803 * @return True if and only if we are actually running an animation. Note that
2804 * {@link #isSelfAnimating} also returns true if we are waiting for an animation to
2805 * start.
2806 */
2807 private boolean isReallyAnimating() {
2808 return super.isSelfAnimating();
2809 }
2810
Evan Rosky25b56192019-02-06 16:10:56 -08002811 /**
2812 * @param cancel {@code true} if clearing the leash due to cancelling instead of transferring
2813 * to another leash.
2814 */
2815 private void clearChangeLeash(Transaction t, boolean cancel) {
2816 if (mTransitChangeLeash == null) {
2817 return;
2818 }
2819 if (cancel) {
2820 clearThumbnail();
2821 SurfaceControl sc = getSurfaceControl();
2822 SurfaceControl parentSc = getParentSurfaceControl();
2823 // Don't reparent if surface is getting destroyed
2824 if (parentSc != null && sc != null) {
2825 t.reparent(sc, getParentSurfaceControl());
2826 }
2827 }
2828 t.hide(mTransitChangeLeash);
2829 t.reparent(mTransitChangeLeash, null);
2830 mTransitChangeLeash = null;
2831 if (cancel) {
2832 onAnimationLeashDestroyed(t);
2833 }
2834 }
2835
Jorim Jaggi988f6682017-11-17 17:46:43 +01002836 @Override
2837 void cancelAnimation() {
Evan Rosky2289ba12018-11-19 18:28:18 -08002838 cancelAnimationOnly();
Jorim Jaggi988f6682017-11-17 17:46:43 +01002839 clearThumbnail();
Evan Rosky25b56192019-02-06 16:10:56 -08002840 clearChangeLeash(getPendingTransaction(), true /* cancel */);
Evan Rosky2289ba12018-11-19 18:28:18 -08002841 }
2842
2843 /**
2844 * This only cancels the animation. It doesn't do other teardown like cleaning-up thumbnail
2845 * or interim leashes.
2846 * <p>
2847 * Used when canceling in preparation for starting a new animation.
2848 */
2849 void cancelAnimationOnly() {
2850 super.cancelAnimation();
Jorim Jaggi988f6682017-11-17 17:46:43 +01002851 }
2852
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002853 boolean isWaitingForTransitionStart() {
lumark588a3e82018-07-20 18:53:54 +08002854 return getDisplayContent().mAppTransition.isTransitionSet()
2855 && (getDisplayContent().mOpeningApps.contains(this)
Evan Rosky2289ba12018-11-19 18:28:18 -08002856 || getDisplayContent().mClosingApps.contains(this)
2857 || getDisplayContent().mChangingApps.contains(this));
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002858 }
2859
2860 public int getTransit() {
2861 return mTransit;
2862 }
2863
2864 int getTransitFlags() {
2865 return mTransitFlags;
2866 }
2867
Jorim Jaggi988f6682017-11-17 17:46:43 +01002868 void attachThumbnailAnimation() {
2869 if (!isReallyAnimating()) {
2870 return;
2871 }
2872 final int taskId = getTask().mTaskId;
2873 final GraphicBuffer thumbnailHeader =
lumark588a3e82018-07-20 18:53:54 +08002874 getDisplayContent().mAppTransition.getAppTransitionThumbnailHeader(taskId);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002875 if (thumbnailHeader == null) {
2876 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG, "No thumbnail header bitmap for: " + taskId);
2877 return;
2878 }
2879 clearThumbnail();
2880 mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnailHeader);
2881 mThumbnail.startAnimation(getPendingTransaction(), loadThumbnailAnimation(thumbnailHeader));
2882 }
2883
Tony Mak64b8d562017-12-28 17:44:02 +00002884 /**
2885 * Attaches a surface with a thumbnail for the
2886 * {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation.
2887 */
2888 void attachCrossProfileAppsThumbnailAnimation() {
2889 if (!isReallyAnimating()) {
2890 return;
2891 }
2892 clearThumbnail();
2893
2894 final WindowState win = findMainWindow();
2895 if (win == null) {
2896 return;
2897 }
chaviw492139a2018-07-16 16:07:35 -07002898 final Rect frame = win.getFrameLw();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002899 final int thumbnailDrawableRes = getTask().mUserId == mWmService.mCurrentUserId
Tony Mak64b8d562017-12-28 17:44:02 +00002900 ? R.drawable.ic_account_circle
Tony Makda4af232018-04-27 11:01:10 +01002901 : R.drawable.ic_corp_badge;
Tony Mak64b8d562017-12-28 17:44:02 +00002902 final GraphicBuffer thumbnail =
lumark588a3e82018-07-20 18:53:54 +08002903 getDisplayContent().mAppTransition
Tony Mak64b8d562017-12-28 17:44:02 +00002904 .createCrossProfileAppsThumbnail(thumbnailDrawableRes, frame);
2905 if (thumbnail == null) {
2906 return;
2907 }
2908 mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnail);
2909 final Animation animation =
lumark588a3e82018-07-20 18:53:54 +08002910 getDisplayContent().mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(
chaviw492139a2018-07-16 16:07:35 -07002911 win.getFrameLw());
Tony Mak64b8d562017-12-28 17:44:02 +00002912 mThumbnail.startAnimation(getPendingTransaction(), animation, new Point(frame.left,
2913 frame.top));
2914 }
2915
Jorim Jaggi988f6682017-11-17 17:46:43 +01002916 private Animation loadThumbnailAnimation(GraphicBuffer thumbnailHeader) {
2917 final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
2918
2919 // If this is a multi-window scenario, we use the windows frame as
2920 // destination of the thumbnail header animation. If this is a full screen
2921 // window scenario, we use the whole display as the target.
2922 WindowState win = findMainWindow();
2923 Rect appRect = win != null ? win.getContentFrameLw() :
2924 new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
chaviw9c81e632018-07-31 11:17:52 -07002925 final Rect insets = win != null ? win.getContentInsets() : null;
Jorim Jaggi988f6682017-11-17 17:46:43 +01002926 final Configuration displayConfig = mDisplayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08002927 return getDisplayContent().mAppTransition.createThumbnailAspectScaleAnimationLocked(
Jorim Jaggi988f6682017-11-17 17:46:43 +01002928 appRect, insets, thumbnailHeader, getTask().mTaskId, displayConfig.uiMode,
2929 displayConfig.orientation);
2930 }
2931
2932 private void clearThumbnail() {
2933 if (mThumbnail == null) {
2934 return;
2935 }
2936 mThumbnail.destroy();
2937 mThumbnail = null;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002938 }
2939
Jorim Jaggif84e2f62018-01-16 14:17:59 +01002940 void registerRemoteAnimations(RemoteAnimationDefinition definition) {
2941 mRemoteAnimationDefinition = definition;
2942 }
2943
2944 RemoteAnimationDefinition getRemoteAnimationDefinition() {
2945 return mRemoteAnimationDefinition;
2946 }
2947
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002948 @Override
2949 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
2950 super.dump(pw, prefix, dumpAll);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002951 if (appToken != null) {
Wale Ogunwale72919d22016-12-08 18:58:50 -08002952 pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002953 }
Winson Chung48b25652018-10-22 14:04:30 -07002954 pw.println(prefix + "component=" + mActivityComponent.flattenToShortString());
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08002955 pw.print(prefix); pw.print("task="); pw.println(getTask());
Wale Ogunwale51362492016-09-08 17:49:17 -07002956 pw.print(prefix); pw.print(" mFillsParent="); pw.print(mFillsParent);
2957 pw.print(" mOrientation="); pw.println(mOrientation);
Wale Ogunwale89973222017-04-23 18:39:45 -07002958 pw.println(prefix + "hiddenRequested=" + hiddenRequested + " mClientHidden=" + mClientHidden
2959 + ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "")
2960 + " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible);
Craig Mautner59431632012-04-04 11:56:44 -07002961 if (paused) {
2962 pw.print(prefix); pw.print("paused="); pw.println(paused);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002963 }
Wale Ogunwale9017ec02016-02-25 08:55:25 -08002964 if (mAppStopped) {
2965 pw.print(prefix); pw.print("mAppStopped="); pw.println(mAppStopped);
2966 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002967 if (mNumInterestingWindows != 0 || mNumDrawnWindows != 0
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002968 || allDrawn || mLastAllDrawn) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002969 pw.print(prefix); pw.print("mNumInterestingWindows=");
2970 pw.print(mNumInterestingWindows);
2971 pw.print(" mNumDrawnWindows="); pw.print(mNumDrawnWindows);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002972 pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
Craig Mautner6fbda632012-07-03 09:26:39 -07002973 pw.print(" allDrawn="); pw.print(allDrawn);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002974 pw.print(" lastAllDrawn="); pw.print(mLastAllDrawn);
Craig Mautner6fbda632012-07-03 09:26:39 -07002975 pw.println(")");
2976 }
2977 if (inPendingTransaction) {
2978 pw.print(prefix); pw.print("inPendingTransaction=");
2979 pw.println(inPendingTransaction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002980 }
Craig Mautner799bc1d2015-01-14 10:33:48 -08002981 if (startingData != null || removed || firstWindowDrawn || mIsExiting) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002982 pw.print(prefix); pw.print("startingData="); pw.print(startingData);
2983 pw.print(" removed="); pw.print(removed);
Craig Mautner3d7ca312015-01-08 10:56:00 -08002984 pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
Craig Mautner799bc1d2015-01-14 10:33:48 -08002985 pw.print(" mIsExiting="); pw.println(mIsExiting);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002986 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08002987 if (startingWindow != null || startingSurface != null
Wale Ogunwale6c459212017-05-17 08:56:03 -07002988 || startingDisplayed || startingMoved || mHiddenSetFromTransferredStartingWindow) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002989 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08002990 pw.print(" startingSurface="); pw.print(startingSurface);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002991 pw.print(" startingDisplayed="); pw.print(startingDisplayed);
Wale Ogunwale6c459212017-05-17 08:56:03 -07002992 pw.print(" startingMoved="); pw.print(startingMoved);
2993 pw.println(" mHiddenSetFromTransferredStartingWindow="
2994 + mHiddenSetFromTransferredStartingWindow);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002995 }
Jorim Jaggi0429f352015-12-22 16:29:16 +01002996 if (!mFrozenBounds.isEmpty()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08002997 pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
Jorim Jaggi26c8c422016-05-09 19:57:25 -07002998 pw.print(prefix); pw.print("mFrozenMergedConfig="); pw.println(mFrozenMergedConfig);
Chong Zhangd78ddb42016-03-02 17:01:14 -08002999 }
3000 if (mPendingRelaunchCount != 0) {
3001 pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount);
Jorim Jaggi0429f352015-12-22 16:29:16 +01003002 }
Riddle Hsub398da32019-01-21 21:48:16 +08003003 if (mSizeCompatScale != 1f || mSizeCompatBounds != null) {
3004 pw.println(prefix + "mSizeCompatScale=" + mSizeCompatScale + " mSizeCompatBounds="
3005 + mSizeCompatBounds);
3006 }
Wale Ogunwalee287e192017-04-21 09:30:12 -07003007 if (mRemovingFromDisplay) {
3008 pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay);
3009 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003010 }
3011
3012 @Override
3013 void setHidden(boolean hidden) {
3014 super.setHidden(hidden);
Winson Chunge55c0192017-08-24 14:50:48 -07003015
3016 if (hidden) {
3017 // Once the app window is hidden, reset the last saved PiP snap fraction
3018 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(this);
3019 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003020 scheduleAnimation();
3021 }
3022
3023 @Override
3024 void prepareSurfaces() {
3025 // isSelfAnimating also returns true when we are about to start a transition, so we need
3026 // to check super here.
3027 final boolean reallyAnimating = super.isSelfAnimating();
3028 final boolean show = !isHidden() || reallyAnimating;
Robert Carrd8e4fb72019-01-31 11:14:30 -08003029
3030 if (mSurfaceControl != null) {
3031 if (show && !mLastSurfaceShowing) {
3032 mPendingTransaction.show(mSurfaceControl);
3033 } else if (!show && mLastSurfaceShowing) {
3034 mPendingTransaction.hide(mSurfaceControl);
3035 }
Jorim Jaggi4d1835d2017-08-31 17:28:27 +02003036 }
Jorim Jaggi988f6682017-11-17 17:46:43 +01003037 if (mThumbnail != null) {
3038 mThumbnail.setShowing(mPendingTransaction, show);
3039 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003040 mLastSurfaceShowing = show;
3041 super.prepareSurfaces();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003042 }
3043
Jorim Jaggi77d0f36c2018-03-16 17:49:49 +01003044 /**
3045 * @return Whether our {@link #getSurfaceControl} is currently showing.
3046 */
3047 boolean isSurfaceShowing() {
3048 return mLastSurfaceShowing;
3049 }
3050
Jorim Jaggib0fc8172017-11-23 17:04:08 +00003051 boolean isFreezingScreen() {
3052 return mFreezingScreen;
3053 }
3054
3055 @Override
3056 boolean needsZBoost() {
3057 return mNeedsZBoost || super.needsZBoost();
3058 }
3059
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07003060 @CallSuper
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003061 @Override
Nataniel Borges023ecb52019-01-16 14:15:43 -08003062 public void writeToProto(ProtoOutputStream proto, long fieldId,
3063 @WindowTraceLogLevel int logLevel) {
3064 // Critical log level logs only visible elements to mitigate performance overheard
3065 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
3066 return;
3067 }
3068
Steven Timotiusaf03df62017-07-18 16:56:43 -07003069 final long token = proto.start(fieldId);
3070 writeNameToProto(proto, NAME);
Nataniel Borges023ecb52019-01-16 14:15:43 -08003071 super.writeToProto(proto, WINDOW_TOKEN, logLevel);
Vishnu Nair04ab4392018-01-10 11:00:06 -08003072 proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing);
3073 proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart());
3074 proto.write(IS_REALLY_ANIMATING, isReallyAnimating());
3075 if (mThumbnail != null){
3076 mThumbnail.writeToProto(proto, THUMBNAIL);
3077 }
3078 proto.write(FILLS_PARENT, mFillsParent);
3079 proto.write(APP_STOPPED, mAppStopped);
3080 proto.write(HIDDEN_REQUESTED, hiddenRequested);
3081 proto.write(CLIENT_HIDDEN, mClientHidden);
3082 proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient);
3083 proto.write(REPORTED_DRAWN, reportedDrawn);
3084 proto.write(REPORTED_VISIBLE, reportedVisible);
3085 proto.write(NUM_INTERESTING_WINDOWS, mNumInterestingWindows);
3086 proto.write(NUM_DRAWN_WINDOWS, mNumDrawnWindows);
3087 proto.write(ALL_DRAWN, allDrawn);
3088 proto.write(LAST_ALL_DRAWN, mLastAllDrawn);
3089 proto.write(REMOVED, removed);
Nataniel Borges023ecb52019-01-16 14:15:43 -08003090 if (startingWindow != null) {
Vishnu Nair04ab4392018-01-10 11:00:06 -08003091 startingWindow.writeIdentifierToProto(proto, STARTING_WINDOW);
3092 }
3093 proto.write(STARTING_DISPLAYED, startingDisplayed);
3094 proto.write(STARTING_MOVED, startingMoved);
3095 proto.write(HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW,
3096 mHiddenSetFromTransferredStartingWindow);
3097 for (Rect bounds : mFrozenBounds) {
3098 bounds.writeToProto(proto, FROZEN_BOUNDS);
3099 }
Steven Timotiusaf03df62017-07-18 16:56:43 -07003100 proto.end(token);
3101 }
3102
3103 void writeNameToProto(ProtoOutputStream proto, long fieldId) {
3104 if (appToken == null) {
3105 return;
3106 }
3107 try {
3108 proto.write(fieldId, appToken.getName());
3109 } catch (RemoteException e) {
3110 // This shouldn't happen, but in this case fall back to outputting nothing
3111 Slog.e(TAG, e.toString());
3112 }
3113 }
3114
3115 @Override
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003116 public String toString() {
3117 if (stringName == null) {
3118 StringBuilder sb = new StringBuilder();
3119 sb.append("AppWindowToken{");
3120 sb.append(Integer.toHexString(System.identityHashCode(this)));
3121 sb.append(" token="); sb.append(token); sb.append('}');
3122 stringName = sb.toString();
3123 }
Wale Ogunwaleba51ca22016-09-23 06:06:54 -07003124 return stringName + ((mIsExiting) ? " mIsExiting=" : "");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003125 }
Adrian Roos20e07892018-02-23 19:12:01 +01003126
3127 Rect getLetterboxInsets() {
3128 if (mLetterbox != null) {
3129 return mLetterbox.getInsets();
3130 } else {
3131 return new Rect();
3132 }
3133 }
Adrian Roos23df3a32018-03-15 15:41:13 +01003134
3135 /**
3136 * @eturn true if there is a letterbox and any part of that letterbox overlaps with
3137 * the given {@code rect}.
3138 */
3139 boolean isLetterboxOverlappingWith(Rect rect) {
3140 return mLetterbox != null && mLetterbox.isOverlappingWith(rect);
3141 }
chaviw4ad54912018-05-30 11:05:44 -07003142
3143 /**
3144 * Sets if this AWT is in the process of closing or entering PIP.
3145 * {@link #mWillCloseOrEnterPip}}
3146 */
3147 void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
3148 mWillCloseOrEnterPip = willCloseOrEnterPip;
3149 }
3150
3151 /**
3152 * Returns whether this AWT is considered closing. Conditions are either
3153 * 1. Is this app animating and was requested to be hidden
3154 * 2. App is delayed closing since it might enter PIP.
3155 */
3156 boolean isClosingOrEnteringPip() {
3157 return (isAnimating() && hiddenRequested) || mWillCloseOrEnterPip;
3158 }
Jorim Jaggiaf0d6d22018-06-08 15:25:35 +02003159
3160 /**
3161 * @return Whether we are allowed to show non-starting windows at the moment. We disallow
3162 * showing windows during transitions in case we have windows that have wide-color-gamut
3163 * color mode set to avoid jank in the middle of the transition.
3164 */
3165 boolean canShowWindows() {
3166 return allDrawn && !(isReallyAnimating() && hasNonDefaultColorWindow());
3167 }
3168
3169 /**
3170 * @return true if we have a window that has a non-default color mode set; false otherwise.
3171 */
3172 private boolean hasNonDefaultColorWindow() {
3173 return forAllWindows(ws -> ws.mAttrs.getColorMode() != COLOR_MODE_DEFAULT,
3174 true /* topToBottom */);
3175 }
lumark588a3e82018-07-20 18:53:54 +08003176
3177 void removeFromPendingTransition() {
3178 if (isWaitingForTransitionStart() && mDisplayContent != null) {
3179 mDisplayContent.mOpeningApps.remove(this);
Evan Rosky25b56192019-02-06 16:10:56 -08003180 if (mDisplayContent.mChangingApps.remove(this)) {
3181 clearChangeLeash(getPendingTransaction(), true /* cancel */);
3182 }
lumark588a3e82018-07-20 18:53:54 +08003183 mDisplayContent.mClosingApps.remove(this);
3184 }
3185 }
chaviwdcf76ec2019-01-11 16:48:46 -08003186
3187 private void updateColorTransform() {
3188 if (mSurfaceControl != null && mLastAppSaturationInfo != null) {
3189 mPendingTransaction.setColorTransform(mSurfaceControl, mLastAppSaturationInfo.mMatrix,
3190 mLastAppSaturationInfo.mTranslation);
3191 mWmService.scheduleAnimationLocked();
3192 }
3193 }
3194
3195 private static class AppSaturationInfo {
3196 float[] mMatrix = new float[9];
3197 float[] mTranslation = new float[3];
3198
3199 void setSaturation(@Size(9) float[] matrix, @Size(3) float[] translation) {
3200 System.arraycopy(matrix, 0, mMatrix, 0, mMatrix.length);
3201 System.arraycopy(translation, 0, mTranslation, 0, mTranslation.length);
3202 }
3203 }
Jeff Browne9bdb312012-04-05 15:30:10 -07003204}