blob: a9903ddb752226c5857c20dbb45d3e0220bceb91 [file] [log] [blame]
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.wm;
18
Evan Rosky2289ba12018-11-19 18:28:18 -080019import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
Winson Chunge55c0192017-08-24 14:50:48 -070020import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
Jorim Jaggic6976f02018-04-18 16:31:07 +020021import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
Winson Chunge55c0192017-08-24 14:50:48 -070022import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
Jorim Jaggiaf0d6d22018-06-08 15:25:35 +020023import static android.content.pm.ActivityInfo.COLOR_MODE_DEFAULT;
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -070024import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
Wale Ogunwale51362492016-09-08 17:49:17 -070025import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
Jorim Jaggif5f9e122017-10-24 18:21:09 +020026import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
Jorim Jaggife762342016-10-13 14:33:27 +020027import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
Jorim Jaggid635a4a2017-05-03 15:21:26 +020028import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080029import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
Jorim Jaggife762342016-10-13 14:33:27 +020030import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
Wale Ogunwaled1c37912016-08-16 03:19:39 -070031import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080032import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -070033import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080034import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
Evan Rosky2289ba12018-11-19 18:28:18 -080035import static android.view.WindowManager.TRANSIT_TASK_CHANGE_WINDOWING_MODE;
chaviw9c81e632018-07-31 11:17:52 -070036import static android.view.WindowManager.TRANSIT_UNSET;
Jorim Jaggic6976f02018-04-18 16:31:07 +020037import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
chaviw9c81e632018-07-31 11:17:52 -070038
Adrian Roose99bc052017-11-20 17:55:31 +010039import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
40import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070041import static com.android.server.wm.AppWindowTokenProto.ALL_DRAWN;
42import static com.android.server.wm.AppWindowTokenProto.APP_STOPPED;
43import static com.android.server.wm.AppWindowTokenProto.CLIENT_HIDDEN;
44import static com.android.server.wm.AppWindowTokenProto.DEFER_HIDING_CLIENT;
45import static com.android.server.wm.AppWindowTokenProto.FILLS_PARENT;
46import static com.android.server.wm.AppWindowTokenProto.FROZEN_BOUNDS;
47import static com.android.server.wm.AppWindowTokenProto.HIDDEN_REQUESTED;
48import static com.android.server.wm.AppWindowTokenProto.HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW;
49import static com.android.server.wm.AppWindowTokenProto.IS_REALLY_ANIMATING;
50import static com.android.server.wm.AppWindowTokenProto.IS_WAITING_FOR_TRANSITION_START;
51import static com.android.server.wm.AppWindowTokenProto.LAST_ALL_DRAWN;
52import static com.android.server.wm.AppWindowTokenProto.LAST_SURFACE_SHOWING;
53import static com.android.server.wm.AppWindowTokenProto.NAME;
54import static com.android.server.wm.AppWindowTokenProto.NUM_DRAWN_WINDOWS;
55import static com.android.server.wm.AppWindowTokenProto.NUM_INTERESTING_WINDOWS;
56import static com.android.server.wm.AppWindowTokenProto.REMOVED;
57import static com.android.server.wm.AppWindowTokenProto.REPORTED_DRAWN;
58import static com.android.server.wm.AppWindowTokenProto.REPORTED_VISIBLE;
59import static com.android.server.wm.AppWindowTokenProto.STARTING_DISPLAYED;
60import static com.android.server.wm.AppWindowTokenProto.STARTING_MOVED;
61import static com.android.server.wm.AppWindowTokenProto.STARTING_WINDOW;
62import static com.android.server.wm.AppWindowTokenProto.THUMBNAIL;
63import static com.android.server.wm.AppWindowTokenProto.WINDOW_TOKEN;
chaviw9c81e632018-07-31 11:17:52 -070064import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
65import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
66import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
67import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
68import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
69import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
70import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
71import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
72import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
73import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
74import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
75import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
76import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
77import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN;
78import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
79import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
80import static com.android.server.wm.WindowManagerService.logWithStack;
Vishnu Naira2977262018-07-26 13:31:26 -070081import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
Evan Rosky641daea2019-04-24 14:45:24 -070082import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080083
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070084import android.annotation.CallSuper;
chaviwdcf76ec2019-01-11 16:48:46 -080085import android.annotation.Size;
Jorim Jaggid635a4a2017-05-03 15:21:26 +020086import android.app.Activity;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080087import android.app.ActivityManager;
Winson Chung48b25652018-10-22 14:04:30 -070088import android.content.ComponentName;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080089import android.content.res.CompatibilityInfo;
Jorim Jaggi26c8c422016-05-09 19:57:25 -070090import android.content.res.Configuration;
Jorim Jaggi988f6682017-11-17 17:46:43 +010091import android.graphics.GraphicBuffer;
Jorim Jaggif5f9e122017-10-24 18:21:09 +020092import android.graphics.Point;
Jorim Jaggi0429f352015-12-22 16:29:16 +010093import android.graphics.Rect;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -070094import android.os.Binder;
Tiger Huang51c5a1d2018-12-11 20:24:51 +080095import android.os.Build;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -080096import android.os.Debug;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -070097import android.os.IBinder;
Steven Timotiusaf03df62017-07-18 16:56:43 -070098import android.os.RemoteException;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080099import android.os.SystemClock;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200100import android.os.Trace;
Evan Rosky2289ba12018-11-19 18:28:18 -0800101import android.util.ArraySet;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800102import android.util.Slog;
Steven Timotiusaf03df62017-07-18 16:56:43 -0700103import android.util.proto.ProtoOutputStream;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200104import android.view.DisplayInfo;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800105import android.view.IApplicationToken;
Robert Carr788f5742018-07-30 17:46:45 -0700106import android.view.InputApplicationHandle;
Evan Rosky966759f2019-01-15 10:33:58 -0800107import android.view.RemoteAnimationAdapter;
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100108import android.view.RemoteAnimationDefinition;
Robert Carr6914f082017-03-20 19:04:30 -0700109import android.view.SurfaceControl;
Tony Mak64b8d562017-12-28 17:44:02 +0000110import android.view.SurfaceControl.Transaction;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800111import android.view.WindowManager;
Jorim Jaggi87fdbcb2017-08-17 13:41:11 +0200112import android.view.WindowManager.LayoutParams;
Tony Mak64b8d562017-12-28 17:44:02 +0000113import android.view.animation.Animation;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800114
Tony Mak64b8d562017-12-28 17:44:02 +0000115import com.android.internal.R;
Riddle Hsua118b3a2018-10-11 22:05:06 +0800116import com.android.internal.annotations.VisibleForTesting;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800117import com.android.internal.util.ToBooleanFunction;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800118import com.android.server.AttributeCache;
chaviwdcf76ec2019-01-11 16:48:46 -0800119import com.android.server.LocalServices;
Christine Franks0ada2772019-02-25 13:54:57 -0800120import com.android.server.display.color.ColorDisplayService;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800121import com.android.server.policy.WindowManagerPolicy;
Adrian Roose99bc052017-11-20 17:55:31 +0100122import com.android.server.policy.WindowManagerPolicy.StartingSurface;
Evan Rosky2289ba12018-11-19 18:28:18 -0800123import com.android.server.wm.RemoteAnimationController.RemoteAnimationRecord;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800124import com.android.server.wm.WindowManagerService.H;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800125
126import java.io.PrintWriter;
chaviwdcf76ec2019-01-11 16:48:46 -0800127import java.lang.ref.WeakReference;
Jorim Jaggi0429f352015-12-22 16:29:16 +0100128import java.util.ArrayDeque;
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800129import java.util.ArrayList;
lumark588a3e82018-07-20 18:53:54 +0800130import java.util.function.Consumer;
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800131
132class AppTokenList extends ArrayList<AppWindowToken> {
133}
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800134
135/**
136 * Version of WindowToken that is specifically for a particular application (or
137 * really activity) that is displaying windows.
138 */
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800139class AppWindowToken extends WindowToken implements WindowManagerService.AppFreezeListener,
140 ConfigurationContainerListener {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800141 private static final String TAG = TAG_WITH_CLASS_NAME ? "AppWindowToken" : TAG_WM;
142
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100143 /**
144 * Value to increment the z-layer when boosting a layer during animations. BOOST in l33tsp34k.
145 */
Jorim Jaggi9cd99132019-04-24 17:41:35 +0200146 @VisibleForTesting static final int Z_BOOST_BASE = 800570000;
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100147
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800148 // Non-null only for application tokens.
149 final IApplicationToken appToken;
Winson Chung48b25652018-10-22 14:04:30 -0700150 final ComponentName mActivityComponent;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800151 final boolean mVoiceInteraction;
Dianne Hackborne30e02f2014-05-27 18:24:45 -0700152
Wale Ogunwale51362492016-09-08 17:49:17 -0700153 /** @see WindowContainer#fillsParent() */
154 private boolean mFillsParent;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800155 boolean mShowForAllUsers;
156 int mTargetSdk;
Craig Mautnera2c77052012-03-26 12:14:43 -0700157
Bryce Lee6d410262017-02-28 15:30:17 -0800158 // Flag set while reparenting to prevent actions normally triggered by an individual parent
159 // change.
160 private boolean mReparenting;
161
Wale Ogunwalee287e192017-04-21 09:30:12 -0700162 // True if we are current in the process of removing this app token from the display
163 private boolean mRemovingFromDisplay = false;
164
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800165 // The input dispatching timeout for this application token in nanoseconds.
Wale Ogunwale72919d22016-12-08 18:58:50 -0800166 long mInputDispatchingTimeoutNanos;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800167
168 // These are used for determining when all windows associated with
169 // an activity have been drawn, so they can be made visible together
170 // at the same time.
Craig Mautner764983d2012-03-22 11:37:36 -0700171 // initialize so that it doesn't match mTransactionSequence which is an int.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700172 private long mLastTransactionSequence = Long.MIN_VALUE;
173 private int mNumInterestingWindows;
174 private int mNumDrawnWindows;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800175 boolean inPendingTransaction;
176 boolean allDrawn;
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000177 private boolean mLastAllDrawn;
178
Craig Mautner7636dfb2012-11-16 15:24:11 -0800179 // Set to true when this app creates a surface while in the middle of an animation. In that
180 // case do not clear allDrawn until the animation completes.
181 boolean deferClearAllDrawn;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800182
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800183 // Is this window's surface needed? This is almost like hidden, except
184 // it will sometimes be true a little earlier: when the token has
185 // been shown, but is still waiting for its app transition to execute
186 // before making its windows shown.
187 boolean hiddenRequested;
188
189 // Have we told the window clients to hide themselves?
Wale Ogunwale89973222017-04-23 18:39:45 -0700190 private boolean mClientHidden;
191
192 // If true we will defer setting mClientHidden to true and reporting to the client that it is
193 // hidden.
194 boolean mDeferHidingClient;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800195
196 // Last visibility state we reported to the app token.
197 boolean reportedVisible;
198
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700199 // Last drawn state we reported to the app token.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700200 private boolean reportedDrawn;
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700201
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800202 // Set to true when the token has been removed from the window mgr.
203 boolean removed;
204
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800205 // Information about an application starting window if displayed.
206 StartingData startingData;
207 WindowState startingWindow;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800208 StartingSurface startingSurface;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800209 boolean startingDisplayed;
210 boolean startingMoved;
Jorim Jaggi60f9c972018-02-01 19:21:07 +0100211
Wale Ogunwale6c459212017-05-17 08:56:03 -0700212 // True if the hidden state of this token was forced to false due to a transferred starting
213 // window.
214 private boolean mHiddenSetFromTransferredStartingWindow;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800215 boolean firstWindowDrawn;
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700216 private final WindowState.UpdateReportedVisibilityResults mReportedVisibilityResults =
217 new WindowState.UpdateReportedVisibilityResults();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800218
219 // Input application handle used by the input dispatcher.
Jeff Brown9302c872011-07-13 22:51:29 -0700220 final InputApplicationHandle mInputApplicationHandle;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800221
Wale Ogunwale571771c2016-08-26 13:18:50 -0700222 // TODO: Have a WindowContainer state for tracking exiting/deferred removal.
Craig Mautner799bc1d2015-01-14 10:33:48 -0800223 boolean mIsExiting;
Craig Mautner9ef471f2014-02-07 13:11:47 -0800224
Craig Mautnerbb742462014-07-07 15:28:55 -0700225 boolean mLaunchTaskBehind;
Craig Mautner8746a472014-07-24 15:12:54 -0700226 boolean mEnteringAnimation;
Craig Mautnerbb742462014-07-07 15:28:55 -0700227
Wale Ogunwale72919d22016-12-08 18:58:50 -0800228 private boolean mAlwaysFocusable;
Wale Ogunwale6cae7652015-12-26 07:36:26 -0800229
Robert Carre12aece2016-02-02 22:43:27 -0800230 boolean mAppStopped;
Robert Carrfd10cd12016-06-29 16:41:50 -0700231 int mRotationAnimationHint;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700232 private int mPendingRelaunchCount;
Robert Carre12aece2016-02-02 22:43:27 -0800233
Jorim Jaggife762342016-10-13 14:33:27 +0200234 private boolean mLastContainsShowWhenLockedWindow;
235 private boolean mLastContainsDismissKeyguardWindow;
236
Jorim Jaggi0429f352015-12-22 16:29:16 +0100237 ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
Jorim Jaggi26c8c422016-05-09 19:57:25 -0700238 ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
Jorim Jaggi0429f352015-12-22 16:29:16 +0100239
Riddle Hsub398da32019-01-21 21:48:16 +0800240 /**
241 * The scale to fit at least one side of the activity to its parent. If the activity uses
242 * 1920x1080, and the actually size on the screen is 960x540, then the scale is 0.5.
243 */
244 private float mSizeCompatScale = 1f;
245 /**
246 * The bounds in global coordinates for activity in size compatibility mode.
247 * @see ActivityRecord#inSizeCompatMode
248 */
249 private Rect mSizeCompatBounds;
250
Wale Ogunwale6c459212017-05-17 08:56:03 -0700251 private boolean mDisablePreviewScreenshots;
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +0100252
Wale Ogunwale034a8ec2017-09-02 17:14:40 -0700253 private Task mLastParent;
Robert Carred3e83b2017-04-21 13:26:55 -0700254
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800255 // TODO: Remove after unification
256 ActivityRecord mActivityRecord;
257
chaviwd3bf08d2017-08-01 17:24:59 -0700258 /**
259 * See {@link #canTurnScreenOn()}
260 */
261 private boolean mCanTurnScreenOn = true;
262
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200263 /**
264 * If we are running an animation, this determines the transition type. Must be one of
265 * AppTransition.TRANSIT_* constants.
266 */
267 private int mTransit;
268
269 /**
270 * If we are running an animation, this determines the flags during this animation. Must be a
271 * bitwise combination of AppTransition.TRANSIT_FLAG_* constants.
272 */
273 private int mTransitFlags;
274
275 /** Whether our surface was set to be showing in the last call to {@link #prepareSurfaces} */
Jorim Jaggifd1891462017-12-29 15:41:36 +0100276 private boolean mLastSurfaceShowing = true;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200277
Evan Rosky2289ba12018-11-19 18:28:18 -0800278 /**
279 * This gets used during some open/close transitions as well as during a change transition
280 * where it represents the starting-state snapshot.
281 */
Jorim Jaggi988f6682017-11-17 17:46:43 +0100282 private AppWindowThumbnail mThumbnail;
Evan Rosky2289ba12018-11-19 18:28:18 -0800283 private final Rect mTransitStartRect = new Rect();
284
285 /**
286 * This leash is used to "freeze" the app surface in place after the state change, but before
287 * the animation is ready to start.
288 */
289 private SurfaceControl mTransitChangeLeash = null;
Jorim Jaggi988f6682017-11-17 17:46:43 +0100290
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000291 /** Have we been asked to have this token keep the screen frozen? */
292 private boolean mFreezingScreen;
293
294 /** Whether this token should be boosted at the top of all app window tokens. */
Jorim Jaggi9cd99132019-04-24 17:41:35 +0200295 @VisibleForTesting boolean mNeedsZBoost;
Adrian Roos4d18a2e2017-12-19 19:08:05 +0100296 private Letterbox mLetterbox;
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000297
chaviw23ee71c2017-12-18 11:29:41 -0800298 private final Point mTmpPoint = new Point();
chaviw23012112017-12-20 15:29:04 -0800299 private final Rect mTmpRect = new Rect();
Evan Rosky2289ba12018-11-19 18:28:18 -0800300 private final Rect mTmpPrevBounds = new Rect();
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100301 private RemoteAnimationDefinition mRemoteAnimationDefinition;
Jorim Jaggi6de61012018-03-19 14:53:23 +0100302 private AnimatingAppWindowTokenRegistry mAnimatingAppWindowTokenRegistry;
chaviw23ee71c2017-12-18 11:29:41 -0800303
chaviw4ad54912018-05-30 11:05:44 -0700304 /**
305 * A flag to determine if this AWT is in the process of closing or entering PIP. This is needed
306 * to help AWT know that the app is in the process of closing but hasn't yet started closing on
307 * the WM side.
308 */
309 private boolean mWillCloseOrEnterPip;
310
Vishnu Naira2977262018-07-26 13:31:26 -0700311 /** Layer used to constrain the animation to a token's stack bounds. */
312 SurfaceControl mAnimationBoundsLayer;
313
314 /** Whether this token needs to create mAnimationBoundsLayer for cropping animations. */
315 boolean mNeedsAnimationBoundsLayer;
316
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800317 private static final int STARTING_WINDOW_TYPE_NONE = 0;
318 private static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
319 private static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
320
chaviwdcf76ec2019-01-11 16:48:46 -0800321 private AppSaturationInfo mLastAppSaturationInfo;
322
323 private final ColorDisplayService.ColorTransformController mColorTransformController =
324 (matrix, translation) -> mWmService.mH.post(() -> {
325 synchronized (mWmService.mGlobalLock) {
326 if (mLastAppSaturationInfo == null) {
327 mLastAppSaturationInfo = new AppSaturationInfo();
328 }
329
330 mLastAppSaturationInfo.setSaturation(matrix, translation);
331 updateColorTransform();
332 }
333 });
334
Winson Chung48b25652018-10-22 14:04:30 -0700335 AppWindowToken(WindowManagerService service, IApplicationToken token,
336 ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
337 long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers,
Jorim Jaggi91d382a2019-03-27 17:00:48 +0100338 int targetSdk, int orientation, int rotationAnimationHint,
Winson Chung48b25652018-10-22 14:04:30 -0700339 boolean launchTaskBehind, boolean alwaysFocusable,
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800340 ActivityRecord activityRecord) {
Winson Chung48b25652018-10-22 14:04:30 -0700341 this(service, token, activityComponent, voiceInteraction, dc, fullscreen);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800342 // TODO: remove after unification
343 mActivityRecord = activityRecord;
344 mActivityRecord.registerConfigurationChangeListener(this);
Wale Ogunwale72919d22016-12-08 18:58:50 -0800345 mInputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800346 mShowForAllUsers = showForAllUsers;
347 mTargetSdk = targetSdk;
348 mOrientation = orientation;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800349 mLaunchTaskBehind = launchTaskBehind;
350 mAlwaysFocusable = alwaysFocusable;
351 mRotationAnimationHint = rotationAnimationHint;
352
353 // Application tokens start out hidden.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200354 setHidden(true);
Wale Ogunwale72919d22016-12-08 18:58:50 -0800355 hiddenRequested = true;
chaviwdcf76ec2019-01-11 16:48:46 -0800356
357 ColorDisplayService.ColorDisplayServiceInternal cds = LocalServices.getService(
358 ColorDisplayService.ColorDisplayServiceInternal.class);
359 cds.attachColorTransformController(activityRecord.packageName, activityRecord.mUserId,
360 new WeakReference<>(mColorTransformController));
Wale Ogunwale72919d22016-12-08 18:58:50 -0800361 }
362
Winson Chung48b25652018-10-22 14:04:30 -0700363 AppWindowToken(WindowManagerService service, IApplicationToken token,
364 ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
365 boolean fillsParent) {
Wale Ogunwale5cd907d2017-01-26 14:14:08 -0800366 super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true, dc,
367 false /* ownerCanManageAppTokens */);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700368 appToken = token;
Winson Chung48b25652018-10-22 14:04:30 -0700369 mActivityComponent = activityComponent;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800370 mVoiceInteraction = voiceInteraction;
Wale Ogunwale17f175c2017-02-07 16:54:10 -0800371 mFillsParent = fillsParent;
Robert Carr0bcbe642018-10-11 19:07:43 -0700372 mInputApplicationHandle = new InputApplicationHandle(appToken.asBinder());
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800373 }
374
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800375 void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
376 firstWindowDrawn = true;
377
378 // We now have a good window to show, remove dead placeholders
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700379 removeDeadWindows();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800380
Jorim Jaggi02886a82016-12-06 09:10:06 -0800381 if (startingWindow != null) {
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800382 if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Slog.v(TAG, "Finish starting "
383 + win.mToken + ": first real window is shown, no animation");
384 // If this initial window is animating, stop it -- we will do an animation to reveal
385 // it from behind the starting window, so there is no need for it to also be doing its
386 // own stuff.
Jorim Jaggia5e10572017-11-15 14:36:26 +0100387 win.cancelAnimation();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800388 removeStartingWindow();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800389 }
390 updateReportedVisibilityLocked();
391 }
392
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800393 void updateReportedVisibilityLocked() {
394 if (appToken == null) {
395 return;
396 }
397
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700398 if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700399 final int count = mChildren.size();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800400
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700401 mReportedVisibilityResults.reset();
402
403 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700404 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700405 win.updateReportedVisibility(mReportedVisibilityResults);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800406 }
407
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700408 int numInteresting = mReportedVisibilityResults.numInteresting;
409 int numVisible = mReportedVisibilityResults.numVisible;
410 int numDrawn = mReportedVisibilityResults.numDrawn;
411 boolean nowGone = mReportedVisibilityResults.nowGone;
412
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700413 boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200414 boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting && !isHidden();
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700415 if (!nowGone) {
416 // If the app is not yet gone, then it can only become visible/drawn.
417 if (!nowDrawn) {
418 nowDrawn = reportedDrawn;
419 }
420 if (!nowVisible) {
421 nowVisible = reportedVisible;
422 }
423 }
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800424 if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800425 + numInteresting + " visible=" + numVisible);
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700426 if (nowDrawn != reportedDrawn) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800427 if (mActivityRecord != null) {
428 mActivityRecord.onWindowsDrawn(nowDrawn, SystemClock.uptimeMillis());
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700429 }
430 reportedDrawn = nowDrawn;
431 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800432 if (nowVisible != reportedVisible) {
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700433 if (DEBUG_VISIBILITY) Slog.v(TAG,
434 "Visibility changed in " + this + ": vis=" + nowVisible);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800435 reportedVisible = nowVisible;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800436 if (mActivityRecord != null) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800437 if (nowVisible) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800438 onWindowsVisible();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800439 } else {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800440 onWindowsGone();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800441 }
442 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800443 }
444 }
445
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800446 private void onWindowsGone() {
447 if (mActivityRecord == null) {
448 return;
449 }
450 if (DEBUG_VISIBILITY) {
451 Slog.v(TAG_WM, "Reporting gone in " + mActivityRecord.appToken);
452 }
453 mActivityRecord.onWindowsGone();
454 }
455
456 private void onWindowsVisible() {
457 if (mActivityRecord == null) {
458 return;
459 }
460 if (DEBUG_VISIBILITY) {
461 Slog.v(TAG_WM, "Reporting visible in " + mActivityRecord.appToken);
462 }
463 mActivityRecord.onWindowsVisible();
464 }
465
Wale Ogunwale89973222017-04-23 18:39:45 -0700466 boolean isClientHidden() {
467 return mClientHidden;
468 }
469
470 void setClientHidden(boolean hideClient) {
471 if (mClientHidden == hideClient || (hideClient && mDeferHidingClient)) {
472 return;
473 }
Jorim Jaggi067b5bf2018-02-23 17:42:39 +0100474 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "setClientHidden: " + this
475 + " clientHidden=" + hideClient + " Callers=" + Debug.getCallers(5));
Wale Ogunwale89973222017-04-23 18:39:45 -0700476 mClientHidden = hideClient;
477 sendAppVisibilityToClients();
478 }
479
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800480 void setVisibility(boolean visible, boolean deferHidingClient) {
481 final AppTransition appTransition = getDisplayContent().mAppTransition;
482
483 // Don't set visibility to false if we were already not visible. This prevents WM from
484 // adding the app to the closing app list which doesn't make sense for something that is
485 // already not visible. However, set visibility to true even if we are already visible.
486 // This makes sure the app is added to the opening apps list so that the right
487 // transition can be selected.
488 // TODO: Probably a good idea to separate the concept of opening/closing apps from the
489 // concept of setting visibility...
490 if (!visible && hiddenRequested) {
491
492 if (!deferHidingClient && mDeferHidingClient) {
493 // We previously deferred telling the client to hide itself when visibility was
494 // initially set to false. Now we would like it to hide, so go ahead and set it.
495 mDeferHidingClient = deferHidingClient;
496 setClientHidden(true);
497 }
498 return;
499 }
500
501 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) {
502 Slog.v(TAG_WM, "setAppVisibility("
503 + appToken + ", visible=" + visible + "): " + appTransition
504 + " hidden=" + isHidden() + " hiddenRequested="
505 + hiddenRequested + " Callers=" + Debug.getCallers(6));
506 }
507
508 final DisplayContent displayContent = getDisplayContent();
509 displayContent.mOpeningApps.remove(this);
510 displayContent.mClosingApps.remove(this);
Evan Roskyb1e75f72019-04-26 20:23:26 -0700511 if (isInChangeTransition()) {
512 clearChangeLeash(getPendingTransaction(), true /* cancel */);
513 }
514 displayContent.mChangingApps.remove(this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800515 waitingToShow = false;
516 hiddenRequested = !visible;
517 mDeferHidingClient = deferHidingClient;
518
519 if (!visible) {
520 // If the app is dead while it was visible, we kept its dead window on screen.
521 // Now that the app is going invisible, we can remove it. It will be restarted
522 // if made visible again.
523 removeDeadWindows();
524 } else {
525 if (!appTransition.isTransitionSet()
526 && appTransition.isReady()) {
527 // Add the app mOpeningApps if transition is unset but ready. This means
528 // we're doing a screen freeze, and the unfreeze will wait for all opening
529 // apps to be ready.
530 displayContent.mOpeningApps.add(this);
531 }
532 startingMoved = false;
533 // If the token is currently hidden (should be the common case), or has been
534 // stopped, then we need to set up to wait for its windows to be ready.
535 if (isHidden() || mAppStopped) {
536 clearAllDrawn();
537
538 // If the app was already visible, don't reset the waitingToShow state.
539 if (isHidden()) {
540 waitingToShow = true;
541 }
542 }
543
544 // In the case where we are making an app visible but holding off for a transition,
545 // we still need to tell the client to make its windows visible so they get drawn.
546 // Otherwise, we will wait on performing the transition until all windows have been
547 // drawn, they never will be, and we are sad.
548 setClientHidden(false);
549
550 requestUpdateWallpaperIfNeeded();
551
552 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "No longer Stopped: " + this);
553 mAppStopped = false;
554
555 transferStartingWindowFromHiddenAboveTokenIfNeeded();
556 }
557
558 // If we are preparing an app transition, then delay changing
559 // the visibility of this token until we execute that transition.
560 if (okToAnimate() && appTransition.isTransitionSet()) {
561 inPendingTransaction = true;
562 if (visible) {
563 displayContent.mOpeningApps.add(this);
564 mEnteringAnimation = true;
565 } else {
566 displayContent.mClosingApps.add(this);
567 mEnteringAnimation = false;
568 }
569 if (appTransition.getAppTransition()
570 == WindowManager.TRANSIT_TASK_OPEN_BEHIND) {
571 // We're launchingBehind, add the launching activity to mOpeningApps.
572 final WindowState win = getDisplayContent().findFocusedWindow();
573 if (win != null) {
574 final AppWindowToken focusedToken = win.mAppToken;
575 if (focusedToken != null) {
576 if (DEBUG_APP_TRANSITIONS) {
577 Slog.d(TAG_WM, "TRANSIT_TASK_OPEN_BEHIND, "
578 + " adding " + focusedToken + " to mOpeningApps");
579 }
580 // Force animation to be loaded.
581 focusedToken.setHidden(true);
582 displayContent.mOpeningApps.add(focusedToken);
583 }
584 }
585 }
Garfield Tanb6776602019-02-20 14:44:26 -0800586 // Changes in opening apps and closing apps may cause orientation change.
587 reportDescendantOrientationChangeIfNeeded();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800588 return;
589 }
590
591 commitVisibility(null, visible, TRANSIT_UNSET, true, mVoiceInteraction);
592 updateReportedVisibilityLocked();
593 }
594
595 boolean commitVisibility(WindowManager.LayoutParams lp,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700596 boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
597
598 boolean delayed = false;
599 inPendingTransaction = false;
Wale Ogunwale9e4721f2017-05-23 19:37:30 -0700600 // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually
601 // been set by the app now.
602 mHiddenSetFromTransferredStartingWindow = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700603
604 // Allow for state changes and animation to be applied if:
605 // * token is transitioning visibility state
606 // * or the token was marked as hidden and is exiting before we had a chance to play the
607 // transition animation
608 // * or this is an opening app and windows are being replaced.
609 boolean visibilityChanged = false;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200610 if (isHidden() == visible || (isHidden() && mIsExiting) || (visible && waitingForReplacement())) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800611 final AccessibilityController accessibilityController =
612 mWmService.mAccessibilityController;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700613 boolean changed = false;
614 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM,
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200615 "Changing app " + this + " hidden=" + isHidden() + " performLayout=" + performLayout);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700616
617 boolean runningAppAnimation = false;
618
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100619 if (transit != WindowManager.TRANSIT_UNSET) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200620 if (applyAnimationLocked(lp, transit, visible, isVoiceInteraction)) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700621 delayed = runningAppAnimation = true;
622 }
623 final WindowState window = findMainWindow();
Rhed Jao02655dc2018-10-30 20:44:52 +0800624 if (window != null && accessibilityController != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700625 accessibilityController.onAppWindowTransitionLocked(window, transit);
626 }
627 changed = true;
628 }
629
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700630 final int windowsCount = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700631 for (int i = 0; i < windowsCount; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700632 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700633 changed |= win.onAppVisibilityChanged(visible, runningAppAnimation);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700634 }
635
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200636 setHidden(!visible);
637 hiddenRequested = !visible;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700638 visibilityChanged = true;
639 if (!visible) {
640 stopFreezingScreen(true, true);
641 } else {
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700642 // If we are being set visible, and the starting window is not yet displayed,
643 // then make sure it doesn't get displayed.
644 if (startingWindow != null && !startingWindow.isDrawnLw()) {
645 startingWindow.mPolicyVisibility = false;
646 startingWindow.mPolicyVisibilityAfterAnim = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700647 }
Jorim Jaggi38d44ec2017-06-14 16:04:59 -0700648
649 // We are becoming visible, so better freeze the screen with the windows that are
650 // getting visible so we also wait for them.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800651 forAllWindows(mWmService::makeWindowFreezingScreenIfNeededLocked, true);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700652 }
653
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800654 if (DEBUG_APP_TRANSITIONS) {
655 Slog.v(TAG_WM, "commitVisibility: " + this
656 + ": hidden=" + isHidden() + " hiddenRequested=" + hiddenRequested);
657 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700658
659 if (changed) {
Arthur Hung95b38a92018-07-20 18:56:12 +0800660 getDisplayContent().getInputMonitor().setUpdateInputWindowsNeededLw();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700661 if (performLayout) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800662 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700663 false /*updateInputWindows*/);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800664 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700665 }
Arthur Hung95b38a92018-07-20 18:56:12 +0800666 getDisplayContent().getInputMonitor().updateInputWindowsLw(false /*force*/);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700667 }
668 }
669
lumarkd14173e2019-03-27 19:14:33 +0800670 if (isReallyAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700671 delayed = true;
Jorim Jaggiab9fcb22018-03-15 23:46:12 +0100672 } else {
673
674 // We aren't animating anything, but exiting windows rely on the animation finished
675 // callback being called in case the AppWindowToken was pretending to be animating,
676 // which we might have done because we were in closing/opening apps list.
677 onAnimationFinished();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700678 }
679
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700680 for (int i = mChildren.size() - 1; i >= 0 && !delayed; i--) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100681 if ((mChildren.get(i)).isSelfOrChildAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700682 delayed = true;
683 }
684 }
685
686 if (visibilityChanged) {
687 if (visible && !delayed) {
688 // The token was made immediately visible, there will be no entrance animation.
689 // We need to inform the client the enter animation was finished.
690 mEnteringAnimation = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800691 mWmService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(
692 token);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700693 }
Robert Carr61b81112017-07-17 18:08:15 -0700694
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800695 // If we're becoming visible, immediately change client visibility as well. there seem
696 // to be some edge cases where we change our visibility but client visibility never gets
697 // updated.
Jorim Jaggi110839b2018-01-22 12:49:04 +0100698 // If we're becoming invisible, update the client visibility if we are not running an
699 // animation. Otherwise, we'll update client visibility in onAnimationFinished.
Jorim Jaggi3cad57f2018-02-20 18:32:01 +0100700 if (visible || !isReallyAnimating()) {
Jorim Jaggi110839b2018-01-22 12:49:04 +0100701 setClientHidden(!visible);
Jorim Jaggi4876b4a2018-01-11 15:43:49 +0100702 }
703
lumark588a3e82018-07-20 18:53:54 +0800704 if (!getDisplayContent().mClosingApps.contains(this)
705 && !getDisplayContent().mOpeningApps.contains(this)) {
chaviwa953fcf2018-03-01 12:00:39 -0800706 // The token is not closing nor opening, so even if there is an animation set, that
707 // doesn't mean that it goes through the normal app transition cycle so we have
708 // to inform the docked controller about visibility change.
709 // TODO(multi-display): notify docked divider on all displays where visibility was
710 // affected.
lumark588a3e82018-07-20 18:53:54 +0800711 getDisplayContent().getDockedDividerController().notifyAppVisibilityChanged();
chaviwa953fcf2018-03-01 12:00:39 -0800712
713 // Take the screenshot before possibly hiding the WSA, otherwise the screenshot
714 // will not be taken.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800715 mWmService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible);
chaviwa953fcf2018-03-01 12:00:39 -0800716 }
717
Robert Carre7cc44d2017-03-20 19:04:30 -0700718 // If we are hidden but there is no delay needed we immediately
719 // apply the Surface transaction so that the ActivityManager
Robert Carr61b81112017-07-17 18:08:15 -0700720 // can have some guarantee on the Surface state following
721 // setting the visibility. This captures cases like dismissing
722 // the docked or pinned stack where there is no app transition.
723 //
724 // In the case of a "Null" animation, there will be
725 // no animation but there will still be a transition set.
726 // We still need to delay hiding the surface such that it
727 // can be synchronized with showing the next surface in the transition.
lumark588a3e82018-07-20 18:53:54 +0800728 if (isHidden() && !delayed && !getDisplayContent().mAppTransition.isTransitionSet()) {
Robert Carr6914f082017-03-20 19:04:30 -0700729 SurfaceControl.openTransaction();
730 for (int i = mChildren.size() - 1; i >= 0; i--) {
731 mChildren.get(i).mWinAnimator.hide("immediately hidden");
732 }
733 SurfaceControl.closeTransaction();
734 }
Garfield Tanb6776602019-02-20 14:44:26 -0800735
736 // Visibility changes may cause orientation request change.
737 reportDescendantOrientationChangeIfNeeded();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700738 }
739
740 return delayed;
741 }
742
Garfield Tanb6776602019-02-20 14:44:26 -0800743 private void reportDescendantOrientationChangeIfNeeded() {
744 // Orientation request is exposed only when we're visible. Therefore visibility change
745 // will change requested orientation. Notify upward the hierarchy ladder to adjust
746 // configuration. This is important to cases where activities with incompatible
747 // orientations launch, or user goes back from an activity of bi-orientation to an
748 // activity with specified orientation.
749 if (mActivityRecord.getRequestedConfigurationOrientation() == getConfiguration().orientation
750 || getOrientationIgnoreVisibility() == SCREEN_ORIENTATION_UNSET) {
751 return;
752 }
753
754 final IBinder freezeToken =
755 mActivityRecord.mayFreezeScreenLocked(mActivityRecord.app)
756 ? mActivityRecord.appToken : null;
757 onDescendantOrientationChanged(freezeToken, mActivityRecord);
758 }
759
Jorim Jaggi87fdbcb2017-08-17 13:41:11 +0200760 /**
761 * @return The to top most child window for which {@link LayoutParams#isFullscreen()} returns
762 * true.
763 */
764 WindowState getTopFullscreenWindow() {
765 for (int i = mChildren.size() - 1; i >= 0; i--) {
766 final WindowState win = mChildren.get(i);
767 if (win != null && win.mAttrs.isFullscreen()) {
768 return win;
769 }
770 }
771 return null;
772 }
773
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800774 WindowState findMainWindow() {
Matthew Ng53e66b22018-01-12 17:13:13 -0800775 return findMainWindow(true);
776 }
777
778 /**
779 * Finds the main window that either has type base application or application starting if
780 * requested.
781 *
782 * @param includeStartingApp Allow to search application-starting windows to also be returned.
783 * @return The main window of type base application or application starting if requested.
784 */
785 WindowState findMainWindow(boolean includeStartingApp) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700786 WindowState candidate = null;
Matthew Ng53e66b22018-01-12 17:13:13 -0800787 for (int j = mChildren.size() - 1; j >= 0; --j) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700788 final WindowState win = mChildren.get(j);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700789 final int type = win.mAttrs.type;
790 // No need to loop through child window as base application and starting types can't be
791 // child windows.
Matthew Ng53e66b22018-01-12 17:13:13 -0800792 if (type == TYPE_BASE_APPLICATION
793 || (includeStartingApp && type == TYPE_APPLICATION_STARTING)) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700794 // In cases where there are multiple windows, we prefer the non-exiting window. This
Sungsoo Lim0d3d1f82015-12-02 14:47:59 +0900795 // happens for example when replacing windows during an activity relaunch. When
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700796 // constructing the animation, we want the new window, not the exiting one.
Wale Ogunwalec48a3542016-02-19 15:18:45 -0800797 if (win.mAnimatingExit) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700798 candidate = win;
799 } else {
800 return win;
801 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800802 }
803 }
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700804 return candidate;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800805 }
806
Wale Ogunwale6cae7652015-12-26 07:36:26 -0800807 boolean windowsAreFocusable() {
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800808 if (mTargetSdk < Build.VERSION_CODES.Q) {
809 final int pid = mActivityRecord != null
810 ? (mActivityRecord.app != null ? mActivityRecord.app.getPid() : 0) : 0;
811 final AppWindowToken topFocusedAppOfMyProcess =
812 mWmService.mRoot.mTopFocusedAppByProcess.get(pid);
813 if (topFocusedAppOfMyProcess != null && topFocusedAppOfMyProcess != this) {
814 // For the apps below Q, there can be only one app which has the focused window per
815 // process, because legacy apps may not be ready for a multi-focus system.
816 return false;
817 }
818 }
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700819 return getWindowConfiguration().canReceiveKeys() || mAlwaysFocusable;
Wale Ogunwaled045c822015-12-02 09:14:28 -0800820 }
821
Wale Ogunwale571771c2016-08-26 13:18:50 -0700822 @Override
Wale Ogunwale44f21802016-09-02 12:49:48 -0700823 boolean isVisible() {
Wale Ogunwalee471be62016-10-03 07:53:55 -0700824 // If the app token isn't hidden then it is considered visible and there is no need to check
825 // its children windows to see if they are visible.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200826 return !isHidden();
Wale Ogunwale44f21802016-09-02 12:49:48 -0700827 }
828
829 @Override
Wale Ogunwalee287e192017-04-21 09:30:12 -0700830 void removeImmediately() {
831 onRemovedFromDisplay();
Yunfan Chen3a77f282018-12-12 15:47:52 -0800832 if (mActivityRecord != null) {
833 mActivityRecord.unregisterConfigurationChangeListener(this);
834 }
Wale Ogunwalee287e192017-04-21 09:30:12 -0700835 super.removeImmediately();
836 }
837
838 @Override
Wale Ogunwale571771c2016-08-26 13:18:50 -0700839 void removeIfPossible() {
Craig Mautnere3119b72015-01-20 15:02:36 -0800840 mIsExiting = false;
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800841 removeAllWindowsIfPossible();
Bryce Lee6d410262017-02-28 15:30:17 -0800842 removeImmediately();
Craig Mautnere3119b72015-01-20 15:02:36 -0800843 }
844
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700845 @Override
846 boolean checkCompleteDeferredRemoval() {
847 if (mIsExiting) {
848 removeIfPossible();
849 }
850 return super.checkCompleteDeferredRemoval();
851 }
852
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700853 void onRemovedFromDisplay() {
Wale Ogunwalee287e192017-04-21 09:30:12 -0700854 if (mRemovingFromDisplay) {
855 return;
856 }
857 mRemovingFromDisplay = true;
858
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700859 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app token: " + this);
860
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800861 boolean delayed = commitVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700862
lumark588a3e82018-07-20 18:53:54 +0800863 getDisplayContent().mOpeningApps.remove(this);
Evan Rosky2289ba12018-11-19 18:28:18 -0800864 getDisplayContent().mChangingApps.remove(this);
lumark588a3e82018-07-20 18:53:54 +0800865 getDisplayContent().mUnknownAppVisibilityController.appRemovedOrHidden(this);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800866 mWmService.mTaskSnapshotController.onAppRemoved(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700867 waitingToShow = false;
lumark588a3e82018-07-20 18:53:54 +0800868 if (getDisplayContent().mClosingApps.contains(this)) {
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700869 delayed = true;
lumark588a3e82018-07-20 18:53:54 +0800870 } else if (getDisplayContent().mAppTransition.isTransitionSet()) {
871 getDisplayContent().mClosingApps.add(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700872 delayed = true;
873 }
874
875 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app " + this + " delayed=" + delayed
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200876 + " animation=" + getAnimation() + " animating=" + isSelfAnimating());
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700877
878 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: "
879 + this + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
880
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800881 if (startingData != null) {
882 removeStartingWindow();
Jorim Jaggi19be6052017-08-03 18:33:43 +0200883 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800884
Winson Chung87e5d552017-04-05 11:49:38 -0700885 // If this window was animating, then we need to ensure that the app transition notifies
lumark588a3e82018-07-20 18:53:54 +0800886 // that animations have completed in DisplayContent.handleAnimatingStoppedAndTransition(),
887 // so add to that list now
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200888 if (isSelfAnimating()) {
lumark588a3e82018-07-20 18:53:54 +0800889 getDisplayContent().mNoAnimationNotifyOnTransitionFinished.add(token);
Winson Chung87e5d552017-04-05 11:49:38 -0700890 }
891
Wale Ogunwalee287e192017-04-21 09:30:12 -0700892 final TaskStack stack = getStack();
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700893 if (delayed && !isEmpty()) {
894 // set the token aside because it has an active animation to be finished
895 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM,
896 "removeAppToken make exiting: " + this);
Wale Ogunwalee287e192017-04-21 09:30:12 -0700897 if (stack != null) {
898 stack.mExitingAppTokens.add(this);
899 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700900 mIsExiting = true;
901 } else {
902 // Make sure there is no animation running on this token, so any windows associated
903 // with it will be removed as soon as their animations are complete
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200904 cancelAnimation();
Wale Ogunwale3106ae012017-05-16 08:56:37 -0700905 if (stack != null) {
906 stack.mExitingAppTokens.remove(this);
907 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700908 removeIfPossible();
909 }
910
911 removed = true;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700912 stopFreezingScreen(true, true);
Bryce Lee6d410262017-02-28 15:30:17 -0800913
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800914 final DisplayContent dc = getDisplayContent();
915 if (dc.mFocusedApp == this) {
916 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + this
917 + " displayId=" + dc.getDisplayId());
918 dc.setFocusedApp(null);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800919 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700920 }
Riddle Hsu192fe762019-01-15 23:41:57 +0800921 if (mLetterbox != null) {
922 mLetterbox.destroy();
923 mLetterbox = null;
924 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700925
926 if (!delayed) {
927 updateReportedVisibilityLocked();
928 }
Wale Ogunwalee287e192017-04-21 09:30:12 -0700929
930 mRemovingFromDisplay = false;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700931 }
932
Chong Zhange05bcb12016-07-26 17:47:29 -0700933 void clearAnimatingFlags() {
Chong Zhangb0d26702016-08-12 16:03:29 -0700934 boolean wallpaperMightChange = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700935 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700936 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700937 wallpaperMightChange |= win.clearAnimatingFlags();
Chong Zhange05bcb12016-07-26 17:47:29 -0700938 }
Chong Zhangb0d26702016-08-12 16:03:29 -0700939 if (wallpaperMightChange) {
940 requestUpdateWallpaperIfNeeded();
941 }
Chong Zhange05bcb12016-07-26 17:47:29 -0700942 }
943
Robert Carre12aece2016-02-02 22:43:27 -0800944 void destroySurfaces() {
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700945 destroySurfaces(false /*cleanupOnResume*/);
946 }
947
948 /**
949 * Destroy surfaces which have been marked as eligible by the animator, taking care to ensure
950 * the client has finished with them.
951 *
952 * @param cleanupOnResume whether this is done when app is resumed without fully stopped. If
953 * set to true, destroy only surfaces of removed windows, and clear relevant flags of the
954 * others so that they are ready to be reused. If set to false (common case), destroy all
955 * surfaces that's eligible, if the app is already stopped.
956 */
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700957 private void destroySurfaces(boolean cleanupOnResume) {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700958 boolean destroyedSomething = false;
Jorim Jaggia5e10572017-11-15 14:36:26 +0100959
960 // Copying to a different list as multiple children can be removed.
Jorim Jaggi59f3e922018-01-05 15:40:32 +0100961 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
Jorim Jaggia5e10572017-11-15 14:36:26 +0100962 for (int i = children.size() - 1; i >= 0; i--) {
963 final WindowState win = children.get(i);
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700964 destroyedSomething |= win.destroySurface(cleanupOnResume, mAppStopped);
Robert Carre12aece2016-02-02 22:43:27 -0800965 }
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700966 if (destroyedSomething) {
967 final DisplayContent dc = getDisplayContent();
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700968 dc.assignWindowLayers(true /*setLayoutNeeded*/);
Adrian Roos23df3a32018-03-15 15:41:13 +0100969 updateLetterboxSurface(null);
Robert Carre12aece2016-02-02 22:43:27 -0800970 }
971 }
972
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800973 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700974 * Notify that the app is now resumed, and it was not stopped before, perform a clean
975 * up of the surfaces
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800976 */
Jorim Jaggibae01b12017-04-11 16:29:10 -0700977 void notifyAppResumed(boolean wasStopped) {
Chong Zhangad24f962016-08-25 12:12:33 -0700978 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppResumed: wasStopped=" + wasStopped
Jorim Jaggibae01b12017-04-11 16:29:10 -0700979 + " " + this);
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700980 mAppStopped = false;
chaviwd3bf08d2017-08-01 17:24:59 -0700981 // Allow the window to turn the screen on once the app is resumed again.
982 setCanTurnScreenOn(true);
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700983 if (!wasStopped) {
984 destroySurfaces(true /*cleanupOnResume*/);
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800985 }
Robert Carre12aece2016-02-02 22:43:27 -0800986 }
987
Chong Zhangbef461f2015-10-27 11:38:24 -0700988 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700989 * Notify that the app has stopped, and it is okay to destroy any surfaces which were
990 * keeping alive in case they were still being used.
991 */
992 void notifyAppStopped() {
993 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: " + this);
994 mAppStopped = true;
995 destroySurfaces();
996 // Remove any starting window that was added for this app if they are still around.
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800997 removeStartingWindow();
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700998 }
999
Chong Zhang92147042016-05-09 12:47:11 -07001000 void clearAllDrawn() {
1001 allDrawn = false;
1002 deferClearAllDrawn = false;
Chong Zhangbef461f2015-10-27 11:38:24 -07001003 }
1004
Bryce Lee6d410262017-02-28 15:30:17 -08001005 Task getTask() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001006 return (Task) getParent();
Bryce Lee6d410262017-02-28 15:30:17 -08001007 }
1008
Jorim Jaggi3878ca32017-02-02 17:13:05 -08001009 TaskStack getStack() {
1010 final Task task = getTask();
1011 if (task != null) {
1012 return task.mStack;
1013 } else {
1014 return null;
1015 }
1016 }
1017
Bryce Lee6d410262017-02-28 15:30:17 -08001018 @Override
Riddle Hsu3a4bb612019-01-31 00:02:22 +08001019 void onParentChanged() {
1020 super.onParentChanged();
Bryce Lee6d410262017-02-28 15:30:17 -08001021
Robert Carred3e83b2017-04-21 13:26:55 -07001022 final Task task = getTask();
1023
Bryce Lee6d410262017-02-28 15:30:17 -08001024 // When the associated task is {@code null}, the {@link AppWindowToken} can no longer
1025 // access visual elements like the {@link DisplayContent}. We must remove any associations
1026 // such as animations.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001027 if (!mReparenting) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001028 if (task == null) {
1029 // It is possible we have been marked as a closing app earlier. We must remove ourselves
1030 // from this list so we do not participate in any future animations.
lumark588a3e82018-07-20 18:53:54 +08001031 getDisplayContent().mClosingApps.remove(this);
Robert Carred3e83b2017-04-21 13:26:55 -07001032 } else if (mLastParent != null && mLastParent.mStack != null) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001033 task.mStack.mExitingAppTokens.remove(this);
1034 }
Bryce Lee6d410262017-02-28 15:30:17 -08001035 }
Jorim Jaggi6de61012018-03-19 14:53:23 +01001036 final TaskStack stack = getStack();
1037
1038 // If we reparent, make sure to remove ourselves from the old animation registry.
1039 if (mAnimatingAppWindowTokenRegistry != null) {
1040 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
1041 }
1042 mAnimatingAppWindowTokenRegistry = stack != null
1043 ? stack.getAnimatingAppWindowTokenRegistry()
1044 : null;
1045
Robert Carred3e83b2017-04-21 13:26:55 -07001046 mLastParent = task;
chaviwdcf76ec2019-01-11 16:48:46 -08001047
1048 updateColorTransform();
Bryce Lee6d410262017-02-28 15:30:17 -08001049 }
1050
Wale Ogunwalefa854eb2016-09-20 13:43:52 -07001051 void postWindowRemoveStartingWindowCleanup(WindowState win) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001052 // TODO: Something smells about the code below...Is there a better way?
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001053 if (startingWindow == win) {
1054 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Notify removed startingWindow " + win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001055 removeStartingWindow();
Wale Ogunwale6c459212017-05-17 08:56:03 -07001056 } else if (mChildren.size() == 0) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001057 // If this is the last window and we had requested a starting transition window,
1058 // well there is no point now.
Jorim Jaggi02886a82016-12-06 09:10:06 -08001059 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Nulling last startingData");
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001060 startingData = null;
Wale Ogunwale6c459212017-05-17 08:56:03 -07001061 if (mHiddenSetFromTransferredStartingWindow) {
1062 // We set the hidden state to false for the token from a transferred starting window.
1063 // We now reset it back to true since the starting window was the last window in the
1064 // token.
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001065 setHidden(true);
Wale Ogunwale6c459212017-05-17 08:56:03 -07001066 }
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01001067 } else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001068 // If this is the last window except for a starting transition window,
1069 // we need to get rid of the starting transition.
Jorim Jaggie4b0f282017-05-17 15:10:29 +02001070 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Last window, removing starting window "
1071 + win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001072 removeStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001073 }
1074 }
1075
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001076 void removeDeadWindows() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001077 for (int winNdx = mChildren.size() - 1; winNdx >= 0; --winNdx) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001078 WindowState win = mChildren.get(winNdx);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001079 if (win.mAppDied) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001080 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.w(TAG,
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001081 "removeDeadWindows: " + win);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001082 // Set mDestroying, we don't want any animation or delayed removal here.
1083 win.mDestroying = true;
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001084 // Also removes child windows.
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001085 win.removeIfPossible();
Chong Zhang112eb8c2015-11-02 11:17:00 -08001086 }
1087 }
1088 }
1089
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001090 boolean hasWindowsAlive() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001091 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001092 // No need to loop through child windows as the answer should be the same as that of the
1093 // parent window.
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001094 if (!(mChildren.get(i)).mAppDied) {
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001095 return true;
1096 }
1097 }
1098 return false;
1099 }
1100
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001101 void setWillReplaceWindows(boolean animate) {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001102 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
1103 "Marking app token " + this + " with replacing windows.");
Robert Carra1eb4392015-12-10 12:43:51 -08001104
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001105 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001106 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001107 w.setWillReplaceWindow(animate);
Robert Carra1eb4392015-12-10 12:43:51 -08001108 }
Robert Carra1eb4392015-12-10 12:43:51 -08001109 }
1110
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001111 void setWillReplaceChildWindows() {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001112 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Marking app token " + this
Robert Carr23fa16b2016-01-13 13:19:58 -08001113 + " with replacing child windows.");
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001114 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001115 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001116 w.setWillReplaceChildWindows();
Robert Carr23fa16b2016-01-13 13:19:58 -08001117 }
1118 }
1119
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001120 void clearWillReplaceWindows() {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001121 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
1122 "Resetting app token " + this + " of replacing window marks.");
Chong Zhangf596cd52016-01-05 13:42:44 -08001123
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001124 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001125 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001126 w.clearWillReplaceWindow();
Chong Zhangf596cd52016-01-05 13:42:44 -08001127 }
1128 }
1129
Chong Zhang4d7369a2016-04-25 16:09:14 -07001130 void requestUpdateWallpaperIfNeeded() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001131 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001132 final WindowState w = mChildren.get(i);
Chong Zhang4d7369a2016-04-25 16:09:14 -07001133 w.requestUpdateWallpaperIfNeeded();
1134 }
1135 }
1136
Chong Zhangd78ddb42016-03-02 17:01:14 -08001137 boolean isRelaunching() {
1138 return mPendingRelaunchCount > 0;
1139 }
1140
Robert Carr68375192017-06-13 12:41:53 -07001141 boolean shouldFreezeBounds() {
1142 final Task task = getTask();
1143
1144 // For freeform windows, we can't freeze the bounds at the moment because this would make
1145 // the resizing unresponsive.
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001146 if (task == null || task.inFreeformWindowingMode()) {
Robert Carr68375192017-06-13 12:41:53 -07001147 return false;
1148 }
1149
1150 // We freeze the bounds while drag resizing to deal with the time between
1151 // the divider/drag handle being released, and the handling it's new
1152 // configuration. If we are relaunched outside of the drag resizing state,
1153 // we need to be careful not to do this.
1154 return getTask().isDragResizing();
1155 }
1156
Chong Zhangd78ddb42016-03-02 17:01:14 -08001157 void startRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001158 if (shouldFreezeBounds()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08001159 freezeBounds();
1160 }
Robert Carrd5c7dd62017-03-08 10:39:30 -08001161
1162 // In the process of tearing down before relaunching, the app will
1163 // try and clean up it's child surfaces. We need to prevent this from
1164 // happening, so we sever the children, transfering their ownership
1165 // from the client it-self to the parent surface (owned by us).
Robert Carr29daa922018-04-27 11:56:48 -07001166 detachChildren();
1167
1168 mPendingRelaunchCount++;
1169 }
1170
1171 void detachChildren() {
Robert Carrfd8e93b2018-05-10 13:40:25 -07001172 SurfaceControl.openTransaction();
Robert Carrd5c7dd62017-03-08 10:39:30 -08001173 for (int i = mChildren.size() - 1; i >= 0; i--) {
1174 final WindowState w = mChildren.get(i);
1175 w.mWinAnimator.detachChildren();
1176 }
Robert Carrfd8e93b2018-05-10 13:40:25 -07001177 SurfaceControl.closeTransaction();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001178 }
1179
1180 void finishRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001181 unfreezeBounds();
1182
Chong Zhangd78ddb42016-03-02 17:01:14 -08001183 if (mPendingRelaunchCount > 0) {
1184 mPendingRelaunchCount--;
Bryce Lee081554b2017-05-25 07:52:12 -07001185 } else {
1186 // Update keyguard flags upon finishing relaunch.
1187 checkKeyguardFlagsChanged();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001188 }
1189 }
1190
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001191 void clearRelaunching() {
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001192 if (mPendingRelaunchCount == 0) {
1193 return;
1194 }
Robert Carr68375192017-06-13 12:41:53 -07001195 unfreezeBounds();
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001196 mPendingRelaunchCount = 0;
1197 }
1198
Wale Ogunwale07bcab72016-10-14 15:30:09 -07001199 /**
1200 * Returns true if the new child window we are adding to this token is considered greater than
1201 * the existing child window in this token in terms of z-order.
1202 */
1203 @Override
1204 protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
1205 WindowState existingWindow) {
1206 final int type1 = newWindow.mAttrs.type;
1207 final int type2 = existingWindow.mAttrs.type;
1208
1209 // Base application windows should be z-ordered BELOW all other windows in the app token.
1210 if (type1 == TYPE_BASE_APPLICATION && type2 != TYPE_BASE_APPLICATION) {
1211 return false;
1212 } else if (type1 != TYPE_BASE_APPLICATION && type2 == TYPE_BASE_APPLICATION) {
1213 return true;
1214 }
1215
1216 // Starting windows should be z-ordered ABOVE all other windows in the app token.
1217 if (type1 == TYPE_APPLICATION_STARTING && type2 != TYPE_APPLICATION_STARTING) {
1218 return true;
1219 } else if (type1 != TYPE_APPLICATION_STARTING && type2 == TYPE_APPLICATION_STARTING) {
1220 return false;
1221 }
1222
1223 // Otherwise the new window is greater than the existing window.
1224 return true;
1225 }
1226
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001227 @Override
Robert Carra1eb4392015-12-10 12:43:51 -08001228 void addWindow(WindowState w) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001229 super.addWindow(w);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001230
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001231 boolean gotReplacementWindow = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001232 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001233 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001234 gotReplacementWindow |= candidate.setReplacementWindowIfNeeded(w);
1235 }
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001236
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001237 // if we got a replacement window, reset the timeout to give drawing more time
1238 if (gotReplacementWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001239 mWmService.scheduleWindowReplacementTimeouts(this);
Robert Carra1eb4392015-12-10 12:43:51 -08001240 }
Jorim Jaggife762342016-10-13 14:33:27 +02001241 checkKeyguardFlagsChanged();
1242 }
1243
1244 @Override
1245 void removeChild(WindowState child) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001246 if (!mChildren.contains(child)) {
1247 // This can be true when testing.
1248 return;
1249 }
Jorim Jaggife762342016-10-13 14:33:27 +02001250 super.removeChild(child);
1251 checkKeyguardFlagsChanged();
Adrian Roos23df3a32018-03-15 15:41:13 +01001252 updateLetterboxSurface(child);
Robert Carra1eb4392015-12-10 12:43:51 -08001253 }
1254
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001255 private boolean waitingForReplacement() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001256 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001257 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001258 if (candidate.waitingForReplacement()) {
Robert Carra1eb4392015-12-10 12:43:51 -08001259 return true;
1260 }
1261 }
1262 return false;
1263 }
1264
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001265 void onWindowReplacementTimeout() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001266 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001267 (mChildren.get(i)).onWindowReplacementTimeout();
Robert Carra1eb4392015-12-10 12:43:51 -08001268 }
1269 }
1270
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001271 void reparent(Task task, int position) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001272 if (DEBUG_ADD_REMOVE) {
1273 Slog.i(TAG_WM, "reparent: moving app token=" + this
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001274 + " to task=" + task.mTaskId + " at " + position);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001275 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001276 if (task == null) {
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001277 throw new IllegalArgumentException("reparent: could not find task");
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001278 }
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001279 final Task currentTask = getTask();
1280 if (task == currentTask) {
Winson Chung30480042017-01-26 10:55:34 -08001281 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001282 "window token=" + this + " already child of task=" + currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001283 }
Bryce Lee6d410262017-02-28 15:30:17 -08001284
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001285 if (currentTask.mStack != task.mStack) {
Bryce Lee6d410262017-02-28 15:30:17 -08001286 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001287 "window token=" + this + " current task=" + currentTask
Bryce Lee6d410262017-02-28 15:30:17 -08001288 + " belongs to a different stack than " + task);
1289 }
1290
Winson Chung30480042017-01-26 10:55:34 -08001291 if (DEBUG_ADD_REMOVE) Slog.i(TAG, "reParentWindowToken: removing window token=" + this
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001292 + " from task=" + currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001293 final DisplayContent prevDisplayContent = getDisplayContent();
1294
Bryce Lee6d410262017-02-28 15:30:17 -08001295 mReparenting = true;
1296
Winson Chung30480042017-01-26 10:55:34 -08001297 getParent().removeChild(this);
1298 task.addChild(this, position);
1299
Bryce Lee6d410262017-02-28 15:30:17 -08001300 mReparenting = false;
1301
Winson Chung30480042017-01-26 10:55:34 -08001302 // Relayout display(s).
1303 final DisplayContent displayContent = task.getDisplayContent();
1304 displayContent.setLayoutNeeded();
1305 if (prevDisplayContent != displayContent) {
1306 onDisplayChanged(displayContent);
1307 prevDisplayContent.setLayoutNeeded();
1308 }
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001309 getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
Winson Chung30480042017-01-26 10:55:34 -08001310 }
1311
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001312 @Override
1313 void onDisplayChanged(DisplayContent dc) {
1314 DisplayContent prevDc = mDisplayContent;
1315 super.onDisplayChanged(dc);
Evan Roskyb1e75f72019-04-26 20:23:26 -07001316 if (prevDc == null || prevDc == mDisplayContent) {
Evan Rosky25b56192019-02-06 16:10:56 -08001317 return;
1318 }
1319 if (prevDc.mChangingApps.contains(this)) {
1320 // This gets called *after* the AppWindowToken has been reparented to the new display.
1321 // That reparenting resulted in this window changing modes (eg. FREEFORM -> FULLSCREEN),
1322 // so this token is now "frozen" while waiting for the animation to start on prevDc
1323 // (which will be cancelled since the window is no-longer a child). However, since this
1324 // is no longer a child of prevDc, this won't be notified of the cancelled animation,
1325 // so we need to cancel the change transition here.
1326 clearChangeLeash(getPendingTransaction(), true /* cancel */);
1327 }
1328 if (prevDc.mFocusedApp == this) {
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001329 prevDc.setFocusedApp(null);
lumarkbf844642018-11-23 17:11:36 +08001330 final TaskStack stack = dc.getTopStack();
1331 if (stack != null) {
1332 final Task task = stack.getTopChild();
1333 if (task != null && task.getTopChild() == this) {
1334 dc.setFocusedApp(this);
1335 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001336 }
1337 }
Riddle Hsu192fe762019-01-15 23:41:57 +08001338
Evan Roskyb1e75f72019-04-26 20:23:26 -07001339 if (mLetterbox != null) {
Riddle Hsu192fe762019-01-15 23:41:57 +08001340 mLetterbox.onMovedToDisplay(mDisplayContent.getDisplayId());
1341 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001342 }
1343
Jorim Jaggi0429f352015-12-22 16:29:16 +01001344 /**
1345 * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds
1346 * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even
1347 * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen
1348 * with a queue.
1349 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001350 private void freezeBounds() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001351 final Task task = getTask();
1352 mFrozenBounds.offer(new Rect(task.mPreparedFrozenBounds));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001353
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001354 if (task.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001355 // We didn't call prepareFreezingBounds on the task, so use the current value.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001356 mFrozenMergedConfig.offer(new Configuration(task.getConfiguration()));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001357 } else {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001358 mFrozenMergedConfig.offer(new Configuration(task.mPreparedFrozenMergedConfig));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001359 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001360 // Calling unset() to make it equal to Configuration.EMPTY.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001361 task.mPreparedFrozenMergedConfig.unset();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001362 }
1363
1364 /**
1365 * Unfreezes the previously frozen bounds. See {@link #freezeBounds}.
1366 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001367 private void unfreezeBounds() {
Robert Carr68375192017-06-13 12:41:53 -07001368 if (mFrozenBounds.isEmpty()) {
1369 return;
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001370 }
Robert Carr68375192017-06-13 12:41:53 -07001371 mFrozenBounds.remove();
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001372 if (!mFrozenMergedConfig.isEmpty()) {
1373 mFrozenMergedConfig.remove();
1374 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001375 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001376 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001377 win.onUnfreezeBounds();
Jorim Jaggi4846ee32016-01-07 17:39:12 +01001378 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001379 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001380 }
1381
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001382 void setAppLayoutChanges(int changes, String reason) {
1383 if (!mChildren.isEmpty()) {
1384 final DisplayContent dc = getDisplayContent();
1385 dc.pendingLayoutChanges |= changes;
1386 if (DEBUG_LAYOUT_REPEATS) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001387 mWmService.mWindowPlacerLocked.debugLayoutRepeats(reason, dc.pendingLayoutChanges);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001388 }
1389 }
1390 }
1391
1392 void removeReplacedWindowIfNeeded(WindowState replacement) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001393 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001394 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001395 if (win.removeReplacedWindowIfNeeded(replacement)) {
1396 return;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001397 }
1398 }
1399 }
1400
1401 void startFreezingScreen() {
1402 if (DEBUG_ORIENTATION) logWithStack(TAG, "Set freezing of " + appToken + ": hidden="
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001403 + isHidden() + " freezing=" + mFreezingScreen + " hiddenRequested="
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001404 + hiddenRequested);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001405 if (!hiddenRequested) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001406 if (!mFreezingScreen) {
1407 mFreezingScreen = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001408 mWmService.registerAppFreezeListener(this);
1409 mWmService.mAppsFreezingScreen++;
1410 if (mWmService.mAppsFreezingScreen == 1) {
1411 mWmService.startFreezingDisplayLocked(0, 0, getDisplayContent());
1412 mWmService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
1413 mWmService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001414 }
1415 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001416 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001417 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001418 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001419 w.onStartFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001420 }
1421 }
1422 }
1423
1424 void stopFreezingScreen(boolean unfreezeSurfaceNow, boolean force) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001425 if (!mFreezingScreen) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001426 return;
1427 }
1428 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + this + " force=" + force);
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001429 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001430 boolean unfrozeWindows = false;
1431 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001432 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001433 unfrozeWindows |= w.onStopFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001434 }
1435 if (force || unfrozeWindows) {
1436 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "No longer freezing: " + this);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001437 mFreezingScreen = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001438 mWmService.unregisterAppFreezeListener(this);
1439 mWmService.mAppsFreezingScreen--;
1440 mWmService.mLastFinishedFreezeSource = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001441 }
1442 if (unfreezeSurfaceNow) {
1443 if (unfrozeWindows) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001444 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001445 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001446 mWmService.stopFreezingDisplayLocked();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001447 }
1448 }
1449
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001450 @Override
1451 public void onAppFreezeTimeout() {
1452 Slog.w(TAG_WM, "Force clearing freeze: " + this);
1453 stopFreezingScreen(true, true);
1454 }
1455
Jorim Jaggi60f9c972018-02-01 19:21:07 +01001456 /**
1457 * Tries to transfer the starting window from a token that's above ourselves in the task but
1458 * not visible anymore. This is a common scenario apps use: Trampoline activity T start main
1459 * activity M in the same task. Now, when reopening the task, T starts on top of M but then
1460 * immediately finishes after, so we have to transfer T to M.
1461 */
1462 void transferStartingWindowFromHiddenAboveTokenIfNeeded() {
1463 final Task task = getTask();
1464 for (int i = task.mChildren.size() - 1; i >= 0; i--) {
1465 final AppWindowToken fromToken = task.mChildren.get(i);
1466 if (fromToken == this) {
1467 return;
1468 }
1469 if (fromToken.hiddenRequested && transferStartingWindow(fromToken.token)) {
1470 return;
1471 }
1472 }
1473 }
1474
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001475 boolean transferStartingWindow(IBinder transferFrom) {
Wale Ogunwale02319a62016-09-26 15:21:22 -07001476 final AppWindowToken fromToken = getDisplayContent().getAppWindowToken(transferFrom);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001477 if (fromToken == null) {
1478 return false;
1479 }
1480
1481 final WindowState tStartingWindow = fromToken.startingWindow;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08001482 if (tStartingWindow != null && fromToken.startingSurface != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001483 // In this case, the starting icon has already been displayed, so start
1484 // letting windows get shown immediately without any more transitions.
lumark588a3e82018-07-20 18:53:54 +08001485 getDisplayContent().mSkipAppTransitionAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001486
1487 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Moving existing starting " + tStartingWindow
1488 + " from " + fromToken + " to " + this);
1489
1490 final long origId = Binder.clearCallingIdentity();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001491 try {
1492 // Transfer the starting window over to the new token.
1493 startingData = fromToken.startingData;
1494 startingSurface = fromToken.startingSurface;
1495 startingDisplayed = fromToken.startingDisplayed;
1496 fromToken.startingDisplayed = false;
1497 startingWindow = tStartingWindow;
1498 reportedVisible = fromToken.reportedVisible;
1499 fromToken.startingData = null;
1500 fromToken.startingSurface = null;
1501 fromToken.startingWindow = null;
1502 fromToken.startingMoved = true;
1503 tStartingWindow.mToken = this;
1504 tStartingWindow.mAppToken = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001505
Peter Visontay3556a3b2017-11-01 17:23:17 +00001506 if (DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
1507 "Removing starting " + tStartingWindow + " from " + fromToken);
1508 fromToken.removeChild(tStartingWindow);
1509 fromToken.postWindowRemoveStartingWindowCleanup(tStartingWindow);
1510 fromToken.mHiddenSetFromTransferredStartingWindow = false;
1511 addWindow(tStartingWindow);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001512
Peter Visontay3556a3b2017-11-01 17:23:17 +00001513 // Propagate other interesting state between the tokens. If the old token is displayed,
1514 // we should immediately force the new one to be displayed. If it is animating, we need
1515 // to move that animation to the new one.
1516 if (fromToken.allDrawn) {
1517 allDrawn = true;
1518 deferClearAllDrawn = fromToken.deferClearAllDrawn;
1519 }
1520 if (fromToken.firstWindowDrawn) {
1521 firstWindowDrawn = true;
1522 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001523 if (!fromToken.isHidden()) {
1524 setHidden(false);
Peter Visontay3556a3b2017-11-01 17:23:17 +00001525 hiddenRequested = false;
1526 mHiddenSetFromTransferredStartingWindow = true;
1527 }
1528 setClientHidden(fromToken.mClientHidden);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001529
Jorim Jaggi980c9de2017-11-17 01:41:37 +01001530 transferAnimation(fromToken);
1531
1532 // When transferring an animation, we no longer need to apply an animation to the
1533 // the token we transfer the animation over. Thus, remove the animation from
1534 // pending opening apps.
lumark588a3e82018-07-20 18:53:54 +08001535 getDisplayContent().mOpeningApps.remove(this);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001536
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001537 mWmService.updateFocusedWindowLocked(
Peter Visontay3556a3b2017-11-01 17:23:17 +00001538 UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/);
1539 getDisplayContent().setLayoutNeeded();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001540 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001541 } finally {
1542 Binder.restoreCallingIdentity(origId);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001543 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001544 return true;
1545 } else if (fromToken.startingData != null) {
1546 // The previous app was getting ready to show a
1547 // starting window, but hasn't yet done so. Steal it!
1548 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
1549 "Moving pending starting from " + fromToken + " to " + this);
1550 startingData = fromToken.startingData;
1551 fromToken.startingData = null;
1552 fromToken.startingMoved = true;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001553 scheduleAddStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001554 return true;
1555 }
1556
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001557 // TODO: Transfer thumbnail
1558
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001559 return false;
1560 }
1561
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001562 boolean isLastWindow(WindowState win) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001563 return mChildren.size() == 1 && mChildren.get(0) == win;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001564 }
1565
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001566 @Override
1567 void onAppTransitionDone() {
1568 sendingToBottom = false;
1569 }
1570
Wale Ogunwale51362492016-09-08 17:49:17 -07001571 /**
1572 * We override because this class doesn't want its children affecting its reported orientation
1573 * in anyway.
1574 */
1575 @Override
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001576 int getOrientation(int candidate) {
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001577 if (candidate == SCREEN_ORIENTATION_BEHIND) {
1578 // Allow app to specify orientation regardless of its visibility state if the current
1579 // candidate want us to use orientation behind. I.e. the visible app on-top of this one
1580 // wants us to use the orientation of the app behind it.
1581 return mOrientation;
1582 }
1583
Bryce Lee61fbcbc2017-03-10 14:14:03 -08001584 // The {@link AppWindowToken} should only specify an orientation when it is not closing or
1585 // going to the bottom. Allowing closing {@link AppWindowToken} to participate can lead to
1586 // an Activity in another task being started in the wrong orientation during the transition.
lumark588a3e82018-07-20 18:53:54 +08001587 if (!(sendingToBottom || getDisplayContent().mClosingApps.contains(this))
1588 && (isVisible() || getDisplayContent().mOpeningApps.contains(this))) {
Bryce Leea163b762017-01-24 11:05:01 -08001589 return mOrientation;
Wale Ogunwale51362492016-09-08 17:49:17 -07001590 }
Bryce Leea163b762017-01-24 11:05:01 -08001591
1592 return SCREEN_ORIENTATION_UNSET;
Wale Ogunwale51362492016-09-08 17:49:17 -07001593 }
1594
Wale Ogunwaleb198b742016-12-01 08:44:09 -08001595 /** Returns the app's preferred orientation regardless of its currently visibility state. */
1596 int getOrientationIgnoreVisibility() {
1597 return mOrientation;
1598 }
1599
Riddle Hsub398da32019-01-21 21:48:16 +08001600 /** @return {@code true} if the compatibility bounds is taking effect. */
1601 boolean inSizeCompatMode() {
1602 return mSizeCompatBounds != null;
1603 }
1604
1605 @Override
1606 float getSizeCompatScale() {
1607 return inSizeCompatMode() ? mSizeCompatScale : super.getSizeCompatScale();
1608 }
1609
1610 /**
1611 * @return Non-empty bounds if the activity has override bounds.
1612 * @see ActivityRecord#resolveOverrideConfiguration(Configuration)
1613 */
1614 Rect getResolvedOverrideBounds() {
1615 // Get bounds from resolved override configuration because it is computed with orientation.
1616 return getResolvedOverrideConfiguration().windowConfiguration.getBounds();
1617 }
1618
Craig Mautnerdbb79912012-03-01 18:59:14 -08001619 @Override
Winson Chunge55c0192017-08-24 14:50:48 -07001620 public void onConfigurationChanged(Configuration newParentConfig) {
1621 final int prevWinMode = getWindowingMode();
Evan Rosky2289ba12018-11-19 18:28:18 -08001622 mTmpPrevBounds.set(getBounds());
Winson Chunge55c0192017-08-24 14:50:48 -07001623 super.onConfigurationChanged(newParentConfig);
Riddle Hsub398da32019-01-21 21:48:16 +08001624
1625 final Task task = getTask();
1626 final Rect overrideBounds = getResolvedOverrideBounds();
1627 if (task != null && !overrideBounds.isEmpty()
1628 // If the changes come from change-listener, the incoming parent configuration is
1629 // still the old one. Make sure their orientations are the same to reduce computing
1630 // the compatibility bounds for the intermediate state.
Riddle Hsu04164182019-03-07 18:03:27 +08001631 && (task.mTaskRecord == null || task.mTaskRecord
1632 .getConfiguration().orientation == newParentConfig.orientation)) {
Riddle Hsub398da32019-01-21 21:48:16 +08001633 final Rect taskBounds = task.getBounds();
1634 // Since we only center the activity horizontally, if only the fixed height is smaller
1635 // than its container, the override bounds don't need to take effect.
1636 if ((overrideBounds.width() != taskBounds.width()
1637 || overrideBounds.height() > taskBounds.height())) {
1638 calculateCompatBoundsTransformation(newParentConfig);
1639 updateSurfacePosition();
1640 } else if (mSizeCompatBounds != null) {
1641 mSizeCompatBounds = null;
1642 mSizeCompatScale = 1f;
1643 updateSurfacePosition();
1644 }
1645 }
1646
Winson Chunge55c0192017-08-24 14:50:48 -07001647 final int winMode = getWindowingMode();
1648
1649 if (prevWinMode == winMode) {
1650 return;
1651 }
1652
1653 if (prevWinMode != WINDOWING_MODE_UNDEFINED && winMode == WINDOWING_MODE_PINNED) {
1654 // Entering PiP from fullscreen, reset the snap fraction
1655 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(this);
Winson Chung82267ce2018-04-06 16:38:26 -07001656 } else if (prevWinMode == WINDOWING_MODE_PINNED && winMode != WINDOWING_MODE_UNDEFINED
1657 && !isHidden()) {
Winson Chunge55c0192017-08-24 14:50:48 -07001658 // Leaving PiP to fullscreen, save the snap fraction based on the pre-animation bounds
1659 // for the next re-entry into PiP (assuming the activity is not hidden or destroyed)
1660 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
1661 if (pinnedStack != null) {
Winson Chung8efa1652018-06-06 09:34:23 -07001662 final Rect stackBounds;
1663 if (pinnedStack.lastAnimatingBoundsWasToFullscreen()) {
1664 // We are animating the bounds, use the pre-animation bounds to save the snap
1665 // fraction
1666 stackBounds = pinnedStack.mPreAnimationBounds;
1667 } else {
1668 // We skip the animation if the fullscreen configuration is not compatible, so
1669 // use the current bounds to calculate the saved snap fraction instead
1670 // (see PinnedActivityStack.skipResizeAnimation())
1671 stackBounds = mTmpRect;
1672 pinnedStack.getBounds(stackBounds);
1673 }
Winson Chunge55c0192017-08-24 14:50:48 -07001674 mDisplayContent.mPinnedStackControllerLocked.saveReentrySnapFraction(this,
Winson Chung8efa1652018-06-06 09:34:23 -07001675 stackBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001676 }
Evan Rosky2289ba12018-11-19 18:28:18 -08001677 } else if (shouldStartChangeTransition(prevWinMode, winMode)) {
1678 initializeChangeTransition(mTmpPrevBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001679 }
1680 }
1681
Evan Rosky2289ba12018-11-19 18:28:18 -08001682 private boolean shouldStartChangeTransition(int prevWinMode, int newWinMode) {
Evan Rosky25b56192019-02-06 16:10:56 -08001683 if (mWmService.mDisableTransitionAnimation
1684 || !isVisible()
1685 || getDisplayContent().mAppTransition.isTransitionSet()
1686 || getSurfaceControl() == null) {
Evan Rosky2289ba12018-11-19 18:28:18 -08001687 return false;
1688 }
1689 // Only do an animation into and out-of freeform mode for now. Other mode
1690 // transition animations are currently handled by system-ui.
1691 return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
1692 }
1693
1694 /**
1695 * Initializes a change transition. Because the app is visible already, there is a small period
1696 * of time where the user can see the app content/window update before the transition starts.
1697 * To prevent this, we immediately take a snapshot and place the app/snapshot into a leash which
1698 * "freezes" the location/crop until the transition starts.
1699 * <p>
1700 * Here's a walk-through of the process:
1701 * 1. Create a temporary leash ("interim-change-leash") and reparent the app to it.
1702 * 2. Set the temporary leash's position/crop to the current state.
1703 * 3. Create a snapshot and place that at the top of the leash to cover up content changes.
1704 * 4. Once the transition is ready, it will reparent the app to the animation leash.
1705 * 5. Detach the interim-change-leash.
1706 */
1707 private void initializeChangeTransition(Rect startBounds) {
1708 mDisplayContent.prepareAppTransition(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
1709 false /* alwaysKeepCurrent */, 0, false /* forceOverride */);
1710 mDisplayContent.mChangingApps.add(this);
1711 mTransitStartRect.set(startBounds);
1712
1713 final SurfaceControl.Builder builder = makeAnimationLeash()
1714 .setParent(getAnimationLeashParent())
1715 .setName(getSurfaceControl() + " - interim-change-leash");
1716 mTransitChangeLeash = builder.build();
1717 Transaction t = getPendingTransaction();
1718 t.setWindowCrop(mTransitChangeLeash, startBounds.width(), startBounds.height());
1719 t.setPosition(mTransitChangeLeash, startBounds.left, startBounds.top);
1720 t.show(mTransitChangeLeash);
1721 t.reparent(getSurfaceControl(), mTransitChangeLeash);
1722 onAnimationLeashCreated(t, mTransitChangeLeash);
1723
Evan Rosky966759f2019-01-15 10:33:58 -08001724 // Skip creating snapshot if this transition is controlled by a remote animator which
1725 // doesn't need it.
1726 ArraySet<Integer> activityTypes = new ArraySet<>();
1727 activityTypes.add(getActivityType());
1728 RemoteAnimationAdapter adapter =
1729 mDisplayContent.mAppTransitionController.getRemoteAnimationOverride(
1730 this, TRANSIT_TASK_CHANGE_WINDOWING_MODE, activityTypes);
1731 if (adapter != null && !adapter.getChangeNeedsSnapshot()) {
1732 return;
1733 }
1734
Evan Rosky2289ba12018-11-19 18:28:18 -08001735 if (mThumbnail == null && getTask() != null) {
1736 final TaskSnapshotController snapshotCtrl = mWmService.mTaskSnapshotController;
1737 final ArraySet<Task> tasks = new ArraySet<>();
1738 tasks.add(getTask());
1739 snapshotCtrl.snapshotTasks(tasks);
1740 snapshotCtrl.addSkipClosingAppSnapshotTasks(tasks);
1741 final ActivityManager.TaskSnapshot snapshot = snapshotCtrl.getSnapshot(
1742 getTask().mTaskId, getTask().mUserId, false /* restoreFromDisk */,
1743 false /* reducedResolution */);
Yunfan Chendcb1fcf2019-02-07 19:08:41 +09001744 if (snapshot != null) {
1745 mThumbnail = new AppWindowThumbnail(t, this, snapshot.getSnapshot(),
1746 true /* relative */);
1747 }
Evan Rosky2289ba12018-11-19 18:28:18 -08001748 }
1749 }
1750
1751 boolean isInChangeTransition() {
Evan Roskyec9488c2019-03-01 19:32:12 -08001752 return mTransitChangeLeash != null || AppTransition.isChangeTransit(mTransit);
Evan Rosky2289ba12018-11-19 18:28:18 -08001753 }
1754
Evan Rosky966759f2019-01-15 10:33:58 -08001755 @VisibleForTesting
1756 AppWindowThumbnail getThumbnail() {
1757 return mThumbnail;
1758 }
1759
Riddle Hsub398da32019-01-21 21:48:16 +08001760 /**
1761 * Calculates the scale and offset to horizontal center the size compatibility bounds into the
1762 * region which is available to application.
1763 */
1764 private void calculateCompatBoundsTransformation(Configuration newParentConfig) {
1765 final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds();
Riddle Hsu74826262019-04-17 14:57:42 +08001766 final Rect parentBounds = newParentConfig.windowConfiguration.getBounds();
1767 final Rect viewportBounds = parentAppBounds != null ? parentAppBounds : parentBounds;
Riddle Hsu04164182019-03-07 18:03:27 +08001768 final Rect appBounds = getWindowConfiguration().getAppBounds();
1769 final Rect contentBounds = appBounds != null ? appBounds : getResolvedOverrideBounds();
Riddle Hsub398da32019-01-21 21:48:16 +08001770 final float contentW = contentBounds.width();
1771 final float contentH = contentBounds.height();
1772 final float viewportW = viewportBounds.width();
1773 final float viewportH = viewportBounds.height();
1774 // Only allow to scale down.
1775 mSizeCompatScale = (contentW <= viewportW && contentH <= viewportH)
1776 ? 1 : Math.min(viewportW / contentW, viewportH / contentH);
1777 final int offsetX = (int) ((viewportW - contentW * mSizeCompatScale + 1) * 0.5f)
1778 + viewportBounds.left;
1779
1780 if (mSizeCompatBounds == null) {
1781 mSizeCompatBounds = new Rect();
1782 }
1783 mSizeCompatBounds.set(contentBounds);
1784 mSizeCompatBounds.offsetTo(0, 0);
1785 mSizeCompatBounds.scale(mSizeCompatScale);
Riddle Hsu74826262019-04-17 14:57:42 +08001786 // Ensure to align the top with the parent.
1787 mSizeCompatBounds.top = parentBounds.top;
Riddle Hsu04164182019-03-07 18:03:27 +08001788 // The decor inset is included in height.
1789 mSizeCompatBounds.bottom += viewportBounds.top;
Riddle Hsub398da32019-01-21 21:48:16 +08001790 mSizeCompatBounds.left += offsetX;
1791 mSizeCompatBounds.right += offsetX;
1792 }
1793
1794 @Override
1795 public Rect getBounds() {
1796 if (mSizeCompatBounds != null) {
1797 return mSizeCompatBounds;
1798 }
1799 return super.getBounds();
1800 }
1801
1802 @Override
1803 public boolean matchParentBounds() {
1804 if (super.matchParentBounds()) {
1805 return true;
1806 }
1807 // An activity in size compatibility mode may have override bounds which equals to its
1808 // parent bounds, so the exact bounds should also be checked.
1809 final WindowContainer parent = getParent();
1810 return parent == null || parent.getBounds().equals(getResolvedOverrideBounds());
1811 }
1812
Winson Chunge55c0192017-08-24 14:50:48 -07001813 @Override
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001814 void checkAppWindowsReadyToShow() {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001815 if (allDrawn == mLastAllDrawn) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001816 return;
1817 }
1818
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001819 mLastAllDrawn = allDrawn;
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001820 if (!allDrawn) {
1821 return;
1822 }
1823
1824 // The token has now changed state to having all windows shown... what to do, what to do?
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001825 if (mFreezingScreen) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001826 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001827 stopFreezingScreen(false, true);
1828 if (DEBUG_ORIENTATION) Slog.i(TAG,
1829 "Setting mOrientationChangeComplete=true because wtoken " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001830 + " numInteresting=" + mNumInterestingWindows + " numDrawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001831 // This will set mOrientationChangeComplete and cause a pass through layout.
1832 setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001833 "checkAppWindowsReadyToShow: freezingScreen");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001834 } else {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001835 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001836
1837 // We can now show all of the drawn windows!
lumark588a3e82018-07-20 18:53:54 +08001838 if (!getDisplayContent().mOpeningApps.contains(this) && canShowWindows()) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001839 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001840 }
1841 }
1842 }
1843
Matthew Ng5d23afa2017-06-21 16:16:24 -07001844 /**
Bryce Leed390deb2017-06-22 13:14:28 -07001845 * Returns whether the drawn window states of this {@link AppWindowToken} has considered every
1846 * child {@link WindowState}. A child is considered if it has been passed into
1847 * {@link #updateDrawnWindowStates(WindowState)} after being added. This is used to determine
1848 * whether states, such as {@code allDrawn}, can be set, which relies on state variables such as
1849 * {@code mNumInterestingWindows}, which depend on all {@link WindowState}s being considered.
1850 *
1851 * @return {@code true} If all children have been considered, {@code false}.
1852 */
1853 private boolean allDrawnStatesConsidered() {
Bryce Lee6311c4b2017-07-06 14:09:29 -07001854 for (int i = mChildren.size() - 1; i >= 0; --i) {
1855 final WindowState child = mChildren.get(i);
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001856 if (child.mightAffectAllDrawn() && !child.getDrawnStateEvaluated()) {
Bryce Leed390deb2017-06-22 13:14:28 -07001857 return false;
1858 }
1859 }
1860 return true;
1861 }
1862
1863 /**
Matthew Ng5d23afa2017-06-21 16:16:24 -07001864 * Determines if the token has finished drawing. This should only be called from
1865 * {@link DisplayContent#applySurfaceChangesTransaction}
1866 */
Matthew Ng498c71d2017-04-18 13:55:45 -07001867 void updateAllDrawn() {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001868 if (!allDrawn) {
Matthew Ng498c71d2017-04-18 13:55:45 -07001869 // Number of drawn windows can be less when a window is being relaunched, wait for
Bryce Leed390deb2017-06-22 13:14:28 -07001870 // all windows to be launched and drawn for this token be considered all drawn.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001871 final int numInteresting = mNumInterestingWindows;
Bryce Leed390deb2017-06-22 13:14:28 -07001872
1873 // We must make sure that all present children have been considered (determined by
1874 // {@link #allDrawnStatesConsidered}) before evaluating whether everything has been
1875 // drawn.
1876 if (numInteresting > 0 && allDrawnStatesConsidered()
1877 && mNumDrawnWindows >= numInteresting && !isRelaunching()) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001878 if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawn: " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001879 + " interesting=" + numInteresting + " drawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001880 allDrawn = true;
1881 // Force an additional layout pass where
1882 // WindowStateAnimator#commitFinishDrawingLocked() will call performShowLocked().
Matthew Ng498c71d2017-04-18 13:55:45 -07001883 if (mDisplayContent != null) {
1884 mDisplayContent.setLayoutNeeded();
1885 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001886 mWmService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
Robert Carrecc06b32017-04-18 14:25:10 -07001887
Winson Chunge7ba6862017-05-24 12:13:33 -07001888 // Notify the pinned stack upon all windows drawn. If there was an animation in
1889 // progress then this signal will resume that animation.
Wale Ogunwale61911492017-10-11 08:50:50 -07001890 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
Winson Chunge7ba6862017-05-24 12:13:33 -07001891 if (pinnedStack != null) {
1892 pinnedStack.onAllWindowsDrawn();
Robert Carrecc06b32017-04-18 14:25:10 -07001893 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001894 }
1895 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001896 }
1897
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001898 boolean keyDispatchingTimedOut(String reason, int windowPid) {
1899 return mActivityRecord != null && mActivityRecord.keyDispatchingTimedOut(reason, windowPid);
1900 }
1901
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001902 /**
1903 * Updated this app token tracking states for interesting and drawn windows based on the window.
1904 *
1905 * @return Returns true if the input window is considered interesting and drawn while all the
1906 * windows in this app token where not considered drawn as of the last pass.
1907 */
1908 boolean updateDrawnWindowStates(WindowState w) {
Bryce Leed390deb2017-06-22 13:14:28 -07001909 w.setDrawnStateEvaluated(true /*evaluated*/);
1910
Jorim Jaggie4b0f282017-05-17 15:10:29 +02001911 if (DEBUG_STARTING_WINDOW_VERBOSE && w == startingWindow) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001912 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + w.isOnScreen()
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001913 + " allDrawn=" + allDrawn + " freezingScreen=" + mFreezingScreen);
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001914 }
1915
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001916 if (allDrawn && !mFreezingScreen) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001917 return false;
1918 }
1919
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001920 if (mLastTransactionSequence != mWmService.mTransactionSequence) {
1921 mLastTransactionSequence = mWmService.mTransactionSequence;
Matthew Ng53e66b22018-01-12 17:13:13 -08001922 mNumDrawnWindows = 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001923 startingDisplayed = false;
Matthew Ng53e66b22018-01-12 17:13:13 -08001924
1925 // There is the main base application window, even if it is exiting, wait for it
1926 mNumInterestingWindows = findMainWindow(false /* includeStartingApp */) != null ? 1 : 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001927 }
1928
1929 final WindowStateAnimator winAnimator = w.mWinAnimator;
1930
1931 boolean isInterestingAndDrawn = false;
1932
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001933 if (!allDrawn && w.mightAffectAllDrawn()) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001934 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
1935 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001936 + ", isAnimationSet=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001937 if (!w.isDrawnLw()) {
1938 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController
1939 + " pv=" + w.mPolicyVisibility
1940 + " mDrawState=" + winAnimator.drawStateToString()
1941 + " ph=" + w.isParentWindowHidden() + " th=" + hiddenRequested
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001942 + " a=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001943 }
1944 }
1945
1946 if (w != startingWindow) {
1947 if (w.isInteresting()) {
Matthew Ng53e66b22018-01-12 17:13:13 -08001948 // Add non-main window as interesting since the main app has already been added
1949 if (findMainWindow(false /* includeStartingApp */) != w) {
1950 mNumInterestingWindows++;
1951 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001952 if (w.isDrawnLw()) {
1953 mNumDrawnWindows++;
1954
1955 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, "tokenMayBeDrawn: "
1956 + this + " w=" + w + " numInteresting=" + mNumInterestingWindows
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001957 + " freezingScreen=" + mFreezingScreen
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001958 + " mAppFreezing=" + w.mAppFreezing);
1959
1960 isInterestingAndDrawn = true;
1961 }
1962 }
1963 } else if (w.isDrawnLw()) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001964 if (mActivityRecord != null) {
1965 mActivityRecord.onStartingWindowDrawn(SystemClock.uptimeMillis());
Jorim Jaggi3878ca32017-02-02 17:13:05 -08001966 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001967 startingDisplayed = true;
1968 }
1969 }
1970
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001971 return isInterestingAndDrawn;
1972 }
1973
Adrian Roos23df3a32018-03-15 15:41:13 +01001974 void layoutLetterbox(WindowState winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001975 final WindowState w = findMainWindow();
Adrian Roosf93b6d22018-03-21 13:48:26 +01001976 if (w == null || winHint != null && w != winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001977 return;
1978 }
Jorim Jaggia32da382018-03-28 18:01:22 +02001979 final boolean surfaceReady = w.isDrawnLw() // Regular case
Adrian Roosf93b6d22018-03-21 13:48:26 +01001980 || w.mWinAnimator.mSurfaceDestroyDeferred // The preserved surface is still ready.
1981 || w.isDragResizeChanged(); // Waiting for relayoutWindow to call preserveSurface.
Jorim Jaggi4981f152019-03-26 18:58:45 +01001982 final boolean needsLetterbox = surfaceReady && w.isLetterboxedAppWindow() && fillsParent();
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001983 if (needsLetterbox) {
1984 if (mLetterbox == null) {
1985 mLetterbox = new Letterbox(() -> makeChildSurface(null));
Riddle Hsu192fe762019-01-15 23:41:57 +08001986 mLetterbox.attachInput(w);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001987 }
Adrian Roos7af9d972018-11-30 15:26:27 +01001988 getPosition(mTmpPoint);
Evan Rosky67c15642019-04-24 13:17:28 -07001989 // Get the bounds of the "space-to-fill". In multi-window mode, the task-level
1990 // represents this. In fullscreen-mode, the stack does (since the orientation letterbox
1991 // is also applied to the task).
1992 Rect spaceToFill = (inMultiWindowMode() || getStack() == null)
1993 ? getTask().getDisplayedBounds() : getStack().getDisplayedBounds();
Evan Rosky4fb1e912019-03-06 13:54:43 -08001994 mLetterbox.layout(spaceToFill, w.getFrameLw(), mTmpPoint);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001995 } else if (mLetterbox != null) {
Adrian Roos23df3a32018-03-15 15:41:13 +01001996 mLetterbox.hide();
1997 }
1998 }
1999
2000 void updateLetterboxSurface(WindowState winHint) {
2001 final WindowState w = findMainWindow();
2002 if (w != winHint && winHint != null && w != null) {
2003 return;
2004 }
2005 layoutLetterbox(winHint);
2006 if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) {
2007 mLetterbox.applySurfaceChanges(mPendingTransaction);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002008 }
2009 }
2010
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07002011 @Override
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002012 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002013 // For legacy reasons we process the TaskStack.mExitingAppTokens first in DisplayContent
2014 // before the non-exiting app tokens. So, we skip the exiting app tokens here.
2015 // TODO: Investigate if we need to continue to do this or if we can just process them
2016 // in-order.
2017 if (mIsExiting && !waitingForReplacement()) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002018 return false;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002019 }
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002020 return forAllWindowsUnchecked(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002021 }
2022
lumark588a3e82018-07-20 18:53:54 +08002023 @Override
2024 void forAllAppWindows(Consumer<AppWindowToken> callback) {
2025 callback.accept(this);
2026 }
2027
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002028 boolean forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback,
2029 boolean traverseTopToBottom) {
2030 return super.forAllWindows(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002031 }
2032
2033 @Override
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002034 AppWindowToken asAppWindowToken() {
2035 // I am an app window token!
2036 return this;
2037 }
2038
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002039 boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
2040 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
2041 IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
2042 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
2043 // If the display is frozen, we won't do anything until the actual window is
2044 // displayed so there is no reason to put in the starting window.
2045 if (!okToDisplay()) {
2046 return false;
2047 }
2048
2049 if (startingData != null) {
2050 return false;
2051 }
2052
2053 final WindowState mainWin = findMainWindow();
2054 if (mainWin != null && mainWin.mWinAnimator.getShown()) {
2055 // App already has a visible window...why would you want a starting window?
2056 return false;
2057 }
2058
2059 final ActivityManager.TaskSnapshot snapshot =
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002060 mWmService.mTaskSnapshotController.getSnapshot(
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002061 getTask().mTaskId, getTask().mUserId,
2062 false /* restoreFromDisk */, false /* reducedResolution */);
2063 final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
2064 allowTaskSnapshot, activityCreated, fromRecents, snapshot);
2065
2066 if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
2067 return createSnapshot(snapshot);
2068 }
2069
2070 // If this is a translucent window, then don't show a starting window -- the current
2071 // effect (a full-screen opaque starting window that fades away to the real contents
2072 // when it is ready) does not work for this.
2073 if (DEBUG_STARTING_WINDOW) {
2074 Slog.v(TAG, "Checking theme of starting window: 0x" + Integer.toHexString(theme));
2075 }
2076 if (theme != 0) {
2077 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
2078 com.android.internal.R.styleable.Window,
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002079 mWmService.mCurrentUserId);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002080 if (ent == null) {
2081 // Whoops! App doesn't exist. Um. Okay. We'll just pretend like we didn't
2082 // see that.
2083 return false;
2084 }
2085 final boolean windowIsTranslucent = ent.array.getBoolean(
2086 com.android.internal.R.styleable.Window_windowIsTranslucent, false);
2087 final boolean windowIsFloating = ent.array.getBoolean(
2088 com.android.internal.R.styleable.Window_windowIsFloating, false);
2089 final boolean windowShowWallpaper = ent.array.getBoolean(
2090 com.android.internal.R.styleable.Window_windowShowWallpaper, false);
2091 final boolean windowDisableStarting = ent.array.getBoolean(
2092 com.android.internal.R.styleable.Window_windowDisablePreview, false);
2093 if (DEBUG_STARTING_WINDOW) {
2094 Slog.v(TAG, "Translucent=" + windowIsTranslucent
2095 + " Floating=" + windowIsFloating
2096 + " ShowWallpaper=" + windowShowWallpaper);
2097 }
2098 if (windowIsTranslucent) {
2099 return false;
2100 }
2101 if (windowIsFloating || windowDisableStarting) {
2102 return false;
2103 }
2104 if (windowShowWallpaper) {
2105 if (getDisplayContent().mWallpaperController
2106 .getWallpaperTarget() == null) {
2107 // If this theme is requesting a wallpaper, and the wallpaper
2108 // is not currently visible, then this effectively serves as
2109 // an opaque window and our starting window transition animation
2110 // can still work. We just need to make sure the starting window
2111 // is also showing the wallpaper.
2112 windowFlags |= FLAG_SHOW_WALLPAPER;
2113 } else {
2114 return false;
2115 }
2116 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002117 }
Yunfan Chen8a8c0ed2018-12-18 16:46:32 -08002118
2119 if (transferStartingWindow(transferFrom)) {
2120 return true;
2121 }
2122
2123 // There is no existing starting window, and we don't want to create a splash screen, so
2124 // that's it!
2125 if (type != STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
2126 return false;
2127 }
2128
2129 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SplashScreenStartingData");
2130 startingData = new SplashScreenStartingData(mWmService, pkg,
2131 theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
2132 getMergedOverrideConfiguration());
2133 scheduleAddStartingWindow();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002134 return true;
2135 }
2136
2137
2138 private boolean createSnapshot(ActivityManager.TaskSnapshot snapshot) {
2139 if (snapshot == null) {
2140 return false;
2141 }
2142
2143 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SnapshotStartingData");
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002144 startingData = new SnapshotStartingData(mWmService, snapshot);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002145 scheduleAddStartingWindow();
2146 return true;
2147 }
2148
2149 void scheduleAddStartingWindow() {
2150 // Note: we really want to do sendMessageAtFrontOfQueue() because we
2151 // want to process the message ASAP, before any other queued
2152 // messages.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002153 if (!mWmService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002154 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING");
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002155 mWmService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002156 }
2157 }
2158
2159 private final Runnable mAddStartingWindow = new Runnable() {
2160
2161 @Override
2162 public void run() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002163 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002164 // There can only be one adding request, silly caller!
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002165 mWmService.mAnimationHandler.removeCallbacks(this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002166 }
2167
2168 if (startingData == null) {
2169 // Animation has been canceled... do nothing.
2170 if (DEBUG_STARTING_WINDOW) {
2171 Slog.v(TAG, "startingData was nulled out before handling"
2172 + " mAddStartingWindow: " + AppWindowToken.this);
2173 }
2174 return;
2175 }
2176
2177 if (DEBUG_STARTING_WINDOW) {
2178 Slog.v(TAG, "Add starting " + this + ": startingData=" + startingData);
2179 }
2180
2181 WindowManagerPolicy.StartingSurface surface = null;
2182 try {
2183 surface = startingData.createStartingSurface(AppWindowToken.this);
2184 } catch (Exception e) {
2185 Slog.w(TAG, "Exception when adding starting window", e);
2186 }
2187 if (surface != null) {
2188 boolean abort = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002189 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002190 // If the window was successfully added, then
2191 // we need to remove it.
2192 if (removed || startingData == null) {
2193 if (DEBUG_STARTING_WINDOW) {
2194 Slog.v(TAG, "Aborted starting " + AppWindowToken.this
2195 + ": removed=" + removed + " startingData=" + startingData);
2196 }
2197 startingWindow = null;
2198 startingData = null;
2199 abort = true;
2200 } else {
2201 startingSurface = surface;
2202 }
2203 if (DEBUG_STARTING_WINDOW && !abort) {
2204 Slog.v(TAG, "Added starting " + AppWindowToken.this + ": startingWindow="
2205 + startingWindow + " startingView=" + startingSurface);
2206 }
2207 }
2208 if (abort) {
2209 surface.remove();
2210 }
2211 } else if (DEBUG_STARTING_WINDOW) {
2212 Slog.v(TAG, "Surface returned was null: " + AppWindowToken.this);
2213 }
2214 }
2215 };
2216
2217 private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
2218 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents,
2219 ActivityManager.TaskSnapshot snapshot) {
2220 if (getDisplayContent().mAppTransition.getAppTransition()
2221 == TRANSIT_DOCK_TASK_FROM_RECENTS) {
2222 // TODO(b/34099271): Remove this statement to add back the starting window and figure
2223 // out why it causes flickering, the starting window appears over the thumbnail while
2224 // the docked from recents transition occurs
2225 return STARTING_WINDOW_TYPE_NONE;
2226 } else if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
2227 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2228 } else if (taskSwitch && allowTaskSnapshot) {
Kevin716a9db2018-12-18 16:53:39 -08002229 if (mWmService.mLowRamTaskSnapshotsAndRecents) {
Kevin58b47f12018-12-17 14:09:01 -08002230 // For low RAM devices, we use the splash screen starting window instead of the
2231 // task snapshot starting window.
2232 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2233 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002234 return snapshot == null ? STARTING_WINDOW_TYPE_NONE
2235 : snapshotOrientationSameAsTask(snapshot) || fromRecents
2236 ? STARTING_WINDOW_TYPE_SNAPSHOT : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2237 } else {
2238 return STARTING_WINDOW_TYPE_NONE;
2239 }
2240 }
2241
2242
2243 private boolean snapshotOrientationSameAsTask(ActivityManager.TaskSnapshot snapshot) {
2244 if (snapshot == null) {
2245 return false;
2246 }
2247 return getTask().getConfiguration().orientation == snapshot.getOrientation();
2248 }
2249
2250 void removeStartingWindow() {
2251 if (startingWindow == null) {
2252 if (startingData != null) {
2253 // Starting window has not been added yet, but it is scheduled to be added.
2254 // Go ahead and cancel the request.
2255 if (DEBUG_STARTING_WINDOW) {
2256 Slog.v(TAG_WM, "Clearing startingData for token=" + this);
2257 }
2258 startingData = null;
2259 }
2260 return;
2261 }
2262
2263 final WindowManagerPolicy.StartingSurface surface;
2264 if (startingData != null) {
2265 surface = startingSurface;
2266 startingData = null;
2267 startingSurface = null;
2268 startingWindow = null;
2269 startingDisplayed = false;
2270 if (surface == null) {
2271 if (DEBUG_STARTING_WINDOW) {
2272 Slog.v(TAG_WM, "startingWindow was set but startingSurface==null, couldn't "
2273 + "remove");
2274 }
2275 return;
2276 }
2277 } else {
2278 if (DEBUG_STARTING_WINDOW) {
2279 Slog.v(TAG_WM, "Tried to remove starting window but startingWindow was null:"
2280 + this);
2281 }
2282 return;
2283 }
2284
2285 if (DEBUG_STARTING_WINDOW) {
2286 Slog.v(TAG_WM, "Schedule remove starting " + this
2287 + " startingWindow=" + startingWindow
2288 + " startingView=" + startingSurface
2289 + " Callers=" + Debug.getCallers(5));
2290 }
2291
2292 // Use the same thread to remove the window as we used to add it, as otherwise we end up
2293 // with things in the view hierarchy being called from different threads.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002294 mWmService.mAnimationHandler.post(() -> {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002295 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Removing startingView=" + surface);
2296 try {
2297 surface.remove();
2298 } catch (Exception e) {
2299 Slog.w(TAG_WM, "Exception when removing starting window", e);
2300 }
2301 });
2302 }
2303
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002304 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -07002305 boolean fillsParent() {
2306 return mFillsParent;
2307 }
2308
2309 void setFillsParent(boolean fillsParent) {
2310 mFillsParent = fillsParent;
2311 }
2312
Jorim Jaggife762342016-10-13 14:33:27 +02002313 boolean containsDismissKeyguardWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002314 // Window state is transient during relaunch. We are not guaranteed to be frozen during the
2315 // entirety of the relaunch.
2316 if (isRelaunching()) {
2317 return mLastContainsDismissKeyguardWindow;
2318 }
2319
Jorim Jaggife762342016-10-13 14:33:27 +02002320 for (int i = mChildren.size() - 1; i >= 0; i--) {
2321 if ((mChildren.get(i).mAttrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
2322 return true;
2323 }
2324 }
2325 return false;
2326 }
2327
2328 boolean containsShowWhenLockedWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002329 // When we are relaunching, it is possible for us to be unfrozen before our previous
2330 // windows have been added back. Using the cached value ensures that our previous
2331 // showWhenLocked preference is honored until relaunching is complete.
2332 if (isRelaunching()) {
2333 return mLastContainsShowWhenLockedWindow;
2334 }
2335
Jorim Jaggife762342016-10-13 14:33:27 +02002336 for (int i = mChildren.size() - 1; i >= 0; i--) {
2337 if ((mChildren.get(i).mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
2338 return true;
2339 }
2340 }
Bryce Lee081554b2017-05-25 07:52:12 -07002341
Jorim Jaggife762342016-10-13 14:33:27 +02002342 return false;
2343 }
2344
2345 void checkKeyguardFlagsChanged() {
2346 final boolean containsDismissKeyguard = containsDismissKeyguardWindow();
2347 final boolean containsShowWhenLocked = containsShowWhenLockedWindow();
2348 if (containsDismissKeyguard != mLastContainsDismissKeyguardWindow
2349 || containsShowWhenLocked != mLastContainsShowWhenLockedWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002350 mWmService.notifyKeyguardFlagsChanged(null /* callback */,
lumark588a3e82018-07-20 18:53:54 +08002351 getDisplayContent().getDisplayId());
Jorim Jaggife762342016-10-13 14:33:27 +02002352 }
2353 mLastContainsDismissKeyguardWindow = containsDismissKeyguard;
2354 mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
2355 }
2356
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002357 WindowState getImeTargetBelowWindow(WindowState w) {
2358 final int index = mChildren.indexOf(w);
2359 if (index > 0) {
2360 final WindowState target = mChildren.get(index - 1);
2361 if (target.canBeImeTarget()) {
2362 return target;
2363 }
2364 }
2365 return null;
2366 }
2367
2368 WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
2369 WindowState candidate = null;
2370 for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
2371 final WindowState w = mChildren.get(i);
2372 if (w.mRemoved) {
2373 continue;
2374 }
Jorim Jaggi35d328a2018-08-14 17:00:20 +02002375 if (candidate == null) {
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002376 candidate = w;
2377 }
2378 }
2379 return candidate;
2380 }
2381
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002382 /**
2383 * See {@link Activity#setDisablePreviewScreenshots}.
2384 */
2385 void setDisablePreviewScreenshots(boolean disable) {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002386 mDisablePreviewScreenshots = disable;
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002387 }
2388
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002389 /**
chaviwd3bf08d2017-08-01 17:24:59 -07002390 * Sets whether the current launch can turn the screen on. See {@link #canTurnScreenOn()}
2391 */
2392 void setCanTurnScreenOn(boolean canTurnScreenOn) {
2393 mCanTurnScreenOn = canTurnScreenOn;
2394 }
2395
2396 /**
2397 * Indicates whether the current launch can turn the screen on. This is to prevent multiple
2398 * relayouts from turning the screen back on. The screen should only turn on at most
2399 * once per activity resume.
2400 *
2401 * @return true if the screen can be turned on.
2402 */
2403 boolean canTurnScreenOn() {
2404 return mCanTurnScreenOn;
2405 }
2406
2407 /**
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002408 * Retrieves whether we'd like to generate a snapshot that's based solely on the theme. This is
2409 * the case when preview screenshots are disabled {@link #setDisablePreviewScreenshots} or when
2410 * we can't take a snapshot for other reasons, for example, if we have a secure window.
2411 *
2412 * @return True if we need to generate an app theme snapshot, false if we'd like to take a real
2413 * screenshot.
2414 */
2415 boolean shouldUseAppThemeSnapshot() {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002416 return mDisablePreviewScreenshots || forAllWindows(w -> (w.mAttrs.flags & FLAG_SECURE) != 0,
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002417 true /* topToBottom */);
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002418 }
2419
Jorim Jaggibe418292018-03-26 16:14:12 +02002420 SurfaceControl getAppAnimationLayer() {
Jorim Jaggi391790622018-04-18 15:30:44 +02002421 return getAppAnimationLayer(isActivityTypeHome() ? ANIMATION_LAYER_HOME
2422 : needsZBoost() ? ANIMATION_LAYER_BOOSTED
2423 : ANIMATION_LAYER_STANDARD);
Jorim Jaggibe418292018-03-26 16:14:12 +02002424 }
2425
chaviw23ee71c2017-12-18 11:29:41 -08002426 @Override
Jorim Jaggi596a1992017-12-29 14:48:02 +01002427 public SurfaceControl getAnimationLeashParent() {
Robert Carrb9506032018-02-13 13:54:00 -08002428 // All normal app transitions take place in an animation layer which is below the pinned
2429 // stack but may be above the parent stacks of the given animating apps.
2430 // For transitions in the pinned stack (menu activity) we just let them occur as a child
2431 // of the pinned stack.
2432 if (!inPinnedWindowingMode()) {
2433 return getAppAnimationLayer();
2434 } else {
2435 return getStack().getSurfaceControl();
2436 }
chaviw23ee71c2017-12-18 11:29:41 -08002437 }
2438
Jorim Jaggic6976f02018-04-18 16:31:07 +02002439 private boolean shouldAnimate(int transit) {
2440 final boolean isSplitScreenPrimary =
2441 getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
2442 final boolean allowSplitScreenPrimaryAnimation = transit != TRANSIT_WALLPAPER_OPEN;
2443
lumark54284462019-03-05 20:44:27 +08002444 // Don't animate when the task runs recents animation.
2445 final RecentsAnimationController controller = mWmService.getRecentsAnimationController();
2446 if (controller != null && controller.isAnimatingTask(getTask())) {
2447 return false;
2448 }
2449
Jorim Jaggic6976f02018-04-18 16:31:07 +02002450 // We animate always if it's not split screen primary, and only some special cases in split
2451 // screen primary because it causes issues with stack clipping when we run an un-minimize
2452 // animation at the same time.
2453 return !isSplitScreenPrimary || allowSplitScreenPrimaryAnimation;
2454 }
2455
Vishnu Naira2977262018-07-26 13:31:26 -07002456 /**
2457 * Creates a layer to apply crop to an animation.
2458 */
2459 private SurfaceControl createAnimationBoundsLayer(Transaction t) {
2460 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.i(TAG, "Creating animation bounds layer");
2461 final SurfaceControl.Builder builder = makeAnimationLeash()
2462 .setParent(getAnimationLeashParent())
Vishnu Naire86bd982018-11-28 13:23:17 -08002463 .setName(getSurfaceControl() + " - animation-bounds");
Vishnu Naira2977262018-07-26 13:31:26 -07002464 final SurfaceControl boundsLayer = builder.build();
2465 t.show(boundsLayer);
2466 return boundsLayer;
2467 }
2468
Evan Roskyed6767f2018-10-26 17:21:06 -07002469 @Override
2470 Rect getDisplayedBounds() {
2471 final Task task = getTask();
2472 if (task != null) {
2473 final Rect overrideDisplayedBounds = task.getOverrideDisplayedBounds();
2474 if (!overrideDisplayedBounds.isEmpty()) {
2475 return overrideDisplayedBounds;
2476 }
2477 }
2478 return getBounds();
2479 }
2480
Evan Rosky641daea2019-04-24 14:45:24 -07002481 @VisibleForTesting
2482 Rect getAnimationBounds(int appStackClipMode) {
2483 if (appStackClipMode == STACK_CLIP_BEFORE_ANIM && getStack() != null) {
2484 // Using the stack bounds here effectively applies the clipping before animation.
2485 return getStack().getBounds();
2486 }
2487 // Use task-bounds if available so that activity-level letterbox (maxAspectRatio) is
2488 // included in the animation.
2489 return getTask() != null ? getTask().getBounds() : getBounds();
2490 }
2491
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002492 boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter,
2493 boolean isVoiceInteraction) {
2494
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002495 if (mWmService.mDisableTransitionAnimation || !shouldAnimate(transit)) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002496 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
Jorim Jaggic6976f02018-04-18 16:31:07 +02002497 Slog.v(TAG_WM, "applyAnimation: transition animation is disabled or skipped."
2498 + " atoken=" + this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002499 }
2500 cancelAnimation();
2501 return false;
2502 }
2503
2504 // Only apply an animation if the display isn't frozen. If it is frozen, there is no reason
2505 // to animate and it can cause strange artifacts when we unfreeze the display if some
2506 // different animation is running.
2507 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#applyAnimationLocked");
2508 if (okToAnimate()) {
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002509 final AnimationAdapter adapter;
Evan Rosky2289ba12018-11-19 18:28:18 -08002510 AnimationAdapter thumbnailAdapter = null;
Evan Rosky4fb1e912019-03-06 13:54:43 -08002511
Evan Rosky641daea2019-04-24 14:45:24 -07002512 final int appStackClipMode =
2513 getDisplayContent().mAppTransition.getAppStackClipMode();
2514
2515 // Separate position and size for use in animators.
2516 mTmpRect.set(getAnimationBounds(appStackClipMode));
Evan Rosky4fb1e912019-03-06 13:54:43 -08002517 mTmpPoint.set(mTmpRect.left, mTmpRect.top);
2518 mTmpRect.offsetTo(0, 0);
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002519
Evan Roskyec9488c2019-03-01 19:32:12 -08002520 final boolean isChanging = AppTransition.isChangeTransit(transit) && enter
2521 && getDisplayContent().mChangingApps.contains(this);
Evan Rosky2289ba12018-11-19 18:28:18 -08002522
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002523 // Delaying animation start isn't compatible with remote animations at all.
lumark588a3e82018-07-20 18:53:54 +08002524 if (getDisplayContent().mAppTransition.getRemoteAnimationController() != null
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002525 && !mSurfaceAnimator.isAnimationStartDelayed()) {
Evan Rosky2289ba12018-11-19 18:28:18 -08002526 RemoteAnimationRecord adapters =
2527 getDisplayContent().mAppTransition.getRemoteAnimationController()
2528 .createRemoteAnimationRecord(this, mTmpPoint, mTmpRect,
2529 (isChanging ? mTransitStartRect : null));
2530 adapter = adapters.mAdapter;
2531 thumbnailAdapter = adapters.mThumbnailAdapter;
2532 } else if (isChanging) {
Evan Roskycf76bed2019-01-15 10:33:58 -08002533 final float durationScale = mWmService.getTransitionAnimationScaleLocked();
Evan Rosky2289ba12018-11-19 18:28:18 -08002534 mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y);
2535 adapter = new LocalAnimationAdapter(
2536 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
Evan Roskycf76bed2019-01-15 10:33:58 -08002537 getDisplayContent().getDisplayInfo(), durationScale,
Evan Rosky2289ba12018-11-19 18:28:18 -08002538 true /* isAppAnimation */, false /* isThumbnail */),
2539 mWmService.mSurfaceAnimationRunner);
Evan Rosky966759f2019-01-15 10:33:58 -08002540 if (mThumbnail != null) {
2541 thumbnailAdapter = new LocalAnimationAdapter(
2542 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
Evan Roskycf76bed2019-01-15 10:33:58 -08002543 getDisplayContent().getDisplayInfo(), durationScale,
Evan Rosky966759f2019-01-15 10:33:58 -08002544 true /* isAppAnimation */, true /* isThumbnail */),
2545 mWmService.mSurfaceAnimationRunner);
2546 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002547 mTransit = transit;
2548 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002549 } else {
Vishnu Naira2977262018-07-26 13:31:26 -07002550 mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM);
2551
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002552 final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
2553 if (a != null) {
2554 adapter = new LocalAnimationAdapter(
2555 new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
lumark588a3e82018-07-20 18:53:54 +08002556 getDisplayContent().mAppTransition.canSkipFirstFrame(),
Vishnu Naira2977262018-07-26 13:31:26 -07002557 appStackClipMode,
Lucas Dupin3e1dc202018-12-02 15:14:20 -08002558 true /* isAppAnimation */,
Tiger Huangdc50bb52019-04-24 18:39:53 +08002559 getWindowCornerRadiusForAnimation()),
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002560 mWmService.mSurfaceAnimationRunner);
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002561 if (a.getZAdjustment() == Animation.ZORDER_TOP) {
2562 mNeedsZBoost = true;
2563 }
2564 mTransit = transit;
lumark588a3e82018-07-20 18:53:54 +08002565 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002566 } else {
2567 adapter = null;
chaviw23ee71c2017-12-18 11:29:41 -08002568 }
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002569 }
2570 if (adapter != null) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002571 startAnimation(getPendingTransaction(), adapter, !isVisible());
Jorim Jaggi82c17862018-02-21 17:50:18 +01002572 if (adapter.getShowWallpaper()) {
2573 mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2574 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002575 if (thumbnailAdapter != null) {
2576 mThumbnail.startAnimation(
2577 getPendingTransaction(), thumbnailAdapter, !isVisible());
2578 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002579 }
2580 } else {
2581 cancelAnimation();
2582 }
2583 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2584
2585 return isReallyAnimating();
2586 }
2587
2588 private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
2589 boolean isVoiceInteraction) {
2590 final DisplayContent displayContent = getTask().getDisplayContent();
2591 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2592 final int width = displayInfo.appWidth;
2593 final int height = displayInfo.appHeight;
2594 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG_WM,
2595 "applyAnimation: atoken=" + this);
2596
2597 // Determine the visible rect to calculate the thumbnail clip
2598 final WindowState win = findMainWindow();
2599 final Rect frame = new Rect(0, 0, width, height);
2600 final Rect displayFrame = new Rect(0, 0,
2601 displayInfo.logicalWidth, displayInfo.logicalHeight);
2602 final Rect insets = new Rect();
2603 final Rect stableInsets = new Rect();
2604 Rect surfaceInsets = null;
2605 final boolean freeform = win != null && win.inFreeformWindowingMode();
2606 if (win != null) {
2607 // Containing frame will usually cover the whole screen, including dialog windows.
2608 // For freeform workspace windows it will not cover the whole screen and it also
2609 // won't exactly match the final freeform window frame (e.g. when overlapping with
2610 // the status bar). In that case we need to use the final frame.
2611 if (freeform) {
chaviw492139a2018-07-16 16:07:35 -07002612 frame.set(win.getFrameLw());
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002613 } else if (win.isLetterboxedAppWindow()) {
2614 frame.set(getTask().getBounds());
Winson Chungc1674272018-02-21 10:15:17 -08002615 } else if (win.isDockedResizing()) {
2616 // If we are animating while docked resizing, then use the stack bounds as the
2617 // animation target (which will be different than the task bounds)
2618 frame.set(getTask().getParent().getBounds());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002619 } else {
chaviw553b0212018-07-12 13:37:01 -07002620 frame.set(win.getContainingFrame());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002621 }
2622 surfaceInsets = win.getAttrs().surfaceInsets;
Adrian Roos20e07892018-02-23 19:12:01 +01002623 // XXX(b/72757033): These are insets relative to the window frame, but we're really
2624 // interested in the insets relative to the frame we chose in the if-blocks above.
chaviw9c81e632018-07-31 11:17:52 -07002625 win.getContentInsets(insets);
2626 win.getStableInsets(stableInsets);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002627 }
2628
2629 if (mLaunchTaskBehind) {
2630 // Differentiate the two animations. This one which is briefly on the screen
2631 // gets the !enter animation, and the other activity which remains on the
2632 // screen gets the enter animation. Both appear in the mOpeningApps set.
2633 enter = false;
2634 }
2635 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "Loading animation for app transition."
2636 + " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter
2637 + " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets);
2638 final Configuration displayConfig = displayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08002639 final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002640 displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
2641 surfaceInsets, stableInsets, isVoiceInteraction, freeform, getTask().mTaskId);
2642 if (a != null) {
2643 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
2644 final int containingWidth = frame.width();
2645 final int containingHeight = frame.height();
2646 a.initialize(containingWidth, containingHeight, width, height);
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002647 a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002648 }
2649 return a;
2650 }
2651
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002652 @Override
Jorim Jaggi6de61012018-03-19 14:53:23 +01002653 public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
2654 return mAnimatingAppWindowTokenRegistry != null
2655 && mAnimatingAppWindowTokenRegistry.notifyAboutToFinish(
2656 this, endDeferFinishCallback);
2657 }
2658
2659 @Override
2660 public void onAnimationLeashDestroyed(Transaction t) {
2661 super.onAnimationLeashDestroyed(t);
Vishnu Naira2977262018-07-26 13:31:26 -07002662 if (mAnimationBoundsLayer != null) {
Robert Carr71200f22019-02-05 09:44:53 -08002663 t.remove(mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002664 mAnimationBoundsLayer = null;
2665 }
2666
Jorim Jaggi6de61012018-03-19 14:53:23 +01002667 if (mAnimatingAppWindowTokenRegistry != null) {
2668 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
2669 }
2670 }
2671
2672 @Override
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002673 protected void setLayer(Transaction t, int layer) {
2674 if (!mSurfaceAnimator.hasLeash()) {
2675 t.setLayer(mSurfaceControl, layer);
2676 }
2677 }
2678
2679 @Override
2680 protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
2681 if (!mSurfaceAnimator.hasLeash()) {
2682 t.setRelativeLayer(mSurfaceControl, relativeTo, layer);
2683 }
2684 }
2685
2686 @Override
2687 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
2688 if (!mSurfaceAnimator.hasLeash()) {
Robert Carr10584fa2019-01-14 15:55:19 -08002689 t.reparent(mSurfaceControl, newParent);
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002690 }
2691 }
2692
2693 @Override
2694 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002695 // The leash is parented to the animation layer. We need to preserve the z-order by using
2696 // the prefix order index, but we boost if necessary.
Robert Carrb9506032018-02-13 13:54:00 -08002697 int layer = 0;
2698 if (!inPinnedWindowingMode()) {
2699 layer = getPrefixOrderIndex();
2700 } else {
2701 // Pinned stacks have animations take place within themselves rather than an animation
2702 // layer so we need to preserve the order relative to the stack (e.g. the order of our
2703 // task/parent).
2704 layer = getParent().getPrefixOrderIndex();
2705 }
2706
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002707 if (mNeedsZBoost) {
2708 layer += Z_BOOST_BASE;
2709 }
Jorim Jaggi9cd99132019-04-24 17:41:35 +02002710 if (!mNeedsAnimationBoundsLayer) {
2711 leash.setLayer(layer);
2712 }
Robert Carr2f8aa392018-01-31 14:46:51 -08002713
2714 final DisplayContent dc = getDisplayContent();
Jorim Jaggibe418292018-03-26 16:14:12 +02002715 dc.assignStackOrdering();
Evan Rosky2289ba12018-11-19 18:28:18 -08002716
2717 if (leash == mTransitChangeLeash) {
2718 // This is a temporary state so skip any animation notifications
2719 return;
2720 } else if (mTransitChangeLeash != null) {
2721 // unparent mTransitChangeLeash for clean-up
Evan Rosky25b56192019-02-06 16:10:56 -08002722 clearChangeLeash(t, false /* cancel */);
Evan Rosky2289ba12018-11-19 18:28:18 -08002723 }
2724
Jorim Jaggi6de61012018-03-19 14:53:23 +01002725 if (mAnimatingAppWindowTokenRegistry != null) {
2726 mAnimatingAppWindowTokenRegistry.notifyStarting(this);
2727 }
Vishnu Naira2977262018-07-26 13:31:26 -07002728
2729 // If the animation needs to be cropped then an animation bounds layer is created as a child
2730 // of the pinned stack or animation layer. The leash is then reparented to this new layer.
2731 if (mNeedsAnimationBoundsLayer) {
Evan Rosky7735d352019-03-18 17:27:27 -07002732 mTmpRect.setEmpty();
2733 final Task task = getTask();
2734 if (getDisplayContent().mAppTransitionController.isTransitWithinTask(
2735 getTransit(), task)) {
2736 task.getBounds(mTmpRect);
2737 } else {
2738 final TaskStack stack = getStack();
2739 if (stack == null) {
2740 return;
2741 }
2742 // Set clip rect to stack bounds.
2743 stack.getBounds(mTmpRect);
Vishnu Naira2977262018-07-26 13:31:26 -07002744 }
2745 mAnimationBoundsLayer = createAnimationBoundsLayer(t);
2746
Vishnu Naira2977262018-07-26 13:31:26 -07002747 // Crop to stack bounds.
2748 t.setWindowCrop(mAnimationBoundsLayer, mTmpRect);
Jorim Jaggi9cd99132019-04-24 17:41:35 +02002749 t.setLayer(mAnimationBoundsLayer, layer);
Vishnu Naira2977262018-07-26 13:31:26 -07002750
2751 // Reparent leash to animation bounds layer.
Robert Carr10584fa2019-01-14 15:55:19 -08002752 t.reparent(leash, mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002753 }
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002754 }
2755
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002756 /**
2757 * This must be called while inside a transaction.
2758 */
2759 void showAllWindowsLocked() {
2760 forAllWindows(windowState -> {
2761 if (DEBUG_VISIBILITY) Slog.v(TAG, "performing show on: " + windowState);
2762 windowState.performShowLocked();
2763 }, false /* traverseTopToBottom */);
Jorim Jaggia5e10572017-11-15 14:36:26 +01002764 }
2765
2766 @Override
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002767 protected void onAnimationFinished() {
2768 super.onAnimationFinished();
2769
2770 mTransit = TRANSIT_UNSET;
2771 mTransitFlags = 0;
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002772 mNeedsZBoost = false;
Vishnu Naira2977262018-07-26 13:31:26 -07002773 mNeedsAnimationBoundsLayer = false;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002774
2775 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER,
2776 "AppWindowToken");
2777
Jorim Jaggi988f6682017-11-17 17:46:43 +01002778 clearThumbnail();
Jorim Jaggi752cd822018-03-29 16:29:18 +02002779 setClientHidden(isHidden() && hiddenRequested);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002780
lumarkff0ab692018-11-05 20:32:30 +08002781 getDisplayContent().computeImeTargetIfNeeded(this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002782
2783 if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + this
2784 + ": reportedVisible=" + reportedVisible
2785 + " okToDisplay=" + okToDisplay()
2786 + " okToAnimate=" + okToAnimate()
2787 + " startingDisplayed=" + startingDisplayed);
2788
Evan Rosky2289ba12018-11-19 18:28:18 -08002789 // clean up thumbnail window
2790 if (mThumbnail != null) {
2791 mThumbnail.destroy();
2792 mThumbnail = null;
2793 }
2794
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002795 // WindowState.onExitAnimationDone might modify the children list, so make a copy and then
2796 // traverse the copy.
2797 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
2798 children.forEach(WindowState::onExitAnimationDone);
2799
lumark588a3e82018-07-20 18:53:54 +08002800 getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002801 scheduleAnimation();
Jorim Jaggi9b5e3312019-03-01 18:08:00 +01002802
2803 mActivityRecord.onAnimationFinished();
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002804 }
2805
2806 @Override
2807 boolean isAppAnimating() {
2808 return isSelfAnimating();
2809 }
2810
2811 @Override
2812 boolean isSelfAnimating() {
2813 // If we are about to start a transition, we also need to be considered animating.
2814 return isWaitingForTransitionStart() || isReallyAnimating();
2815 }
2816
2817 /**
2818 * @return True if and only if we are actually running an animation. Note that
2819 * {@link #isSelfAnimating} also returns true if we are waiting for an animation to
2820 * start.
2821 */
2822 private boolean isReallyAnimating() {
2823 return super.isSelfAnimating();
2824 }
2825
Evan Rosky25b56192019-02-06 16:10:56 -08002826 /**
2827 * @param cancel {@code true} if clearing the leash due to cancelling instead of transferring
2828 * to another leash.
2829 */
2830 private void clearChangeLeash(Transaction t, boolean cancel) {
2831 if (mTransitChangeLeash == null) {
2832 return;
2833 }
2834 if (cancel) {
2835 clearThumbnail();
2836 SurfaceControl sc = getSurfaceControl();
2837 SurfaceControl parentSc = getParentSurfaceControl();
2838 // Don't reparent if surface is getting destroyed
2839 if (parentSc != null && sc != null) {
2840 t.reparent(sc, getParentSurfaceControl());
2841 }
2842 }
2843 t.hide(mTransitChangeLeash);
2844 t.reparent(mTransitChangeLeash, null);
2845 mTransitChangeLeash = null;
2846 if (cancel) {
2847 onAnimationLeashDestroyed(t);
2848 }
2849 }
2850
Jorim Jaggi988f6682017-11-17 17:46:43 +01002851 @Override
2852 void cancelAnimation() {
Evan Rosky2289ba12018-11-19 18:28:18 -08002853 cancelAnimationOnly();
Jorim Jaggi988f6682017-11-17 17:46:43 +01002854 clearThumbnail();
Evan Rosky25b56192019-02-06 16:10:56 -08002855 clearChangeLeash(getPendingTransaction(), true /* cancel */);
Evan Rosky2289ba12018-11-19 18:28:18 -08002856 }
2857
2858 /**
2859 * This only cancels the animation. It doesn't do other teardown like cleaning-up thumbnail
2860 * or interim leashes.
2861 * <p>
2862 * Used when canceling in preparation for starting a new animation.
2863 */
2864 void cancelAnimationOnly() {
2865 super.cancelAnimation();
Jorim Jaggi988f6682017-11-17 17:46:43 +01002866 }
2867
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002868 boolean isWaitingForTransitionStart() {
lumark588a3e82018-07-20 18:53:54 +08002869 return getDisplayContent().mAppTransition.isTransitionSet()
2870 && (getDisplayContent().mOpeningApps.contains(this)
Evan Rosky2289ba12018-11-19 18:28:18 -08002871 || getDisplayContent().mClosingApps.contains(this)
2872 || getDisplayContent().mChangingApps.contains(this));
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002873 }
2874
2875 public int getTransit() {
2876 return mTransit;
2877 }
2878
2879 int getTransitFlags() {
2880 return mTransitFlags;
2881 }
2882
Jorim Jaggi988f6682017-11-17 17:46:43 +01002883 void attachThumbnailAnimation() {
2884 if (!isReallyAnimating()) {
2885 return;
2886 }
2887 final int taskId = getTask().mTaskId;
2888 final GraphicBuffer thumbnailHeader =
lumark588a3e82018-07-20 18:53:54 +08002889 getDisplayContent().mAppTransition.getAppTransitionThumbnailHeader(taskId);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002890 if (thumbnailHeader == null) {
2891 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG, "No thumbnail header bitmap for: " + taskId);
2892 return;
2893 }
2894 clearThumbnail();
2895 mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnailHeader);
2896 mThumbnail.startAnimation(getPendingTransaction(), loadThumbnailAnimation(thumbnailHeader));
2897 }
2898
Tony Mak64b8d562017-12-28 17:44:02 +00002899 /**
2900 * Attaches a surface with a thumbnail for the
2901 * {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation.
2902 */
2903 void attachCrossProfileAppsThumbnailAnimation() {
2904 if (!isReallyAnimating()) {
2905 return;
2906 }
2907 clearThumbnail();
2908
2909 final WindowState win = findMainWindow();
2910 if (win == null) {
2911 return;
2912 }
chaviw492139a2018-07-16 16:07:35 -07002913 final Rect frame = win.getFrameLw();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002914 final int thumbnailDrawableRes = getTask().mUserId == mWmService.mCurrentUserId
Tony Mak64b8d562017-12-28 17:44:02 +00002915 ? R.drawable.ic_account_circle
Tony Makda4af232018-04-27 11:01:10 +01002916 : R.drawable.ic_corp_badge;
Tony Mak64b8d562017-12-28 17:44:02 +00002917 final GraphicBuffer thumbnail =
lumark588a3e82018-07-20 18:53:54 +08002918 getDisplayContent().mAppTransition
Tony Mak64b8d562017-12-28 17:44:02 +00002919 .createCrossProfileAppsThumbnail(thumbnailDrawableRes, frame);
2920 if (thumbnail == null) {
2921 return;
2922 }
2923 mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnail);
2924 final Animation animation =
lumark588a3e82018-07-20 18:53:54 +08002925 getDisplayContent().mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(
chaviw492139a2018-07-16 16:07:35 -07002926 win.getFrameLw());
Tony Mak64b8d562017-12-28 17:44:02 +00002927 mThumbnail.startAnimation(getPendingTransaction(), animation, new Point(frame.left,
2928 frame.top));
2929 }
2930
Jorim Jaggi988f6682017-11-17 17:46:43 +01002931 private Animation loadThumbnailAnimation(GraphicBuffer thumbnailHeader) {
2932 final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
2933
2934 // If this is a multi-window scenario, we use the windows frame as
2935 // destination of the thumbnail header animation. If this is a full screen
2936 // window scenario, we use the whole display as the target.
2937 WindowState win = findMainWindow();
2938 Rect appRect = win != null ? win.getContentFrameLw() :
2939 new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
chaviw9c81e632018-07-31 11:17:52 -07002940 final Rect insets = win != null ? win.getContentInsets() : null;
Jorim Jaggi988f6682017-11-17 17:46:43 +01002941 final Configuration displayConfig = mDisplayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08002942 return getDisplayContent().mAppTransition.createThumbnailAspectScaleAnimationLocked(
Jorim Jaggi988f6682017-11-17 17:46:43 +01002943 appRect, insets, thumbnailHeader, getTask().mTaskId, displayConfig.uiMode,
2944 displayConfig.orientation);
2945 }
2946
2947 private void clearThumbnail() {
2948 if (mThumbnail == null) {
2949 return;
2950 }
2951 mThumbnail.destroy();
2952 mThumbnail = null;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002953 }
2954
Jorim Jaggif84e2f62018-01-16 14:17:59 +01002955 void registerRemoteAnimations(RemoteAnimationDefinition definition) {
2956 mRemoteAnimationDefinition = definition;
2957 }
2958
2959 RemoteAnimationDefinition getRemoteAnimationDefinition() {
2960 return mRemoteAnimationDefinition;
2961 }
2962
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002963 @Override
2964 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
2965 super.dump(pw, prefix, dumpAll);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002966 if (appToken != null) {
Wale Ogunwale72919d22016-12-08 18:58:50 -08002967 pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002968 }
Winson Chung48b25652018-10-22 14:04:30 -07002969 pw.println(prefix + "component=" + mActivityComponent.flattenToShortString());
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08002970 pw.print(prefix); pw.print("task="); pw.println(getTask());
Wale Ogunwale51362492016-09-08 17:49:17 -07002971 pw.print(prefix); pw.print(" mFillsParent="); pw.print(mFillsParent);
2972 pw.print(" mOrientation="); pw.println(mOrientation);
Wale Ogunwale89973222017-04-23 18:39:45 -07002973 pw.println(prefix + "hiddenRequested=" + hiddenRequested + " mClientHidden=" + mClientHidden
2974 + ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "")
2975 + " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible);
Craig Mautner59431632012-04-04 11:56:44 -07002976 if (paused) {
2977 pw.print(prefix); pw.print("paused="); pw.println(paused);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002978 }
Wale Ogunwale9017ec02016-02-25 08:55:25 -08002979 if (mAppStopped) {
2980 pw.print(prefix); pw.print("mAppStopped="); pw.println(mAppStopped);
2981 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002982 if (mNumInterestingWindows != 0 || mNumDrawnWindows != 0
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002983 || allDrawn || mLastAllDrawn) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002984 pw.print(prefix); pw.print("mNumInterestingWindows=");
2985 pw.print(mNumInterestingWindows);
2986 pw.print(" mNumDrawnWindows="); pw.print(mNumDrawnWindows);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002987 pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
Craig Mautner6fbda632012-07-03 09:26:39 -07002988 pw.print(" allDrawn="); pw.print(allDrawn);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002989 pw.print(" lastAllDrawn="); pw.print(mLastAllDrawn);
Craig Mautner6fbda632012-07-03 09:26:39 -07002990 pw.println(")");
2991 }
2992 if (inPendingTransaction) {
2993 pw.print(prefix); pw.print("inPendingTransaction=");
2994 pw.println(inPendingTransaction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002995 }
Craig Mautner799bc1d2015-01-14 10:33:48 -08002996 if (startingData != null || removed || firstWindowDrawn || mIsExiting) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002997 pw.print(prefix); pw.print("startingData="); pw.print(startingData);
2998 pw.print(" removed="); pw.print(removed);
Craig Mautner3d7ca312015-01-08 10:56:00 -08002999 pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
Craig Mautner799bc1d2015-01-14 10:33:48 -08003000 pw.print(" mIsExiting="); pw.println(mIsExiting);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003001 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08003002 if (startingWindow != null || startingSurface != null
Wale Ogunwale6c459212017-05-17 08:56:03 -07003003 || startingDisplayed || startingMoved || mHiddenSetFromTransferredStartingWindow) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003004 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08003005 pw.print(" startingSurface="); pw.print(startingSurface);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003006 pw.print(" startingDisplayed="); pw.print(startingDisplayed);
Wale Ogunwale6c459212017-05-17 08:56:03 -07003007 pw.print(" startingMoved="); pw.print(startingMoved);
3008 pw.println(" mHiddenSetFromTransferredStartingWindow="
3009 + mHiddenSetFromTransferredStartingWindow);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003010 }
Jorim Jaggi0429f352015-12-22 16:29:16 +01003011 if (!mFrozenBounds.isEmpty()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08003012 pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
Jorim Jaggi26c8c422016-05-09 19:57:25 -07003013 pw.print(prefix); pw.print("mFrozenMergedConfig="); pw.println(mFrozenMergedConfig);
Chong Zhangd78ddb42016-03-02 17:01:14 -08003014 }
3015 if (mPendingRelaunchCount != 0) {
3016 pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount);
Jorim Jaggi0429f352015-12-22 16:29:16 +01003017 }
Riddle Hsub398da32019-01-21 21:48:16 +08003018 if (mSizeCompatScale != 1f || mSizeCompatBounds != null) {
3019 pw.println(prefix + "mSizeCompatScale=" + mSizeCompatScale + " mSizeCompatBounds="
3020 + mSizeCompatBounds);
3021 }
Wale Ogunwalee287e192017-04-21 09:30:12 -07003022 if (mRemovingFromDisplay) {
3023 pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay);
3024 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003025 }
3026
3027 @Override
3028 void setHidden(boolean hidden) {
3029 super.setHidden(hidden);
Winson Chunge55c0192017-08-24 14:50:48 -07003030
3031 if (hidden) {
3032 // Once the app window is hidden, reset the last saved PiP snap fraction
3033 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(this);
3034 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003035 scheduleAnimation();
3036 }
3037
3038 @Override
3039 void prepareSurfaces() {
3040 // isSelfAnimating also returns true when we are about to start a transition, so we need
3041 // to check super here.
3042 final boolean reallyAnimating = super.isSelfAnimating();
3043 final boolean show = !isHidden() || reallyAnimating;
Robert Carrd8e4fb72019-01-31 11:14:30 -08003044
3045 if (mSurfaceControl != null) {
3046 if (show && !mLastSurfaceShowing) {
3047 mPendingTransaction.show(mSurfaceControl);
3048 } else if (!show && mLastSurfaceShowing) {
3049 mPendingTransaction.hide(mSurfaceControl);
3050 }
Jorim Jaggi4d1835d2017-08-31 17:28:27 +02003051 }
Jorim Jaggi988f6682017-11-17 17:46:43 +01003052 if (mThumbnail != null) {
3053 mThumbnail.setShowing(mPendingTransaction, show);
3054 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003055 mLastSurfaceShowing = show;
3056 super.prepareSurfaces();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003057 }
3058
Jorim Jaggi77d0f36c2018-03-16 17:49:49 +01003059 /**
3060 * @return Whether our {@link #getSurfaceControl} is currently showing.
3061 */
3062 boolean isSurfaceShowing() {
3063 return mLastSurfaceShowing;
3064 }
3065
Jorim Jaggib0fc8172017-11-23 17:04:08 +00003066 boolean isFreezingScreen() {
3067 return mFreezingScreen;
3068 }
3069
3070 @Override
3071 boolean needsZBoost() {
3072 return mNeedsZBoost || super.needsZBoost();
3073 }
3074
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07003075 @CallSuper
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003076 @Override
Nataniel Borges023ecb52019-01-16 14:15:43 -08003077 public void writeToProto(ProtoOutputStream proto, long fieldId,
3078 @WindowTraceLogLevel int logLevel) {
3079 // Critical log level logs only visible elements to mitigate performance overheard
3080 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
3081 return;
3082 }
3083
Steven Timotiusaf03df62017-07-18 16:56:43 -07003084 final long token = proto.start(fieldId);
3085 writeNameToProto(proto, NAME);
Nataniel Borges023ecb52019-01-16 14:15:43 -08003086 super.writeToProto(proto, WINDOW_TOKEN, logLevel);
Vishnu Nair04ab4392018-01-10 11:00:06 -08003087 proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing);
3088 proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart());
3089 proto.write(IS_REALLY_ANIMATING, isReallyAnimating());
3090 if (mThumbnail != null){
3091 mThumbnail.writeToProto(proto, THUMBNAIL);
3092 }
3093 proto.write(FILLS_PARENT, mFillsParent);
3094 proto.write(APP_STOPPED, mAppStopped);
3095 proto.write(HIDDEN_REQUESTED, hiddenRequested);
3096 proto.write(CLIENT_HIDDEN, mClientHidden);
3097 proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient);
3098 proto.write(REPORTED_DRAWN, reportedDrawn);
3099 proto.write(REPORTED_VISIBLE, reportedVisible);
3100 proto.write(NUM_INTERESTING_WINDOWS, mNumInterestingWindows);
3101 proto.write(NUM_DRAWN_WINDOWS, mNumDrawnWindows);
3102 proto.write(ALL_DRAWN, allDrawn);
3103 proto.write(LAST_ALL_DRAWN, mLastAllDrawn);
3104 proto.write(REMOVED, removed);
Nataniel Borges023ecb52019-01-16 14:15:43 -08003105 if (startingWindow != null) {
Vishnu Nair04ab4392018-01-10 11:00:06 -08003106 startingWindow.writeIdentifierToProto(proto, STARTING_WINDOW);
3107 }
3108 proto.write(STARTING_DISPLAYED, startingDisplayed);
3109 proto.write(STARTING_MOVED, startingMoved);
3110 proto.write(HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW,
3111 mHiddenSetFromTransferredStartingWindow);
3112 for (Rect bounds : mFrozenBounds) {
3113 bounds.writeToProto(proto, FROZEN_BOUNDS);
3114 }
Steven Timotiusaf03df62017-07-18 16:56:43 -07003115 proto.end(token);
3116 }
3117
3118 void writeNameToProto(ProtoOutputStream proto, long fieldId) {
3119 if (appToken == null) {
3120 return;
3121 }
3122 try {
3123 proto.write(fieldId, appToken.getName());
3124 } catch (RemoteException e) {
3125 // This shouldn't happen, but in this case fall back to outputting nothing
3126 Slog.e(TAG, e.toString());
3127 }
3128 }
3129
3130 @Override
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003131 public String toString() {
3132 if (stringName == null) {
3133 StringBuilder sb = new StringBuilder();
3134 sb.append("AppWindowToken{");
3135 sb.append(Integer.toHexString(System.identityHashCode(this)));
3136 sb.append(" token="); sb.append(token); sb.append('}');
3137 stringName = sb.toString();
3138 }
Wale Ogunwaleba51ca22016-09-23 06:06:54 -07003139 return stringName + ((mIsExiting) ? " mIsExiting=" : "");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003140 }
Adrian Roos20e07892018-02-23 19:12:01 +01003141
3142 Rect getLetterboxInsets() {
3143 if (mLetterbox != null) {
3144 return mLetterbox.getInsets();
3145 } else {
3146 return new Rect();
3147 }
3148 }
Adrian Roos23df3a32018-03-15 15:41:13 +01003149
Riddle Hsu69de5fb2019-02-23 01:19:50 +08003150 /** Gets the inner bounds of letterbox. The bounds will be empty if there is no letterbox. */
3151 void getLetterboxInnerBounds(Rect outBounds) {
3152 if (mLetterbox != null) {
3153 outBounds.set(mLetterbox.getInnerFrame());
3154 } else {
3155 outBounds.setEmpty();
3156 }
3157 }
3158
Adrian Roos23df3a32018-03-15 15:41:13 +01003159 /**
Riddle Hsu69de5fb2019-02-23 01:19:50 +08003160 * @return {@code true} if there is a letterbox and any part of that letterbox overlaps with
Adrian Roos23df3a32018-03-15 15:41:13 +01003161 * the given {@code rect}.
3162 */
3163 boolean isLetterboxOverlappingWith(Rect rect) {
3164 return mLetterbox != null && mLetterbox.isOverlappingWith(rect);
3165 }
chaviw4ad54912018-05-30 11:05:44 -07003166
3167 /**
3168 * Sets if this AWT is in the process of closing or entering PIP.
3169 * {@link #mWillCloseOrEnterPip}}
3170 */
3171 void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
3172 mWillCloseOrEnterPip = willCloseOrEnterPip;
3173 }
3174
3175 /**
3176 * Returns whether this AWT is considered closing. Conditions are either
3177 * 1. Is this app animating and was requested to be hidden
3178 * 2. App is delayed closing since it might enter PIP.
3179 */
3180 boolean isClosingOrEnteringPip() {
3181 return (isAnimating() && hiddenRequested) || mWillCloseOrEnterPip;
3182 }
Jorim Jaggiaf0d6d22018-06-08 15:25:35 +02003183
3184 /**
3185 * @return Whether we are allowed to show non-starting windows at the moment. We disallow
3186 * showing windows during transitions in case we have windows that have wide-color-gamut
3187 * color mode set to avoid jank in the middle of the transition.
3188 */
3189 boolean canShowWindows() {
3190 return allDrawn && !(isReallyAnimating() && hasNonDefaultColorWindow());
3191 }
3192
3193 /**
3194 * @return true if we have a window that has a non-default color mode set; false otherwise.
3195 */
3196 private boolean hasNonDefaultColorWindow() {
3197 return forAllWindows(ws -> ws.mAttrs.getColorMode() != COLOR_MODE_DEFAULT,
3198 true /* topToBottom */);
3199 }
lumark588a3e82018-07-20 18:53:54 +08003200
3201 void removeFromPendingTransition() {
3202 if (isWaitingForTransitionStart() && mDisplayContent != null) {
3203 mDisplayContent.mOpeningApps.remove(this);
Evan Rosky25b56192019-02-06 16:10:56 -08003204 if (mDisplayContent.mChangingApps.remove(this)) {
3205 clearChangeLeash(getPendingTransaction(), true /* cancel */);
3206 }
lumark588a3e82018-07-20 18:53:54 +08003207 mDisplayContent.mClosingApps.remove(this);
3208 }
3209 }
chaviwdcf76ec2019-01-11 16:48:46 -08003210
3211 private void updateColorTransform() {
3212 if (mSurfaceControl != null && mLastAppSaturationInfo != null) {
3213 mPendingTransaction.setColorTransform(mSurfaceControl, mLastAppSaturationInfo.mMatrix,
3214 mLastAppSaturationInfo.mTranslation);
3215 mWmService.scheduleAnimationLocked();
3216 }
3217 }
3218
3219 private static class AppSaturationInfo {
3220 float[] mMatrix = new float[9];
3221 float[] mTranslation = new float[3];
3222
3223 void setSaturation(@Size(9) float[] matrix, @Size(3) float[] translation) {
3224 System.arraycopy(matrix, 0, mMatrix, 0, mMatrix.length);
3225 System.arraycopy(translation, 0, mTranslation, 0, mTranslation.length);
3226 }
3227 }
Jeff Browne9bdb312012-04-05 15:30:10 -07003228}