blob: 65b36a092228a0db007027a4d84a142c907a7f55 [file] [log] [blame]
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.wm;
18
Evan Rosky2289ba12018-11-19 18:28:18 -080019import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
Winson Chunge55c0192017-08-24 14:50:48 -070020import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
Jorim Jaggic6976f02018-04-18 16:31:07 +020021import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
Winson Chunge55c0192017-08-24 14:50:48 -070022import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
Jorim Jaggiaf0d6d22018-06-08 15:25:35 +020023import static android.content.pm.ActivityInfo.COLOR_MODE_DEFAULT;
Wale Ogunwale72919d22016-12-08 18:58:50 -080024import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
25import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -070026import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
Wale Ogunwale51362492016-09-08 17:49:17 -070027import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
Jorim Jaggif5f9e122017-10-24 18:21:09 +020028import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
Jorim Jaggife762342016-10-13 14:33:27 +020029import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
Jorim Jaggid635a4a2017-05-03 15:21:26 +020030import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080031import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
Jorim Jaggife762342016-10-13 14:33:27 +020032import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
Wale Ogunwaled1c37912016-08-16 03:19:39 -070033import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080034import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -070035import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080036import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
Evan Rosky2289ba12018-11-19 18:28:18 -080037import static android.view.WindowManager.TRANSIT_TASK_CHANGE_WINDOWING_MODE;
chaviw9c81e632018-07-31 11:17:52 -070038import static android.view.WindowManager.TRANSIT_UNSET;
Jorim Jaggic6976f02018-04-18 16:31:07 +020039import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
chaviw9c81e632018-07-31 11:17:52 -070040
Adrian Roose99bc052017-11-20 17:55:31 +010041import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
42import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070043import static com.android.server.wm.AppWindowTokenProto.ALL_DRAWN;
44import static com.android.server.wm.AppWindowTokenProto.APP_STOPPED;
45import static com.android.server.wm.AppWindowTokenProto.CLIENT_HIDDEN;
46import static com.android.server.wm.AppWindowTokenProto.DEFER_HIDING_CLIENT;
47import static com.android.server.wm.AppWindowTokenProto.FILLS_PARENT;
48import static com.android.server.wm.AppWindowTokenProto.FROZEN_BOUNDS;
49import static com.android.server.wm.AppWindowTokenProto.HIDDEN_REQUESTED;
50import static com.android.server.wm.AppWindowTokenProto.HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW;
51import static com.android.server.wm.AppWindowTokenProto.IS_REALLY_ANIMATING;
52import static com.android.server.wm.AppWindowTokenProto.IS_WAITING_FOR_TRANSITION_START;
53import static com.android.server.wm.AppWindowTokenProto.LAST_ALL_DRAWN;
54import static com.android.server.wm.AppWindowTokenProto.LAST_SURFACE_SHOWING;
55import static com.android.server.wm.AppWindowTokenProto.NAME;
56import static com.android.server.wm.AppWindowTokenProto.NUM_DRAWN_WINDOWS;
57import static com.android.server.wm.AppWindowTokenProto.NUM_INTERESTING_WINDOWS;
58import static com.android.server.wm.AppWindowTokenProto.REMOVED;
59import static com.android.server.wm.AppWindowTokenProto.REPORTED_DRAWN;
60import static com.android.server.wm.AppWindowTokenProto.REPORTED_VISIBLE;
61import static com.android.server.wm.AppWindowTokenProto.STARTING_DISPLAYED;
62import static com.android.server.wm.AppWindowTokenProto.STARTING_MOVED;
63import static com.android.server.wm.AppWindowTokenProto.STARTING_WINDOW;
64import static com.android.server.wm.AppWindowTokenProto.THUMBNAIL;
65import static com.android.server.wm.AppWindowTokenProto.WINDOW_TOKEN;
chaviw9c81e632018-07-31 11:17:52 -070066import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
67import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
68import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
69import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
70import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
71import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
72import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
73import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
74import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
75import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
76import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
77import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
78import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
79import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN;
80import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
81import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
82import static com.android.server.wm.WindowManagerService.logWithStack;
Vishnu Naira2977262018-07-26 13:31:26 -070083import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080084
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070085import android.annotation.CallSuper;
chaviwdcf76ec2019-01-11 16:48:46 -080086import android.annotation.Size;
Jorim Jaggid635a4a2017-05-03 15:21:26 +020087import android.app.Activity;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080088import android.app.ActivityManager;
Winson Chung48b25652018-10-22 14:04:30 -070089import android.content.ComponentName;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080090import android.content.res.CompatibilityInfo;
Jorim Jaggi26c8c422016-05-09 19:57:25 -070091import android.content.res.Configuration;
Jorim Jaggi988f6682017-11-17 17:46:43 +010092import android.graphics.GraphicBuffer;
Jorim Jaggif5f9e122017-10-24 18:21:09 +020093import android.graphics.Point;
Jorim Jaggi0429f352015-12-22 16:29:16 +010094import android.graphics.Rect;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -070095import android.os.Binder;
Tiger Huang51c5a1d2018-12-11 20:24:51 +080096import android.os.Build;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -080097import android.os.Debug;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -070098import android.os.IBinder;
Steven Timotiusaf03df62017-07-18 16:56:43 -070099import android.os.RemoteException;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800100import android.os.SystemClock;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200101import android.os.Trace;
Evan Rosky2289ba12018-11-19 18:28:18 -0800102import android.util.ArraySet;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800103import android.util.Slog;
Steven Timotiusaf03df62017-07-18 16:56:43 -0700104import android.util.proto.ProtoOutputStream;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200105import android.view.DisplayInfo;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800106import android.view.IApplicationToken;
Robert Carr788f5742018-07-30 17:46:45 -0700107import android.view.InputApplicationHandle;
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;
120import com.android.server.display.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 */
146 private static final int Z_BOOST_BASE = 800570000;
147
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;
Craig Mautner4c5eb222013-11-18 12:59:05 -0800155 boolean layoutConfigChanges;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800156 boolean mShowForAllUsers;
157 int mTargetSdk;
Craig Mautnera2c77052012-03-26 12:14:43 -0700158
Bryce Lee6d410262017-02-28 15:30:17 -0800159 // Flag set while reparenting to prevent actions normally triggered by an individual parent
160 // change.
161 private boolean mReparenting;
162
Wale Ogunwalee287e192017-04-21 09:30:12 -0700163 // True if we are current in the process of removing this app token from the display
164 private boolean mRemovingFromDisplay = false;
165
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800166 // The input dispatching timeout for this application token in nanoseconds.
Wale Ogunwale72919d22016-12-08 18:58:50 -0800167 long mInputDispatchingTimeoutNanos;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800168
169 // These are used for determining when all windows associated with
170 // an activity have been drawn, so they can be made visible together
171 // at the same time.
Craig Mautner764983d2012-03-22 11:37:36 -0700172 // initialize so that it doesn't match mTransactionSequence which is an int.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700173 private long mLastTransactionSequence = Long.MIN_VALUE;
174 private int mNumInterestingWindows;
175 private int mNumDrawnWindows;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800176 boolean inPendingTransaction;
177 boolean allDrawn;
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000178 private boolean mLastAllDrawn;
179
Craig Mautner7636dfb2012-11-16 15:24:11 -0800180 // Set to true when this app creates a surface while in the middle of an animation. In that
181 // case do not clear allDrawn until the animation completes.
182 boolean deferClearAllDrawn;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800183
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800184 // Is this window's surface needed? This is almost like hidden, except
185 // it will sometimes be true a little earlier: when the token has
186 // been shown, but is still waiting for its app transition to execute
187 // before making its windows shown.
188 boolean hiddenRequested;
189
190 // Have we told the window clients to hide themselves?
Wale Ogunwale89973222017-04-23 18:39:45 -0700191 private boolean mClientHidden;
192
193 // If true we will defer setting mClientHidden to true and reporting to the client that it is
194 // hidden.
195 boolean mDeferHidingClient;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800196
197 // Last visibility state we reported to the app token.
198 boolean reportedVisible;
199
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700200 // Last drawn state we reported to the app token.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700201 private boolean reportedDrawn;
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700202
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800203 // Set to true when the token has been removed from the window mgr.
204 boolean removed;
205
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800206 // Information about an application starting window if displayed.
207 StartingData startingData;
208 WindowState startingWindow;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800209 StartingSurface startingSurface;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800210 boolean startingDisplayed;
211 boolean startingMoved;
Jorim Jaggi60f9c972018-02-01 19:21:07 +0100212
Wale Ogunwale6c459212017-05-17 08:56:03 -0700213 // True if the hidden state of this token was forced to false due to a transferred starting
214 // window.
215 private boolean mHiddenSetFromTransferredStartingWindow;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800216 boolean firstWindowDrawn;
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700217 private final WindowState.UpdateReportedVisibilityResults mReportedVisibilityResults =
218 new WindowState.UpdateReportedVisibilityResults();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800219
220 // Input application handle used by the input dispatcher.
Jeff Brown9302c872011-07-13 22:51:29 -0700221 final InputApplicationHandle mInputApplicationHandle;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800222
Wale Ogunwale571771c2016-08-26 13:18:50 -0700223 // TODO: Have a WindowContainer state for tracking exiting/deferred removal.
Craig Mautner799bc1d2015-01-14 10:33:48 -0800224 boolean mIsExiting;
Craig Mautner9ef471f2014-02-07 13:11:47 -0800225
Craig Mautnerbb742462014-07-07 15:28:55 -0700226 boolean mLaunchTaskBehind;
Craig Mautner8746a472014-07-24 15:12:54 -0700227 boolean mEnteringAnimation;
Craig Mautnerbb742462014-07-07 15:28:55 -0700228
Wale Ogunwale72919d22016-12-08 18:58:50 -0800229 private boolean mAlwaysFocusable;
Wale Ogunwale6cae7652015-12-26 07:36:26 -0800230
Robert Carre12aece2016-02-02 22:43:27 -0800231 boolean mAppStopped;
Robert Carrfd10cd12016-06-29 16:41:50 -0700232 int mRotationAnimationHint;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700233 private int mPendingRelaunchCount;
Robert Carre12aece2016-02-02 22:43:27 -0800234
Jorim Jaggife762342016-10-13 14:33:27 +0200235 private boolean mLastContainsShowWhenLockedWindow;
236 private boolean mLastContainsDismissKeyguardWindow;
237
Jorim Jaggi0429f352015-12-22 16:29:16 +0100238 ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
Jorim Jaggi26c8c422016-05-09 19:57:25 -0700239 ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
Jorim Jaggi0429f352015-12-22 16:29:16 +0100240
Wale Ogunwale6c459212017-05-17 08:56:03 -0700241 private boolean mDisablePreviewScreenshots;
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +0100242
Wale Ogunwale034a8ec2017-09-02 17:14:40 -0700243 private Task mLastParent;
Robert Carred3e83b2017-04-21 13:26:55 -0700244
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800245 // TODO: Remove after unification
246 ActivityRecord mActivityRecord;
247
chaviwd3bf08d2017-08-01 17:24:59 -0700248 /**
249 * See {@link #canTurnScreenOn()}
250 */
251 private boolean mCanTurnScreenOn = true;
252
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200253 /**
254 * If we are running an animation, this determines the transition type. Must be one of
255 * AppTransition.TRANSIT_* constants.
256 */
257 private int mTransit;
258
259 /**
260 * If we are running an animation, this determines the flags during this animation. Must be a
261 * bitwise combination of AppTransition.TRANSIT_FLAG_* constants.
262 */
263 private int mTransitFlags;
264
265 /** Whether our surface was set to be showing in the last call to {@link #prepareSurfaces} */
Jorim Jaggifd1891462017-12-29 15:41:36 +0100266 private boolean mLastSurfaceShowing = true;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200267
Evan Rosky2289ba12018-11-19 18:28:18 -0800268 /**
269 * This gets used during some open/close transitions as well as during a change transition
270 * where it represents the starting-state snapshot.
271 */
Jorim Jaggi988f6682017-11-17 17:46:43 +0100272 private AppWindowThumbnail mThumbnail;
Evan Rosky2289ba12018-11-19 18:28:18 -0800273 private final Rect mTransitStartRect = new Rect();
274
275 /**
276 * This leash is used to "freeze" the app surface in place after the state change, but before
277 * the animation is ready to start.
278 */
279 private SurfaceControl mTransitChangeLeash = null;
Jorim Jaggi988f6682017-11-17 17:46:43 +0100280
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000281 /** Have we been asked to have this token keep the screen frozen? */
282 private boolean mFreezingScreen;
283
284 /** Whether this token should be boosted at the top of all app window tokens. */
285 private boolean mNeedsZBoost;
Adrian Roos4d18a2e2017-12-19 19:08:05 +0100286 private Letterbox mLetterbox;
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000287
chaviw23ee71c2017-12-18 11:29:41 -0800288 private final Point mTmpPoint = new Point();
chaviw23012112017-12-20 15:29:04 -0800289 private final Rect mTmpRect = new Rect();
Evan Rosky2289ba12018-11-19 18:28:18 -0800290 private final Rect mTmpPrevBounds = new Rect();
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100291 private RemoteAnimationDefinition mRemoteAnimationDefinition;
Jorim Jaggi6de61012018-03-19 14:53:23 +0100292 private AnimatingAppWindowTokenRegistry mAnimatingAppWindowTokenRegistry;
chaviw23ee71c2017-12-18 11:29:41 -0800293
chaviw4ad54912018-05-30 11:05:44 -0700294 /**
295 * A flag to determine if this AWT is in the process of closing or entering PIP. This is needed
296 * to help AWT know that the app is in the process of closing but hasn't yet started closing on
297 * the WM side.
298 */
299 private boolean mWillCloseOrEnterPip;
300
Vishnu Naira2977262018-07-26 13:31:26 -0700301 /** Layer used to constrain the animation to a token's stack bounds. */
302 SurfaceControl mAnimationBoundsLayer;
303
304 /** Whether this token needs to create mAnimationBoundsLayer for cropping animations. */
305 boolean mNeedsAnimationBoundsLayer;
306
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800307 private static final int STARTING_WINDOW_TYPE_NONE = 0;
308 private static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
309 private static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
310
chaviwdcf76ec2019-01-11 16:48:46 -0800311 private AppSaturationInfo mLastAppSaturationInfo;
312
313 private final ColorDisplayService.ColorTransformController mColorTransformController =
314 (matrix, translation) -> mWmService.mH.post(() -> {
315 synchronized (mWmService.mGlobalLock) {
316 if (mLastAppSaturationInfo == null) {
317 mLastAppSaturationInfo = new AppSaturationInfo();
318 }
319
320 mLastAppSaturationInfo.setSaturation(matrix, translation);
321 updateColorTransform();
322 }
323 });
324
Winson Chung48b25652018-10-22 14:04:30 -0700325 AppWindowToken(WindowManagerService service, IApplicationToken token,
326 ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
327 long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers,
328 int targetSdk, int orientation, int rotationAnimationHint, int configChanges,
329 boolean launchTaskBehind, boolean alwaysFocusable,
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800330 ActivityRecord activityRecord) {
Winson Chung48b25652018-10-22 14:04:30 -0700331 this(service, token, activityComponent, voiceInteraction, dc, fullscreen);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800332 // TODO: remove after unification
333 mActivityRecord = activityRecord;
334 mActivityRecord.registerConfigurationChangeListener(this);
Wale Ogunwale72919d22016-12-08 18:58:50 -0800335 mInputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800336 mShowForAllUsers = showForAllUsers;
337 mTargetSdk = targetSdk;
338 mOrientation = orientation;
339 layoutConfigChanges = (configChanges & (CONFIG_SCREEN_SIZE | CONFIG_ORIENTATION)) != 0;
340 mLaunchTaskBehind = launchTaskBehind;
341 mAlwaysFocusable = alwaysFocusable;
342 mRotationAnimationHint = rotationAnimationHint;
343
344 // Application tokens start out hidden.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200345 setHidden(true);
Wale Ogunwale72919d22016-12-08 18:58:50 -0800346 hiddenRequested = true;
chaviwdcf76ec2019-01-11 16:48:46 -0800347
348 ColorDisplayService.ColorDisplayServiceInternal cds = LocalServices.getService(
349 ColorDisplayService.ColorDisplayServiceInternal.class);
350 cds.attachColorTransformController(activityRecord.packageName, activityRecord.mUserId,
351 new WeakReference<>(mColorTransformController));
Wale Ogunwale72919d22016-12-08 18:58:50 -0800352 }
353
Winson Chung48b25652018-10-22 14:04:30 -0700354 AppWindowToken(WindowManagerService service, IApplicationToken token,
355 ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
356 boolean fillsParent) {
Wale Ogunwale5cd907d2017-01-26 14:14:08 -0800357 super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true, dc,
358 false /* ownerCanManageAppTokens */);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700359 appToken = token;
Winson Chung48b25652018-10-22 14:04:30 -0700360 mActivityComponent = activityComponent;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800361 mVoiceInteraction = voiceInteraction;
Wale Ogunwale17f175c2017-02-07 16:54:10 -0800362 mFillsParent = fillsParent;
Robert Carr0bcbe642018-10-11 19:07:43 -0700363 mInputApplicationHandle = new InputApplicationHandle(appToken.asBinder());
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800364 }
365
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800366 void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
367 firstWindowDrawn = true;
368
369 // We now have a good window to show, remove dead placeholders
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700370 removeDeadWindows();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800371
Jorim Jaggi02886a82016-12-06 09:10:06 -0800372 if (startingWindow != null) {
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800373 if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Slog.v(TAG, "Finish starting "
374 + win.mToken + ": first real window is shown, no animation");
375 // If this initial window is animating, stop it -- we will do an animation to reveal
376 // it from behind the starting window, so there is no need for it to also be doing its
377 // own stuff.
Jorim Jaggia5e10572017-11-15 14:36:26 +0100378 win.cancelAnimation();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800379 removeStartingWindow();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800380 }
381 updateReportedVisibilityLocked();
382 }
383
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800384 void updateReportedVisibilityLocked() {
385 if (appToken == null) {
386 return;
387 }
388
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700389 if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700390 final int count = mChildren.size();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800391
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700392 mReportedVisibilityResults.reset();
393
394 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700395 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700396 win.updateReportedVisibility(mReportedVisibilityResults);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800397 }
398
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700399 int numInteresting = mReportedVisibilityResults.numInteresting;
400 int numVisible = mReportedVisibilityResults.numVisible;
401 int numDrawn = mReportedVisibilityResults.numDrawn;
402 boolean nowGone = mReportedVisibilityResults.nowGone;
403
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700404 boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200405 boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting && !isHidden();
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700406 if (!nowGone) {
407 // If the app is not yet gone, then it can only become visible/drawn.
408 if (!nowDrawn) {
409 nowDrawn = reportedDrawn;
410 }
411 if (!nowVisible) {
412 nowVisible = reportedVisible;
413 }
414 }
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800415 if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800416 + numInteresting + " visible=" + numVisible);
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700417 if (nowDrawn != reportedDrawn) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800418 if (mActivityRecord != null) {
419 mActivityRecord.onWindowsDrawn(nowDrawn, SystemClock.uptimeMillis());
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700420 }
421 reportedDrawn = nowDrawn;
422 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800423 if (nowVisible != reportedVisible) {
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700424 if (DEBUG_VISIBILITY) Slog.v(TAG,
425 "Visibility changed in " + this + ": vis=" + nowVisible);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800426 reportedVisible = nowVisible;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800427 if (mActivityRecord != null) {
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800428 if (nowVisible) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800429 onWindowsVisible();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800430 } else {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800431 onWindowsGone();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800432 }
433 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800434 }
435 }
436
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800437 private void onWindowsGone() {
438 if (mActivityRecord == null) {
439 return;
440 }
441 if (DEBUG_VISIBILITY) {
442 Slog.v(TAG_WM, "Reporting gone in " + mActivityRecord.appToken);
443 }
444 mActivityRecord.onWindowsGone();
445 }
446
447 private void onWindowsVisible() {
448 if (mActivityRecord == null) {
449 return;
450 }
451 if (DEBUG_VISIBILITY) {
452 Slog.v(TAG_WM, "Reporting visible in " + mActivityRecord.appToken);
453 }
454 mActivityRecord.onWindowsVisible();
455 }
456
Wale Ogunwale89973222017-04-23 18:39:45 -0700457 boolean isClientHidden() {
458 return mClientHidden;
459 }
460
461 void setClientHidden(boolean hideClient) {
462 if (mClientHidden == hideClient || (hideClient && mDeferHidingClient)) {
463 return;
464 }
Jorim Jaggi067b5bf2018-02-23 17:42:39 +0100465 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "setClientHidden: " + this
466 + " clientHidden=" + hideClient + " Callers=" + Debug.getCallers(5));
Wale Ogunwale89973222017-04-23 18:39:45 -0700467 mClientHidden = hideClient;
468 sendAppVisibilityToClients();
469 }
470
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800471 void setVisibility(boolean visible, boolean deferHidingClient) {
472 final AppTransition appTransition = getDisplayContent().mAppTransition;
473
474 // Don't set visibility to false if we were already not visible. This prevents WM from
475 // adding the app to the closing app list which doesn't make sense for something that is
476 // already not visible. However, set visibility to true even if we are already visible.
477 // This makes sure the app is added to the opening apps list so that the right
478 // transition can be selected.
479 // TODO: Probably a good idea to separate the concept of opening/closing apps from the
480 // concept of setting visibility...
481 if (!visible && hiddenRequested) {
482
483 if (!deferHidingClient && mDeferHidingClient) {
484 // We previously deferred telling the client to hide itself when visibility was
485 // initially set to false. Now we would like it to hide, so go ahead and set it.
486 mDeferHidingClient = deferHidingClient;
487 setClientHidden(true);
488 }
489 return;
490 }
491
492 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) {
493 Slog.v(TAG_WM, "setAppVisibility("
494 + appToken + ", visible=" + visible + "): " + appTransition
495 + " hidden=" + isHidden() + " hiddenRequested="
496 + hiddenRequested + " Callers=" + Debug.getCallers(6));
497 }
498
499 final DisplayContent displayContent = getDisplayContent();
500 displayContent.mOpeningApps.remove(this);
501 displayContent.mClosingApps.remove(this);
502 waitingToShow = false;
503 hiddenRequested = !visible;
504 mDeferHidingClient = deferHidingClient;
505
506 if (!visible) {
507 // If the app is dead while it was visible, we kept its dead window on screen.
508 // Now that the app is going invisible, we can remove it. It will be restarted
509 // if made visible again.
510 removeDeadWindows();
511 } else {
512 if (!appTransition.isTransitionSet()
513 && appTransition.isReady()) {
514 // Add the app mOpeningApps if transition is unset but ready. This means
515 // we're doing a screen freeze, and the unfreeze will wait for all opening
516 // apps to be ready.
517 displayContent.mOpeningApps.add(this);
518 }
519 startingMoved = false;
520 // If the token is currently hidden (should be the common case), or has been
521 // stopped, then we need to set up to wait for its windows to be ready.
522 if (isHidden() || mAppStopped) {
523 clearAllDrawn();
524
525 // If the app was already visible, don't reset the waitingToShow state.
526 if (isHidden()) {
527 waitingToShow = true;
528 }
529 }
530
531 // In the case where we are making an app visible but holding off for a transition,
532 // we still need to tell the client to make its windows visible so they get drawn.
533 // Otherwise, we will wait on performing the transition until all windows have been
534 // drawn, they never will be, and we are sad.
535 setClientHidden(false);
536
537 requestUpdateWallpaperIfNeeded();
538
539 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "No longer Stopped: " + this);
540 mAppStopped = false;
541
542 transferStartingWindowFromHiddenAboveTokenIfNeeded();
543 }
544
545 // If we are preparing an app transition, then delay changing
546 // the visibility of this token until we execute that transition.
547 if (okToAnimate() && appTransition.isTransitionSet()) {
548 inPendingTransaction = true;
549 if (visible) {
550 displayContent.mOpeningApps.add(this);
551 mEnteringAnimation = true;
552 } else {
553 displayContent.mClosingApps.add(this);
554 mEnteringAnimation = false;
555 }
556 if (appTransition.getAppTransition()
557 == WindowManager.TRANSIT_TASK_OPEN_BEHIND) {
558 // We're launchingBehind, add the launching activity to mOpeningApps.
559 final WindowState win = getDisplayContent().findFocusedWindow();
560 if (win != null) {
561 final AppWindowToken focusedToken = win.mAppToken;
562 if (focusedToken != null) {
563 if (DEBUG_APP_TRANSITIONS) {
564 Slog.d(TAG_WM, "TRANSIT_TASK_OPEN_BEHIND, "
565 + " adding " + focusedToken + " to mOpeningApps");
566 }
567 // Force animation to be loaded.
568 focusedToken.setHidden(true);
569 displayContent.mOpeningApps.add(focusedToken);
570 }
571 }
572 }
573 return;
574 }
575
576 commitVisibility(null, visible, TRANSIT_UNSET, true, mVoiceInteraction);
577 updateReportedVisibilityLocked();
578 }
579
580 boolean commitVisibility(WindowManager.LayoutParams lp,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700581 boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
582
583 boolean delayed = false;
584 inPendingTransaction = false;
Wale Ogunwale9e4721f2017-05-23 19:37:30 -0700585 // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually
586 // been set by the app now.
587 mHiddenSetFromTransferredStartingWindow = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700588
589 // Allow for state changes and animation to be applied if:
590 // * token is transitioning visibility state
591 // * or the token was marked as hidden and is exiting before we had a chance to play the
592 // transition animation
593 // * or this is an opening app and windows are being replaced.
594 boolean visibilityChanged = false;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200595 if (isHidden() == visible || (isHidden() && mIsExiting) || (visible && waitingForReplacement())) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800596 final AccessibilityController accessibilityController =
597 mWmService.mAccessibilityController;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700598 boolean changed = false;
599 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM,
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200600 "Changing app " + this + " hidden=" + isHidden() + " performLayout=" + performLayout);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700601
602 boolean runningAppAnimation = false;
603
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100604 if (transit != WindowManager.TRANSIT_UNSET) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200605 if (applyAnimationLocked(lp, transit, visible, isVoiceInteraction)) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700606 delayed = runningAppAnimation = true;
607 }
608 final WindowState window = findMainWindow();
Rhed Jao02655dc2018-10-30 20:44:52 +0800609 if (window != null && accessibilityController != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700610 accessibilityController.onAppWindowTransitionLocked(window, transit);
611 }
612 changed = true;
613 }
614
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700615 final int windowsCount = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700616 for (int i = 0; i < windowsCount; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700617 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700618 changed |= win.onAppVisibilityChanged(visible, runningAppAnimation);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700619 }
620
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200621 setHidden(!visible);
622 hiddenRequested = !visible;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700623 visibilityChanged = true;
624 if (!visible) {
625 stopFreezingScreen(true, true);
626 } else {
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700627 // If we are being set visible, and the starting window is not yet displayed,
628 // then make sure it doesn't get displayed.
629 if (startingWindow != null && !startingWindow.isDrawnLw()) {
630 startingWindow.mPolicyVisibility = false;
631 startingWindow.mPolicyVisibilityAfterAnim = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700632 }
Jorim Jaggi38d44ec2017-06-14 16:04:59 -0700633
634 // We are becoming visible, so better freeze the screen with the windows that are
635 // getting visible so we also wait for them.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800636 forAllWindows(mWmService::makeWindowFreezingScreenIfNeededLocked, true);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700637 }
638
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800639 if (DEBUG_APP_TRANSITIONS) {
640 Slog.v(TAG_WM, "commitVisibility: " + this
641 + ": hidden=" + isHidden() + " hiddenRequested=" + hiddenRequested);
642 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700643
644 if (changed) {
Arthur Hung95b38a92018-07-20 18:56:12 +0800645 getDisplayContent().getInputMonitor().setUpdateInputWindowsNeededLw();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700646 if (performLayout) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800647 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700648 false /*updateInputWindows*/);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800649 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700650 }
Arthur Hung95b38a92018-07-20 18:56:12 +0800651 getDisplayContent().getInputMonitor().updateInputWindowsLw(false /*force*/);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700652 }
653 }
654
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200655 if (isReallyAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700656 delayed = true;
Jorim Jaggiab9fcb22018-03-15 23:46:12 +0100657 } else {
658
659 // We aren't animating anything, but exiting windows rely on the animation finished
660 // callback being called in case the AppWindowToken was pretending to be animating,
661 // which we might have done because we were in closing/opening apps list.
662 onAnimationFinished();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700663 }
664
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700665 for (int i = mChildren.size() - 1; i >= 0 && !delayed; i--) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100666 if ((mChildren.get(i)).isSelfOrChildAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700667 delayed = true;
668 }
669 }
670
671 if (visibilityChanged) {
672 if (visible && !delayed) {
673 // The token was made immediately visible, there will be no entrance animation.
674 // We need to inform the client the enter animation was finished.
675 mEnteringAnimation = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800676 mWmService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(
677 token);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700678 }
Robert Carr61b81112017-07-17 18:08:15 -0700679
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800680 // If we're becoming visible, immediately change client visibility as well. there seem
681 // to be some edge cases where we change our visibility but client visibility never gets
682 // updated.
Jorim Jaggi110839b2018-01-22 12:49:04 +0100683 // If we're becoming invisible, update the client visibility if we are not running an
684 // animation. Otherwise, we'll update client visibility in onAnimationFinished.
Jorim Jaggi3cad57f2018-02-20 18:32:01 +0100685 if (visible || !isReallyAnimating()) {
Jorim Jaggi110839b2018-01-22 12:49:04 +0100686 setClientHidden(!visible);
Jorim Jaggi4876b4a2018-01-11 15:43:49 +0100687 }
688
lumark588a3e82018-07-20 18:53:54 +0800689 if (!getDisplayContent().mClosingApps.contains(this)
690 && !getDisplayContent().mOpeningApps.contains(this)) {
chaviwa953fcf2018-03-01 12:00:39 -0800691 // The token is not closing nor opening, so even if there is an animation set, that
692 // doesn't mean that it goes through the normal app transition cycle so we have
693 // to inform the docked controller about visibility change.
694 // TODO(multi-display): notify docked divider on all displays where visibility was
695 // affected.
lumark588a3e82018-07-20 18:53:54 +0800696 getDisplayContent().getDockedDividerController().notifyAppVisibilityChanged();
chaviwa953fcf2018-03-01 12:00:39 -0800697
698 // Take the screenshot before possibly hiding the WSA, otherwise the screenshot
699 // will not be taken.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800700 mWmService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible);
chaviwa953fcf2018-03-01 12:00:39 -0800701 }
702
Robert Carre7cc44d2017-03-20 19:04:30 -0700703 // If we are hidden but there is no delay needed we immediately
704 // apply the Surface transaction so that the ActivityManager
Robert Carr61b81112017-07-17 18:08:15 -0700705 // can have some guarantee on the Surface state following
706 // setting the visibility. This captures cases like dismissing
707 // the docked or pinned stack where there is no app transition.
708 //
709 // In the case of a "Null" animation, there will be
710 // no animation but there will still be a transition set.
711 // We still need to delay hiding the surface such that it
712 // can be synchronized with showing the next surface in the transition.
lumark588a3e82018-07-20 18:53:54 +0800713 if (isHidden() && !delayed && !getDisplayContent().mAppTransition.isTransitionSet()) {
Robert Carr6914f082017-03-20 19:04:30 -0700714 SurfaceControl.openTransaction();
715 for (int i = mChildren.size() - 1; i >= 0; i--) {
716 mChildren.get(i).mWinAnimator.hide("immediately hidden");
717 }
718 SurfaceControl.closeTransaction();
719 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700720 }
721
722 return delayed;
723 }
724
Jorim Jaggi87fdbcb2017-08-17 13:41:11 +0200725 /**
726 * @return The to top most child window for which {@link LayoutParams#isFullscreen()} returns
727 * true.
728 */
729 WindowState getTopFullscreenWindow() {
730 for (int i = mChildren.size() - 1; i >= 0; i--) {
731 final WindowState win = mChildren.get(i);
732 if (win != null && win.mAttrs.isFullscreen()) {
733 return win;
734 }
735 }
736 return null;
737 }
738
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800739 WindowState findMainWindow() {
Matthew Ng53e66b22018-01-12 17:13:13 -0800740 return findMainWindow(true);
741 }
742
743 /**
744 * Finds the main window that either has type base application or application starting if
745 * requested.
746 *
747 * @param includeStartingApp Allow to search application-starting windows to also be returned.
748 * @return The main window of type base application or application starting if requested.
749 */
750 WindowState findMainWindow(boolean includeStartingApp) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700751 WindowState candidate = null;
Matthew Ng53e66b22018-01-12 17:13:13 -0800752 for (int j = mChildren.size() - 1; j >= 0; --j) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700753 final WindowState win = mChildren.get(j);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700754 final int type = win.mAttrs.type;
755 // No need to loop through child window as base application and starting types can't be
756 // child windows.
Matthew Ng53e66b22018-01-12 17:13:13 -0800757 if (type == TYPE_BASE_APPLICATION
758 || (includeStartingApp && type == TYPE_APPLICATION_STARTING)) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700759 // In cases where there are multiple windows, we prefer the non-exiting window. This
Sungsoo Lim0d3d1f82015-12-02 14:47:59 +0900760 // happens for example when replacing windows during an activity relaunch. When
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700761 // constructing the animation, we want the new window, not the exiting one.
Wale Ogunwalec48a3542016-02-19 15:18:45 -0800762 if (win.mAnimatingExit) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700763 candidate = win;
764 } else {
765 return win;
766 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800767 }
768 }
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700769 return candidate;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800770 }
771
Wale Ogunwale6cae7652015-12-26 07:36:26 -0800772 boolean windowsAreFocusable() {
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800773 if (mTargetSdk < Build.VERSION_CODES.Q) {
774 final int pid = mActivityRecord != null
775 ? (mActivityRecord.app != null ? mActivityRecord.app.getPid() : 0) : 0;
776 final AppWindowToken topFocusedAppOfMyProcess =
777 mWmService.mRoot.mTopFocusedAppByProcess.get(pid);
778 if (topFocusedAppOfMyProcess != null && topFocusedAppOfMyProcess != this) {
779 // For the apps below Q, there can be only one app which has the focused window per
780 // process, because legacy apps may not be ready for a multi-focus system.
781 return false;
782 }
783 }
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700784 return getWindowConfiguration().canReceiveKeys() || mAlwaysFocusable;
Wale Ogunwaled045c822015-12-02 09:14:28 -0800785 }
786
Wale Ogunwale571771c2016-08-26 13:18:50 -0700787 @Override
Wale Ogunwale44f21802016-09-02 12:49:48 -0700788 boolean isVisible() {
Wale Ogunwalee471be62016-10-03 07:53:55 -0700789 // If the app token isn't hidden then it is considered visible and there is no need to check
790 // its children windows to see if they are visible.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200791 return !isHidden();
Wale Ogunwale44f21802016-09-02 12:49:48 -0700792 }
793
794 @Override
Wale Ogunwalee287e192017-04-21 09:30:12 -0700795 void removeImmediately() {
796 onRemovedFromDisplay();
Yunfan Chen3a77f282018-12-12 15:47:52 -0800797 if (mActivityRecord != null) {
798 mActivityRecord.unregisterConfigurationChangeListener(this);
799 }
Wale Ogunwalee287e192017-04-21 09:30:12 -0700800 super.removeImmediately();
801 }
802
803 @Override
Wale Ogunwale571771c2016-08-26 13:18:50 -0700804 void removeIfPossible() {
Craig Mautnere3119b72015-01-20 15:02:36 -0800805 mIsExiting = false;
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800806 removeAllWindowsIfPossible();
Bryce Lee6d410262017-02-28 15:30:17 -0800807 removeImmediately();
Craig Mautnere3119b72015-01-20 15:02:36 -0800808 }
809
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700810 @Override
811 boolean checkCompleteDeferredRemoval() {
812 if (mIsExiting) {
813 removeIfPossible();
814 }
815 return super.checkCompleteDeferredRemoval();
816 }
817
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700818 void onRemovedFromDisplay() {
Wale Ogunwalee287e192017-04-21 09:30:12 -0700819 if (mRemovingFromDisplay) {
820 return;
821 }
822 mRemovingFromDisplay = true;
823
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700824 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app token: " + this);
825
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800826 boolean delayed = commitVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700827
lumark588a3e82018-07-20 18:53:54 +0800828 getDisplayContent().mOpeningApps.remove(this);
Evan Rosky2289ba12018-11-19 18:28:18 -0800829 getDisplayContent().mChangingApps.remove(this);
lumark588a3e82018-07-20 18:53:54 +0800830 getDisplayContent().mUnknownAppVisibilityController.appRemovedOrHidden(this);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800831 mWmService.mTaskSnapshotController.onAppRemoved(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700832 waitingToShow = false;
lumark588a3e82018-07-20 18:53:54 +0800833 if (getDisplayContent().mClosingApps.contains(this)) {
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700834 delayed = true;
lumark588a3e82018-07-20 18:53:54 +0800835 } else if (getDisplayContent().mAppTransition.isTransitionSet()) {
836 getDisplayContent().mClosingApps.add(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700837 delayed = true;
838 }
839
840 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app " + this + " delayed=" + delayed
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200841 + " animation=" + getAnimation() + " animating=" + isSelfAnimating());
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700842
843 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: "
844 + this + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
845
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800846 if (startingData != null) {
847 removeStartingWindow();
Jorim Jaggi19be6052017-08-03 18:33:43 +0200848 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800849
Winson Chung87e5d552017-04-05 11:49:38 -0700850 // If this window was animating, then we need to ensure that the app transition notifies
lumark588a3e82018-07-20 18:53:54 +0800851 // that animations have completed in DisplayContent.handleAnimatingStoppedAndTransition(),
852 // so add to that list now
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200853 if (isSelfAnimating()) {
lumark588a3e82018-07-20 18:53:54 +0800854 getDisplayContent().mNoAnimationNotifyOnTransitionFinished.add(token);
Winson Chung87e5d552017-04-05 11:49:38 -0700855 }
856
Wale Ogunwalee287e192017-04-21 09:30:12 -0700857 final TaskStack stack = getStack();
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700858 if (delayed && !isEmpty()) {
859 // set the token aside because it has an active animation to be finished
860 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM,
861 "removeAppToken make exiting: " + this);
Wale Ogunwalee287e192017-04-21 09:30:12 -0700862 if (stack != null) {
863 stack.mExitingAppTokens.add(this);
864 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700865 mIsExiting = true;
866 } else {
867 // Make sure there is no animation running on this token, so any windows associated
868 // with it will be removed as soon as their animations are complete
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200869 cancelAnimation();
Wale Ogunwale3106ae012017-05-16 08:56:37 -0700870 if (stack != null) {
871 stack.mExitingAppTokens.remove(this);
872 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700873 removeIfPossible();
874 }
875
876 removed = true;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700877 stopFreezingScreen(true, true);
Bryce Lee6d410262017-02-28 15:30:17 -0800878
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800879 final DisplayContent dc = getDisplayContent();
880 if (dc.mFocusedApp == this) {
881 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + this
882 + " displayId=" + dc.getDisplayId());
883 dc.setFocusedApp(null);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800884 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700885 }
886
887 if (!delayed) {
888 updateReportedVisibilityLocked();
889 }
Wale Ogunwalee287e192017-04-21 09:30:12 -0700890
891 mRemovingFromDisplay = false;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700892 }
893
Chong Zhange05bcb12016-07-26 17:47:29 -0700894 void clearAnimatingFlags() {
Chong Zhangb0d26702016-08-12 16:03:29 -0700895 boolean wallpaperMightChange = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700896 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700897 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700898 wallpaperMightChange |= win.clearAnimatingFlags();
Chong Zhange05bcb12016-07-26 17:47:29 -0700899 }
Chong Zhangb0d26702016-08-12 16:03:29 -0700900 if (wallpaperMightChange) {
901 requestUpdateWallpaperIfNeeded();
902 }
Chong Zhange05bcb12016-07-26 17:47:29 -0700903 }
904
Robert Carre12aece2016-02-02 22:43:27 -0800905 void destroySurfaces() {
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700906 destroySurfaces(false /*cleanupOnResume*/);
907 }
908
909 /**
910 * Destroy surfaces which have been marked as eligible by the animator, taking care to ensure
911 * the client has finished with them.
912 *
913 * @param cleanupOnResume whether this is done when app is resumed without fully stopped. If
914 * set to true, destroy only surfaces of removed windows, and clear relevant flags of the
915 * others so that they are ready to be reused. If set to false (common case), destroy all
916 * surfaces that's eligible, if the app is already stopped.
917 */
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700918 private void destroySurfaces(boolean cleanupOnResume) {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700919 boolean destroyedSomething = false;
Jorim Jaggia5e10572017-11-15 14:36:26 +0100920
921 // Copying to a different list as multiple children can be removed.
Jorim Jaggi59f3e922018-01-05 15:40:32 +0100922 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
Jorim Jaggia5e10572017-11-15 14:36:26 +0100923 for (int i = children.size() - 1; i >= 0; i--) {
924 final WindowState win = children.get(i);
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700925 destroyedSomething |= win.destroySurface(cleanupOnResume, mAppStopped);
Robert Carre12aece2016-02-02 22:43:27 -0800926 }
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700927 if (destroyedSomething) {
928 final DisplayContent dc = getDisplayContent();
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700929 dc.assignWindowLayers(true /*setLayoutNeeded*/);
Adrian Roos23df3a32018-03-15 15:41:13 +0100930 updateLetterboxSurface(null);
Robert Carre12aece2016-02-02 22:43:27 -0800931 }
932 }
933
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800934 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700935 * Notify that the app is now resumed, and it was not stopped before, perform a clean
936 * up of the surfaces
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800937 */
Jorim Jaggibae01b12017-04-11 16:29:10 -0700938 void notifyAppResumed(boolean wasStopped) {
Chong Zhangad24f962016-08-25 12:12:33 -0700939 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppResumed: wasStopped=" + wasStopped
Jorim Jaggibae01b12017-04-11 16:29:10 -0700940 + " " + this);
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700941 mAppStopped = false;
chaviwd3bf08d2017-08-01 17:24:59 -0700942 // Allow the window to turn the screen on once the app is resumed again.
943 setCanTurnScreenOn(true);
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700944 if (!wasStopped) {
945 destroySurfaces(true /*cleanupOnResume*/);
Wale Ogunwale8d5a5422016-03-03 18:28:21 -0800946 }
Robert Carre12aece2016-02-02 22:43:27 -0800947 }
948
Chong Zhangbef461f2015-10-27 11:38:24 -0700949 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700950 * Notify that the app has stopped, and it is okay to destroy any surfaces which were
951 * keeping alive in case they were still being used.
952 */
953 void notifyAppStopped() {
954 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: " + this);
955 mAppStopped = true;
956 destroySurfaces();
957 // Remove any starting window that was added for this app if they are still around.
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800958 removeStartingWindow();
Chong Zhang45e6d2d2016-07-20 18:33:56 -0700959 }
960
Chong Zhang92147042016-05-09 12:47:11 -0700961 void clearAllDrawn() {
962 allDrawn = false;
963 deferClearAllDrawn = false;
Chong Zhangbef461f2015-10-27 11:38:24 -0700964 }
965
Bryce Lee6d410262017-02-28 15:30:17 -0800966 Task getTask() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -0800967 return (Task) getParent();
Bryce Lee6d410262017-02-28 15:30:17 -0800968 }
969
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800970 TaskStack getStack() {
971 final Task task = getTask();
972 if (task != null) {
973 return task.mStack;
974 } else {
975 return null;
976 }
977 }
978
Bryce Lee6d410262017-02-28 15:30:17 -0800979 @Override
980 void onParentSet() {
981 super.onParentSet();
982
Robert Carred3e83b2017-04-21 13:26:55 -0700983 final Task task = getTask();
984
Bryce Lee6d410262017-02-28 15:30:17 -0800985 // When the associated task is {@code null}, the {@link AppWindowToken} can no longer
986 // access visual elements like the {@link DisplayContent}. We must remove any associations
987 // such as animations.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -0800988 if (!mReparenting) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -0800989 if (task == null) {
990 // It is possible we have been marked as a closing app earlier. We must remove ourselves
991 // from this list so we do not participate in any future animations.
lumark588a3e82018-07-20 18:53:54 +0800992 getDisplayContent().mClosingApps.remove(this);
Robert Carred3e83b2017-04-21 13:26:55 -0700993 } else if (mLastParent != null && mLastParent.mStack != null) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -0800994 task.mStack.mExitingAppTokens.remove(this);
995 }
Bryce Lee6d410262017-02-28 15:30:17 -0800996 }
Jorim Jaggi6de61012018-03-19 14:53:23 +0100997 final TaskStack stack = getStack();
998
999 // If we reparent, make sure to remove ourselves from the old animation registry.
1000 if (mAnimatingAppWindowTokenRegistry != null) {
1001 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
1002 }
1003 mAnimatingAppWindowTokenRegistry = stack != null
1004 ? stack.getAnimatingAppWindowTokenRegistry()
1005 : null;
1006
Robert Carred3e83b2017-04-21 13:26:55 -07001007 mLastParent = task;
chaviwdcf76ec2019-01-11 16:48:46 -08001008
1009 updateColorTransform();
Bryce Lee6d410262017-02-28 15:30:17 -08001010 }
1011
Wale Ogunwalefa854eb2016-09-20 13:43:52 -07001012 void postWindowRemoveStartingWindowCleanup(WindowState win) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001013 // TODO: Something smells about the code below...Is there a better way?
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001014 if (startingWindow == win) {
1015 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Notify removed startingWindow " + win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001016 removeStartingWindow();
Wale Ogunwale6c459212017-05-17 08:56:03 -07001017 } else if (mChildren.size() == 0) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001018 // If this is the last window and we had requested a starting transition window,
1019 // well there is no point now.
Jorim Jaggi02886a82016-12-06 09:10:06 -08001020 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Nulling last startingData");
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001021 startingData = null;
Wale Ogunwale6c459212017-05-17 08:56:03 -07001022 if (mHiddenSetFromTransferredStartingWindow) {
1023 // We set the hidden state to false for the token from a transferred starting window.
1024 // We now reset it back to true since the starting window was the last window in the
1025 // token.
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001026 setHidden(true);
Wale Ogunwale6c459212017-05-17 08:56:03 -07001027 }
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01001028 } else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001029 // If this is the last window except for a starting transition window,
1030 // we need to get rid of the starting transition.
Jorim Jaggie4b0f282017-05-17 15:10:29 +02001031 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Last window, removing starting window "
1032 + win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001033 removeStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001034 }
1035 }
1036
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001037 void removeDeadWindows() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001038 for (int winNdx = mChildren.size() - 1; winNdx >= 0; --winNdx) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001039 WindowState win = mChildren.get(winNdx);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001040 if (win.mAppDied) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001041 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.w(TAG,
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001042 "removeDeadWindows: " + win);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001043 // Set mDestroying, we don't want any animation or delayed removal here.
1044 win.mDestroying = true;
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001045 // Also removes child windows.
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001046 win.removeIfPossible();
Chong Zhang112eb8c2015-11-02 11:17:00 -08001047 }
1048 }
1049 }
1050
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001051 boolean hasWindowsAlive() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001052 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001053 // No need to loop through child windows as the answer should be the same as that of the
1054 // parent window.
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001055 if (!(mChildren.get(i)).mAppDied) {
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001056 return true;
1057 }
1058 }
1059 return false;
1060 }
1061
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001062 void setWillReplaceWindows(boolean animate) {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001063 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
1064 "Marking app token " + this + " with replacing windows.");
Robert Carra1eb4392015-12-10 12:43:51 -08001065
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001066 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001067 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001068 w.setWillReplaceWindow(animate);
Robert Carra1eb4392015-12-10 12:43:51 -08001069 }
Robert Carra1eb4392015-12-10 12:43:51 -08001070 }
1071
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001072 void setWillReplaceChildWindows() {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001073 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Marking app token " + this
Robert Carr23fa16b2016-01-13 13:19:58 -08001074 + " with replacing child windows.");
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001075 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001076 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001077 w.setWillReplaceChildWindows();
Robert Carr23fa16b2016-01-13 13:19:58 -08001078 }
1079 }
1080
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001081 void clearWillReplaceWindows() {
Wale Ogunwale455fac52016-07-21 07:24:49 -07001082 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
1083 "Resetting app token " + this + " of replacing window marks.");
Chong Zhangf596cd52016-01-05 13:42:44 -08001084
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001085 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001086 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001087 w.clearWillReplaceWindow();
Chong Zhangf596cd52016-01-05 13:42:44 -08001088 }
1089 }
1090
Chong Zhang4d7369a2016-04-25 16:09:14 -07001091 void requestUpdateWallpaperIfNeeded() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001092 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001093 final WindowState w = mChildren.get(i);
Chong Zhang4d7369a2016-04-25 16:09:14 -07001094 w.requestUpdateWallpaperIfNeeded();
1095 }
1096 }
1097
Chong Zhangd78ddb42016-03-02 17:01:14 -08001098 boolean isRelaunching() {
1099 return mPendingRelaunchCount > 0;
1100 }
1101
Robert Carr68375192017-06-13 12:41:53 -07001102 boolean shouldFreezeBounds() {
1103 final Task task = getTask();
1104
1105 // For freeform windows, we can't freeze the bounds at the moment because this would make
1106 // the resizing unresponsive.
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001107 if (task == null || task.inFreeformWindowingMode()) {
Robert Carr68375192017-06-13 12:41:53 -07001108 return false;
1109 }
1110
1111 // We freeze the bounds while drag resizing to deal with the time between
1112 // the divider/drag handle being released, and the handling it's new
1113 // configuration. If we are relaunched outside of the drag resizing state,
1114 // we need to be careful not to do this.
1115 return getTask().isDragResizing();
1116 }
1117
Chong Zhangd78ddb42016-03-02 17:01:14 -08001118 void startRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001119 if (shouldFreezeBounds()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08001120 freezeBounds();
1121 }
Robert Carrd5c7dd62017-03-08 10:39:30 -08001122
1123 // In the process of tearing down before relaunching, the app will
1124 // try and clean up it's child surfaces. We need to prevent this from
1125 // happening, so we sever the children, transfering their ownership
1126 // from the client it-self to the parent surface (owned by us).
Robert Carr29daa922018-04-27 11:56:48 -07001127 detachChildren();
1128
1129 mPendingRelaunchCount++;
1130 }
1131
1132 void detachChildren() {
Robert Carrfd8e93b2018-05-10 13:40:25 -07001133 SurfaceControl.openTransaction();
Robert Carrd5c7dd62017-03-08 10:39:30 -08001134 for (int i = mChildren.size() - 1; i >= 0; i--) {
1135 final WindowState w = mChildren.get(i);
1136 w.mWinAnimator.detachChildren();
1137 }
Robert Carrfd8e93b2018-05-10 13:40:25 -07001138 SurfaceControl.closeTransaction();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001139 }
1140
1141 void finishRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001142 unfreezeBounds();
1143
Chong Zhangd78ddb42016-03-02 17:01:14 -08001144 if (mPendingRelaunchCount > 0) {
1145 mPendingRelaunchCount--;
Bryce Lee081554b2017-05-25 07:52:12 -07001146 } else {
1147 // Update keyguard flags upon finishing relaunch.
1148 checkKeyguardFlagsChanged();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001149 }
1150 }
1151
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001152 void clearRelaunching() {
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001153 if (mPendingRelaunchCount == 0) {
1154 return;
1155 }
Robert Carr68375192017-06-13 12:41:53 -07001156 unfreezeBounds();
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001157 mPendingRelaunchCount = 0;
1158 }
1159
Wale Ogunwale07bcab72016-10-14 15:30:09 -07001160 /**
1161 * Returns true if the new child window we are adding to this token is considered greater than
1162 * the existing child window in this token in terms of z-order.
1163 */
1164 @Override
1165 protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
1166 WindowState existingWindow) {
1167 final int type1 = newWindow.mAttrs.type;
1168 final int type2 = existingWindow.mAttrs.type;
1169
1170 // Base application windows should be z-ordered BELOW all other windows in the app token.
1171 if (type1 == TYPE_BASE_APPLICATION && type2 != TYPE_BASE_APPLICATION) {
1172 return false;
1173 } else if (type1 != TYPE_BASE_APPLICATION && type2 == TYPE_BASE_APPLICATION) {
1174 return true;
1175 }
1176
1177 // Starting windows should be z-ordered ABOVE all other windows in the app token.
1178 if (type1 == TYPE_APPLICATION_STARTING && type2 != TYPE_APPLICATION_STARTING) {
1179 return true;
1180 } else if (type1 != TYPE_APPLICATION_STARTING && type2 == TYPE_APPLICATION_STARTING) {
1181 return false;
1182 }
1183
1184 // Otherwise the new window is greater than the existing window.
1185 return true;
1186 }
1187
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001188 @Override
Robert Carra1eb4392015-12-10 12:43:51 -08001189 void addWindow(WindowState w) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001190 super.addWindow(w);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001191
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001192 boolean gotReplacementWindow = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001193 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001194 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001195 gotReplacementWindow |= candidate.setReplacementWindowIfNeeded(w);
1196 }
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001197
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001198 // if we got a replacement window, reset the timeout to give drawing more time
1199 if (gotReplacementWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001200 mWmService.scheduleWindowReplacementTimeouts(this);
Robert Carra1eb4392015-12-10 12:43:51 -08001201 }
Jorim Jaggife762342016-10-13 14:33:27 +02001202 checkKeyguardFlagsChanged();
1203 }
1204
1205 @Override
1206 void removeChild(WindowState child) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001207 if (!mChildren.contains(child)) {
1208 // This can be true when testing.
1209 return;
1210 }
Jorim Jaggife762342016-10-13 14:33:27 +02001211 super.removeChild(child);
1212 checkKeyguardFlagsChanged();
Adrian Roos23df3a32018-03-15 15:41:13 +01001213 updateLetterboxSurface(child);
Robert Carra1eb4392015-12-10 12:43:51 -08001214 }
1215
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001216 private boolean waitingForReplacement() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001217 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001218 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001219 if (candidate.waitingForReplacement()) {
Robert Carra1eb4392015-12-10 12:43:51 -08001220 return true;
1221 }
1222 }
1223 return false;
1224 }
1225
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001226 void onWindowReplacementTimeout() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001227 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001228 (mChildren.get(i)).onWindowReplacementTimeout();
Robert Carra1eb4392015-12-10 12:43:51 -08001229 }
1230 }
1231
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001232 void reparent(Task task, int position) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001233 if (DEBUG_ADD_REMOVE) {
1234 Slog.i(TAG_WM, "reparent: moving app token=" + this
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001235 + " to task=" + task.mTaskId + " at " + position);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001236 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001237 if (task == null) {
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001238 throw new IllegalArgumentException("reparent: could not find task");
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001239 }
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001240 final Task currentTask = getTask();
1241 if (task == currentTask) {
Winson Chung30480042017-01-26 10:55:34 -08001242 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001243 "window token=" + this + " already child of task=" + currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001244 }
Bryce Lee6d410262017-02-28 15:30:17 -08001245
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001246 if (currentTask.mStack != task.mStack) {
Bryce Lee6d410262017-02-28 15:30:17 -08001247 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001248 "window token=" + this + " current task=" + currentTask
Bryce Lee6d410262017-02-28 15:30:17 -08001249 + " belongs to a different stack than " + task);
1250 }
1251
Winson Chung30480042017-01-26 10:55:34 -08001252 if (DEBUG_ADD_REMOVE) Slog.i(TAG, "reParentWindowToken: removing window token=" + this
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001253 + " from task=" + currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001254 final DisplayContent prevDisplayContent = getDisplayContent();
1255
Bryce Lee6d410262017-02-28 15:30:17 -08001256 mReparenting = true;
1257
Winson Chung30480042017-01-26 10:55:34 -08001258 getParent().removeChild(this);
1259 task.addChild(this, position);
1260
Bryce Lee6d410262017-02-28 15:30:17 -08001261 mReparenting = false;
1262
Winson Chung30480042017-01-26 10:55:34 -08001263 // Relayout display(s).
1264 final DisplayContent displayContent = task.getDisplayContent();
1265 displayContent.setLayoutNeeded();
1266 if (prevDisplayContent != displayContent) {
1267 onDisplayChanged(displayContent);
1268 prevDisplayContent.setLayoutNeeded();
1269 }
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001270 getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
Winson Chung30480042017-01-26 10:55:34 -08001271 }
1272
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001273 @Override
1274 void onDisplayChanged(DisplayContent dc) {
1275 DisplayContent prevDc = mDisplayContent;
1276 super.onDisplayChanged(dc);
1277 if (prevDc != null && prevDc.mFocusedApp == this) {
1278 prevDc.setFocusedApp(null);
lumarkbf844642018-11-23 17:11:36 +08001279 final TaskStack stack = dc.getTopStack();
1280 if (stack != null) {
1281 final Task task = stack.getTopChild();
1282 if (task != null && task.getTopChild() == this) {
1283 dc.setFocusedApp(this);
1284 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001285 }
1286 }
1287 }
1288
Jorim Jaggi0429f352015-12-22 16:29:16 +01001289 /**
1290 * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds
1291 * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even
1292 * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen
1293 * with a queue.
1294 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001295 private void freezeBounds() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001296 final Task task = getTask();
1297 mFrozenBounds.offer(new Rect(task.mPreparedFrozenBounds));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001298
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001299 if (task.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001300 // We didn't call prepareFreezingBounds on the task, so use the current value.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001301 mFrozenMergedConfig.offer(new Configuration(task.getConfiguration()));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001302 } else {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001303 mFrozenMergedConfig.offer(new Configuration(task.mPreparedFrozenMergedConfig));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001304 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001305 // Calling unset() to make it equal to Configuration.EMPTY.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001306 task.mPreparedFrozenMergedConfig.unset();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001307 }
1308
1309 /**
1310 * Unfreezes the previously frozen bounds. See {@link #freezeBounds}.
1311 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001312 private void unfreezeBounds() {
Robert Carr68375192017-06-13 12:41:53 -07001313 if (mFrozenBounds.isEmpty()) {
1314 return;
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001315 }
Robert Carr68375192017-06-13 12:41:53 -07001316 mFrozenBounds.remove();
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001317 if (!mFrozenMergedConfig.isEmpty()) {
1318 mFrozenMergedConfig.remove();
1319 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001320 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001321 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001322 win.onUnfreezeBounds();
Jorim Jaggi4846ee32016-01-07 17:39:12 +01001323 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001324 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001325 }
1326
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001327 void setAppLayoutChanges(int changes, String reason) {
1328 if (!mChildren.isEmpty()) {
1329 final DisplayContent dc = getDisplayContent();
1330 dc.pendingLayoutChanges |= changes;
1331 if (DEBUG_LAYOUT_REPEATS) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001332 mWmService.mWindowPlacerLocked.debugLayoutRepeats(reason, dc.pendingLayoutChanges);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001333 }
1334 }
1335 }
1336
1337 void removeReplacedWindowIfNeeded(WindowState replacement) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001338 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001339 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001340 if (win.removeReplacedWindowIfNeeded(replacement)) {
1341 return;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001342 }
1343 }
1344 }
1345
1346 void startFreezingScreen() {
1347 if (DEBUG_ORIENTATION) logWithStack(TAG, "Set freezing of " + appToken + ": hidden="
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001348 + isHidden() + " freezing=" + mFreezingScreen + " hiddenRequested="
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001349 + hiddenRequested);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001350 if (!hiddenRequested) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001351 if (!mFreezingScreen) {
1352 mFreezingScreen = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001353 mWmService.registerAppFreezeListener(this);
1354 mWmService.mAppsFreezingScreen++;
1355 if (mWmService.mAppsFreezingScreen == 1) {
1356 mWmService.startFreezingDisplayLocked(0, 0, getDisplayContent());
1357 mWmService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
1358 mWmService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001359 }
1360 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001361 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001362 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001363 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001364 w.onStartFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001365 }
1366 }
1367 }
1368
1369 void stopFreezingScreen(boolean unfreezeSurfaceNow, boolean force) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001370 if (!mFreezingScreen) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001371 return;
1372 }
1373 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + this + " force=" + force);
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001374 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001375 boolean unfrozeWindows = false;
1376 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001377 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001378 unfrozeWindows |= w.onStopFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001379 }
1380 if (force || unfrozeWindows) {
1381 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "No longer freezing: " + this);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001382 mFreezingScreen = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001383 mWmService.unregisterAppFreezeListener(this);
1384 mWmService.mAppsFreezingScreen--;
1385 mWmService.mLastFinishedFreezeSource = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001386 }
1387 if (unfreezeSurfaceNow) {
1388 if (unfrozeWindows) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001389 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001390 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001391 mWmService.stopFreezingDisplayLocked();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001392 }
1393 }
1394
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001395 @Override
1396 public void onAppFreezeTimeout() {
1397 Slog.w(TAG_WM, "Force clearing freeze: " + this);
1398 stopFreezingScreen(true, true);
1399 }
1400
Jorim Jaggi60f9c972018-02-01 19:21:07 +01001401 /**
1402 * Tries to transfer the starting window from a token that's above ourselves in the task but
1403 * not visible anymore. This is a common scenario apps use: Trampoline activity T start main
1404 * activity M in the same task. Now, when reopening the task, T starts on top of M but then
1405 * immediately finishes after, so we have to transfer T to M.
1406 */
1407 void transferStartingWindowFromHiddenAboveTokenIfNeeded() {
1408 final Task task = getTask();
1409 for (int i = task.mChildren.size() - 1; i >= 0; i--) {
1410 final AppWindowToken fromToken = task.mChildren.get(i);
1411 if (fromToken == this) {
1412 return;
1413 }
1414 if (fromToken.hiddenRequested && transferStartingWindow(fromToken.token)) {
1415 return;
1416 }
1417 }
1418 }
1419
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001420 boolean transferStartingWindow(IBinder transferFrom) {
Wale Ogunwale02319a62016-09-26 15:21:22 -07001421 final AppWindowToken fromToken = getDisplayContent().getAppWindowToken(transferFrom);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001422 if (fromToken == null) {
1423 return false;
1424 }
1425
1426 final WindowState tStartingWindow = fromToken.startingWindow;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08001427 if (tStartingWindow != null && fromToken.startingSurface != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001428 // In this case, the starting icon has already been displayed, so start
1429 // letting windows get shown immediately without any more transitions.
lumark588a3e82018-07-20 18:53:54 +08001430 getDisplayContent().mSkipAppTransitionAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001431
1432 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Moving existing starting " + tStartingWindow
1433 + " from " + fromToken + " to " + this);
1434
1435 final long origId = Binder.clearCallingIdentity();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001436 try {
1437 // Transfer the starting window over to the new token.
1438 startingData = fromToken.startingData;
1439 startingSurface = fromToken.startingSurface;
1440 startingDisplayed = fromToken.startingDisplayed;
1441 fromToken.startingDisplayed = false;
1442 startingWindow = tStartingWindow;
1443 reportedVisible = fromToken.reportedVisible;
1444 fromToken.startingData = null;
1445 fromToken.startingSurface = null;
1446 fromToken.startingWindow = null;
1447 fromToken.startingMoved = true;
1448 tStartingWindow.mToken = this;
1449 tStartingWindow.mAppToken = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001450
Peter Visontay3556a3b2017-11-01 17:23:17 +00001451 if (DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
1452 "Removing starting " + tStartingWindow + " from " + fromToken);
1453 fromToken.removeChild(tStartingWindow);
1454 fromToken.postWindowRemoveStartingWindowCleanup(tStartingWindow);
1455 fromToken.mHiddenSetFromTransferredStartingWindow = false;
1456 addWindow(tStartingWindow);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001457
Peter Visontay3556a3b2017-11-01 17:23:17 +00001458 // Propagate other interesting state between the tokens. If the old token is displayed,
1459 // we should immediately force the new one to be displayed. If it is animating, we need
1460 // to move that animation to the new one.
1461 if (fromToken.allDrawn) {
1462 allDrawn = true;
1463 deferClearAllDrawn = fromToken.deferClearAllDrawn;
1464 }
1465 if (fromToken.firstWindowDrawn) {
1466 firstWindowDrawn = true;
1467 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001468 if (!fromToken.isHidden()) {
1469 setHidden(false);
Peter Visontay3556a3b2017-11-01 17:23:17 +00001470 hiddenRequested = false;
1471 mHiddenSetFromTransferredStartingWindow = true;
1472 }
1473 setClientHidden(fromToken.mClientHidden);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001474
Jorim Jaggi980c9de2017-11-17 01:41:37 +01001475 transferAnimation(fromToken);
1476
1477 // When transferring an animation, we no longer need to apply an animation to the
1478 // the token we transfer the animation over. Thus, remove the animation from
1479 // pending opening apps.
lumark588a3e82018-07-20 18:53:54 +08001480 getDisplayContent().mOpeningApps.remove(this);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001481
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001482 mWmService.updateFocusedWindowLocked(
Peter Visontay3556a3b2017-11-01 17:23:17 +00001483 UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/);
1484 getDisplayContent().setLayoutNeeded();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001485 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001486 } finally {
1487 Binder.restoreCallingIdentity(origId);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001488 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001489 return true;
1490 } else if (fromToken.startingData != null) {
1491 // The previous app was getting ready to show a
1492 // starting window, but hasn't yet done so. Steal it!
1493 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
1494 "Moving pending starting from " + fromToken + " to " + this);
1495 startingData = fromToken.startingData;
1496 fromToken.startingData = null;
1497 fromToken.startingMoved = true;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001498 scheduleAddStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001499 return true;
1500 }
1501
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001502 // TODO: Transfer thumbnail
1503
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001504 return false;
1505 }
1506
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001507 boolean isLastWindow(WindowState win) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001508 return mChildren.size() == 1 && mChildren.get(0) == win;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001509 }
1510
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001511 @Override
1512 void onAppTransitionDone() {
1513 sendingToBottom = false;
1514 }
1515
Wale Ogunwale51362492016-09-08 17:49:17 -07001516 /**
1517 * We override because this class doesn't want its children affecting its reported orientation
1518 * in anyway.
1519 */
1520 @Override
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001521 int getOrientation(int candidate) {
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001522 if (candidate == SCREEN_ORIENTATION_BEHIND) {
1523 // Allow app to specify orientation regardless of its visibility state if the current
1524 // candidate want us to use orientation behind. I.e. the visible app on-top of this one
1525 // wants us to use the orientation of the app behind it.
1526 return mOrientation;
1527 }
1528
Bryce Lee61fbcbc2017-03-10 14:14:03 -08001529 // The {@link AppWindowToken} should only specify an orientation when it is not closing or
1530 // going to the bottom. Allowing closing {@link AppWindowToken} to participate can lead to
1531 // an Activity in another task being started in the wrong orientation during the transition.
lumark588a3e82018-07-20 18:53:54 +08001532 if (!(sendingToBottom || getDisplayContent().mClosingApps.contains(this))
1533 && (isVisible() || getDisplayContent().mOpeningApps.contains(this))) {
Bryce Leea163b762017-01-24 11:05:01 -08001534 return mOrientation;
Wale Ogunwale51362492016-09-08 17:49:17 -07001535 }
Bryce Leea163b762017-01-24 11:05:01 -08001536
1537 return SCREEN_ORIENTATION_UNSET;
Wale Ogunwale51362492016-09-08 17:49:17 -07001538 }
1539
Wale Ogunwaleb198b742016-12-01 08:44:09 -08001540 /** Returns the app's preferred orientation regardless of its currently visibility state. */
1541 int getOrientationIgnoreVisibility() {
1542 return mOrientation;
1543 }
1544
Craig Mautnerdbb79912012-03-01 18:59:14 -08001545 @Override
Winson Chunge55c0192017-08-24 14:50:48 -07001546 public void onConfigurationChanged(Configuration newParentConfig) {
1547 final int prevWinMode = getWindowingMode();
Evan Rosky2289ba12018-11-19 18:28:18 -08001548 mTmpPrevBounds.set(getBounds());
Winson Chunge55c0192017-08-24 14:50:48 -07001549 super.onConfigurationChanged(newParentConfig);
1550 final int winMode = getWindowingMode();
1551
1552 if (prevWinMode == winMode) {
1553 return;
1554 }
1555
1556 if (prevWinMode != WINDOWING_MODE_UNDEFINED && winMode == WINDOWING_MODE_PINNED) {
1557 // Entering PiP from fullscreen, reset the snap fraction
1558 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(this);
Winson Chung82267ce2018-04-06 16:38:26 -07001559 } else if (prevWinMode == WINDOWING_MODE_PINNED && winMode != WINDOWING_MODE_UNDEFINED
1560 && !isHidden()) {
Winson Chunge55c0192017-08-24 14:50:48 -07001561 // Leaving PiP to fullscreen, save the snap fraction based on the pre-animation bounds
1562 // for the next re-entry into PiP (assuming the activity is not hidden or destroyed)
1563 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
1564 if (pinnedStack != null) {
Winson Chung8efa1652018-06-06 09:34:23 -07001565 final Rect stackBounds;
1566 if (pinnedStack.lastAnimatingBoundsWasToFullscreen()) {
1567 // We are animating the bounds, use the pre-animation bounds to save the snap
1568 // fraction
1569 stackBounds = pinnedStack.mPreAnimationBounds;
1570 } else {
1571 // We skip the animation if the fullscreen configuration is not compatible, so
1572 // use the current bounds to calculate the saved snap fraction instead
1573 // (see PinnedActivityStack.skipResizeAnimation())
1574 stackBounds = mTmpRect;
1575 pinnedStack.getBounds(stackBounds);
1576 }
Winson Chunge55c0192017-08-24 14:50:48 -07001577 mDisplayContent.mPinnedStackControllerLocked.saveReentrySnapFraction(this,
Winson Chung8efa1652018-06-06 09:34:23 -07001578 stackBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001579 }
Evan Rosky2289ba12018-11-19 18:28:18 -08001580 } else if (shouldStartChangeTransition(prevWinMode, winMode)) {
1581 initializeChangeTransition(mTmpPrevBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001582 }
1583 }
1584
Evan Rosky2289ba12018-11-19 18:28:18 -08001585 private boolean shouldStartChangeTransition(int prevWinMode, int newWinMode) {
1586 if (!isVisible() || getDisplayContent().mAppTransition.isTransitionSet()) {
1587 return false;
1588 }
1589 // Only do an animation into and out-of freeform mode for now. Other mode
1590 // transition animations are currently handled by system-ui.
1591 return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
1592 }
1593
1594 /**
1595 * Initializes a change transition. Because the app is visible already, there is a small period
1596 * of time where the user can see the app content/window update before the transition starts.
1597 * To prevent this, we immediately take a snapshot and place the app/snapshot into a leash which
1598 * "freezes" the location/crop until the transition starts.
1599 * <p>
1600 * Here's a walk-through of the process:
1601 * 1. Create a temporary leash ("interim-change-leash") and reparent the app to it.
1602 * 2. Set the temporary leash's position/crop to the current state.
1603 * 3. Create a snapshot and place that at the top of the leash to cover up content changes.
1604 * 4. Once the transition is ready, it will reparent the app to the animation leash.
1605 * 5. Detach the interim-change-leash.
1606 */
1607 private void initializeChangeTransition(Rect startBounds) {
1608 mDisplayContent.prepareAppTransition(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
1609 false /* alwaysKeepCurrent */, 0, false /* forceOverride */);
1610 mDisplayContent.mChangingApps.add(this);
1611 mTransitStartRect.set(startBounds);
1612
1613 final SurfaceControl.Builder builder = makeAnimationLeash()
1614 .setParent(getAnimationLeashParent())
1615 .setName(getSurfaceControl() + " - interim-change-leash");
1616 mTransitChangeLeash = builder.build();
1617 Transaction t = getPendingTransaction();
1618 t.setWindowCrop(mTransitChangeLeash, startBounds.width(), startBounds.height());
1619 t.setPosition(mTransitChangeLeash, startBounds.left, startBounds.top);
1620 t.show(mTransitChangeLeash);
1621 t.reparent(getSurfaceControl(), mTransitChangeLeash);
1622 onAnimationLeashCreated(t, mTransitChangeLeash);
1623
1624 if (mThumbnail == null && getTask() != null) {
1625 final TaskSnapshotController snapshotCtrl = mWmService.mTaskSnapshotController;
1626 final ArraySet<Task> tasks = new ArraySet<>();
1627 tasks.add(getTask());
1628 snapshotCtrl.snapshotTasks(tasks);
1629 snapshotCtrl.addSkipClosingAppSnapshotTasks(tasks);
1630 final ActivityManager.TaskSnapshot snapshot = snapshotCtrl.getSnapshot(
1631 getTask().mTaskId, getTask().mUserId, false /* restoreFromDisk */,
1632 false /* reducedResolution */);
1633 mThumbnail = new AppWindowThumbnail(t, this, snapshot.getSnapshot(),
1634 true /* relative */);
1635 }
1636 }
1637
1638 boolean isInChangeTransition() {
1639 return mTransitChangeLeash != null || isChangeTransition(mTransit);
1640 }
1641
Winson Chunge55c0192017-08-24 14:50:48 -07001642 @Override
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001643 void checkAppWindowsReadyToShow() {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001644 if (allDrawn == mLastAllDrawn) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001645 return;
1646 }
1647
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001648 mLastAllDrawn = allDrawn;
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001649 if (!allDrawn) {
1650 return;
1651 }
1652
1653 // The token has now changed state to having all windows shown... what to do, what to do?
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001654 if (mFreezingScreen) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001655 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001656 stopFreezingScreen(false, true);
1657 if (DEBUG_ORIENTATION) Slog.i(TAG,
1658 "Setting mOrientationChangeComplete=true because wtoken " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001659 + " numInteresting=" + mNumInterestingWindows + " numDrawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001660 // This will set mOrientationChangeComplete and cause a pass through layout.
1661 setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001662 "checkAppWindowsReadyToShow: freezingScreen");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001663 } else {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001664 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001665
1666 // We can now show all of the drawn windows!
lumark588a3e82018-07-20 18:53:54 +08001667 if (!getDisplayContent().mOpeningApps.contains(this) && canShowWindows()) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001668 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001669 }
1670 }
1671 }
1672
Matthew Ng5d23afa2017-06-21 16:16:24 -07001673 /**
Bryce Leed390deb2017-06-22 13:14:28 -07001674 * Returns whether the drawn window states of this {@link AppWindowToken} has considered every
1675 * child {@link WindowState}. A child is considered if it has been passed into
1676 * {@link #updateDrawnWindowStates(WindowState)} after being added. This is used to determine
1677 * whether states, such as {@code allDrawn}, can be set, which relies on state variables such as
1678 * {@code mNumInterestingWindows}, which depend on all {@link WindowState}s being considered.
1679 *
1680 * @return {@code true} If all children have been considered, {@code false}.
1681 */
1682 private boolean allDrawnStatesConsidered() {
Bryce Lee6311c4b2017-07-06 14:09:29 -07001683 for (int i = mChildren.size() - 1; i >= 0; --i) {
1684 final WindowState child = mChildren.get(i);
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001685 if (child.mightAffectAllDrawn() && !child.getDrawnStateEvaluated()) {
Bryce Leed390deb2017-06-22 13:14:28 -07001686 return false;
1687 }
1688 }
1689 return true;
1690 }
1691
1692 /**
Matthew Ng5d23afa2017-06-21 16:16:24 -07001693 * Determines if the token has finished drawing. This should only be called from
1694 * {@link DisplayContent#applySurfaceChangesTransaction}
1695 */
Matthew Ng498c71d2017-04-18 13:55:45 -07001696 void updateAllDrawn() {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001697 if (!allDrawn) {
Matthew Ng498c71d2017-04-18 13:55:45 -07001698 // Number of drawn windows can be less when a window is being relaunched, wait for
Bryce Leed390deb2017-06-22 13:14:28 -07001699 // all windows to be launched and drawn for this token be considered all drawn.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001700 final int numInteresting = mNumInterestingWindows;
Bryce Leed390deb2017-06-22 13:14:28 -07001701
1702 // We must make sure that all present children have been considered (determined by
1703 // {@link #allDrawnStatesConsidered}) before evaluating whether everything has been
1704 // drawn.
1705 if (numInteresting > 0 && allDrawnStatesConsidered()
1706 && mNumDrawnWindows >= numInteresting && !isRelaunching()) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001707 if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawn: " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001708 + " interesting=" + numInteresting + " drawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001709 allDrawn = true;
1710 // Force an additional layout pass where
1711 // WindowStateAnimator#commitFinishDrawingLocked() will call performShowLocked().
Matthew Ng498c71d2017-04-18 13:55:45 -07001712 if (mDisplayContent != null) {
1713 mDisplayContent.setLayoutNeeded();
1714 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001715 mWmService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
Robert Carrecc06b32017-04-18 14:25:10 -07001716
Winson Chunge7ba6862017-05-24 12:13:33 -07001717 // Notify the pinned stack upon all windows drawn. If there was an animation in
1718 // progress then this signal will resume that animation.
Wale Ogunwale61911492017-10-11 08:50:50 -07001719 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
Winson Chunge7ba6862017-05-24 12:13:33 -07001720 if (pinnedStack != null) {
1721 pinnedStack.onAllWindowsDrawn();
Robert Carrecc06b32017-04-18 14:25:10 -07001722 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001723 }
1724 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001725 }
1726
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001727 boolean keyDispatchingTimedOut(String reason, int windowPid) {
1728 return mActivityRecord != null && mActivityRecord.keyDispatchingTimedOut(reason, windowPid);
1729 }
1730
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001731 /**
1732 * Updated this app token tracking states for interesting and drawn windows based on the window.
1733 *
1734 * @return Returns true if the input window is considered interesting and drawn while all the
1735 * windows in this app token where not considered drawn as of the last pass.
1736 */
1737 boolean updateDrawnWindowStates(WindowState w) {
Bryce Leed390deb2017-06-22 13:14:28 -07001738 w.setDrawnStateEvaluated(true /*evaluated*/);
1739
Jorim Jaggie4b0f282017-05-17 15:10:29 +02001740 if (DEBUG_STARTING_WINDOW_VERBOSE && w == startingWindow) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001741 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + w.isOnScreen()
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001742 + " allDrawn=" + allDrawn + " freezingScreen=" + mFreezingScreen);
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001743 }
1744
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001745 if (allDrawn && !mFreezingScreen) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001746 return false;
1747 }
1748
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001749 if (mLastTransactionSequence != mWmService.mTransactionSequence) {
1750 mLastTransactionSequence = mWmService.mTransactionSequence;
Matthew Ng53e66b22018-01-12 17:13:13 -08001751 mNumDrawnWindows = 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001752 startingDisplayed = false;
Matthew Ng53e66b22018-01-12 17:13:13 -08001753
1754 // There is the main base application window, even if it is exiting, wait for it
1755 mNumInterestingWindows = findMainWindow(false /* includeStartingApp */) != null ? 1 : 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001756 }
1757
1758 final WindowStateAnimator winAnimator = w.mWinAnimator;
1759
1760 boolean isInterestingAndDrawn = false;
1761
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001762 if (!allDrawn && w.mightAffectAllDrawn()) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001763 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
1764 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001765 + ", isAnimationSet=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001766 if (!w.isDrawnLw()) {
1767 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController
1768 + " pv=" + w.mPolicyVisibility
1769 + " mDrawState=" + winAnimator.drawStateToString()
1770 + " ph=" + w.isParentWindowHidden() + " th=" + hiddenRequested
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001771 + " a=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001772 }
1773 }
1774
1775 if (w != startingWindow) {
1776 if (w.isInteresting()) {
Matthew Ng53e66b22018-01-12 17:13:13 -08001777 // Add non-main window as interesting since the main app has already been added
1778 if (findMainWindow(false /* includeStartingApp */) != w) {
1779 mNumInterestingWindows++;
1780 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001781 if (w.isDrawnLw()) {
1782 mNumDrawnWindows++;
1783
1784 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, "tokenMayBeDrawn: "
1785 + this + " w=" + w + " numInteresting=" + mNumInterestingWindows
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001786 + " freezingScreen=" + mFreezingScreen
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001787 + " mAppFreezing=" + w.mAppFreezing);
1788
1789 isInterestingAndDrawn = true;
1790 }
1791 }
1792 } else if (w.isDrawnLw()) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001793 if (mActivityRecord != null) {
1794 mActivityRecord.onStartingWindowDrawn(SystemClock.uptimeMillis());
Jorim Jaggi3878ca32017-02-02 17:13:05 -08001795 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001796 startingDisplayed = true;
1797 }
1798 }
1799
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001800 return isInterestingAndDrawn;
1801 }
1802
Adrian Roos23df3a32018-03-15 15:41:13 +01001803 void layoutLetterbox(WindowState winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001804 final WindowState w = findMainWindow();
Adrian Roosf93b6d22018-03-21 13:48:26 +01001805 if (w == null || winHint != null && w != winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001806 return;
1807 }
Jorim Jaggia32da382018-03-28 18:01:22 +02001808 final boolean surfaceReady = w.isDrawnLw() // Regular case
Adrian Roosf93b6d22018-03-21 13:48:26 +01001809 || w.mWinAnimator.mSurfaceDestroyDeferred // The preserved surface is still ready.
1810 || w.isDragResizeChanged(); // Waiting for relayoutWindow to call preserveSurface.
1811 final boolean needsLetterbox = w.isLetterboxedAppWindow() && fillsParent() && surfaceReady;
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001812 if (needsLetterbox) {
1813 if (mLetterbox == null) {
1814 mLetterbox = new Letterbox(() -> makeChildSurface(null));
1815 }
Adrian Roos7af9d972018-11-30 15:26:27 +01001816 getPosition(mTmpPoint);
1817 mLetterbox.layout(getParent().getBounds(), w.getFrameLw(), mTmpPoint);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001818 } else if (mLetterbox != null) {
Adrian Roos23df3a32018-03-15 15:41:13 +01001819 mLetterbox.hide();
1820 }
1821 }
1822
1823 void updateLetterboxSurface(WindowState winHint) {
1824 final WindowState w = findMainWindow();
1825 if (w != winHint && winHint != null && w != null) {
1826 return;
1827 }
1828 layoutLetterbox(winHint);
1829 if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) {
1830 mLetterbox.applySurfaceChanges(mPendingTransaction);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01001831 }
1832 }
1833
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001834 @Override
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001835 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001836 // For legacy reasons we process the TaskStack.mExitingAppTokens first in DisplayContent
1837 // before the non-exiting app tokens. So, we skip the exiting app tokens here.
1838 // TODO: Investigate if we need to continue to do this or if we can just process them
1839 // in-order.
1840 if (mIsExiting && !waitingForReplacement()) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001841 return false;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001842 }
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001843 return forAllWindowsUnchecked(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001844 }
1845
lumark588a3e82018-07-20 18:53:54 +08001846 @Override
1847 void forAllAppWindows(Consumer<AppWindowToken> callback) {
1848 callback.accept(this);
1849 }
1850
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001851 boolean forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback,
1852 boolean traverseTopToBottom) {
1853 return super.forAllWindows(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001854 }
1855
1856 @Override
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07001857 AppWindowToken asAppWindowToken() {
1858 // I am an app window token!
1859 return this;
1860 }
1861
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001862 boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
1863 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
1864 IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
1865 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
1866 // If the display is frozen, we won't do anything until the actual window is
1867 // displayed so there is no reason to put in the starting window.
1868 if (!okToDisplay()) {
1869 return false;
1870 }
1871
1872 if (startingData != null) {
1873 return false;
1874 }
1875
1876 final WindowState mainWin = findMainWindow();
1877 if (mainWin != null && mainWin.mWinAnimator.getShown()) {
1878 // App already has a visible window...why would you want a starting window?
1879 return false;
1880 }
1881
1882 final ActivityManager.TaskSnapshot snapshot =
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001883 mWmService.mTaskSnapshotController.getSnapshot(
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001884 getTask().mTaskId, getTask().mUserId,
1885 false /* restoreFromDisk */, false /* reducedResolution */);
1886 final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
1887 allowTaskSnapshot, activityCreated, fromRecents, snapshot);
1888
1889 if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
1890 return createSnapshot(snapshot);
1891 }
1892
1893 // If this is a translucent window, then don't show a starting window -- the current
1894 // effect (a full-screen opaque starting window that fades away to the real contents
1895 // when it is ready) does not work for this.
1896 if (DEBUG_STARTING_WINDOW) {
1897 Slog.v(TAG, "Checking theme of starting window: 0x" + Integer.toHexString(theme));
1898 }
1899 if (theme != 0) {
1900 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
1901 com.android.internal.R.styleable.Window,
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001902 mWmService.mCurrentUserId);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001903 if (ent == null) {
1904 // Whoops! App doesn't exist. Um. Okay. We'll just pretend like we didn't
1905 // see that.
1906 return false;
1907 }
1908 final boolean windowIsTranslucent = ent.array.getBoolean(
1909 com.android.internal.R.styleable.Window_windowIsTranslucent, false);
1910 final boolean windowIsFloating = ent.array.getBoolean(
1911 com.android.internal.R.styleable.Window_windowIsFloating, false);
1912 final boolean windowShowWallpaper = ent.array.getBoolean(
1913 com.android.internal.R.styleable.Window_windowShowWallpaper, false);
1914 final boolean windowDisableStarting = ent.array.getBoolean(
1915 com.android.internal.R.styleable.Window_windowDisablePreview, false);
1916 if (DEBUG_STARTING_WINDOW) {
1917 Slog.v(TAG, "Translucent=" + windowIsTranslucent
1918 + " Floating=" + windowIsFloating
1919 + " ShowWallpaper=" + windowShowWallpaper);
1920 }
1921 if (windowIsTranslucent) {
1922 return false;
1923 }
1924 if (windowIsFloating || windowDisableStarting) {
1925 return false;
1926 }
1927 if (windowShowWallpaper) {
1928 if (getDisplayContent().mWallpaperController
1929 .getWallpaperTarget() == null) {
1930 // If this theme is requesting a wallpaper, and the wallpaper
1931 // is not currently visible, then this effectively serves as
1932 // an opaque window and our starting window transition animation
1933 // can still work. We just need to make sure the starting window
1934 // is also showing the wallpaper.
1935 windowFlags |= FLAG_SHOW_WALLPAPER;
1936 } else {
1937 return false;
1938 }
1939 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001940 }
Yunfan Chen8a8c0ed2018-12-18 16:46:32 -08001941
1942 if (transferStartingWindow(transferFrom)) {
1943 return true;
1944 }
1945
1946 // There is no existing starting window, and we don't want to create a splash screen, so
1947 // that's it!
1948 if (type != STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
1949 return false;
1950 }
1951
1952 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SplashScreenStartingData");
1953 startingData = new SplashScreenStartingData(mWmService, pkg,
1954 theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
1955 getMergedOverrideConfiguration());
1956 scheduleAddStartingWindow();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001957 return true;
1958 }
1959
1960
1961 private boolean createSnapshot(ActivityManager.TaskSnapshot snapshot) {
1962 if (snapshot == null) {
1963 return false;
1964 }
1965
1966 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SnapshotStartingData");
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001967 startingData = new SnapshotStartingData(mWmService, snapshot);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001968 scheduleAddStartingWindow();
1969 return true;
1970 }
1971
1972 void scheduleAddStartingWindow() {
1973 // Note: we really want to do sendMessageAtFrontOfQueue() because we
1974 // want to process the message ASAP, before any other queued
1975 // messages.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001976 if (!mWmService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001977 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING");
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001978 mWmService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001979 }
1980 }
1981
1982 private final Runnable mAddStartingWindow = new Runnable() {
1983
1984 @Override
1985 public void run() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001986 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001987 // There can only be one adding request, silly caller!
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001988 mWmService.mAnimationHandler.removeCallbacks(this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001989 }
1990
1991 if (startingData == null) {
1992 // Animation has been canceled... do nothing.
1993 if (DEBUG_STARTING_WINDOW) {
1994 Slog.v(TAG, "startingData was nulled out before handling"
1995 + " mAddStartingWindow: " + AppWindowToken.this);
1996 }
1997 return;
1998 }
1999
2000 if (DEBUG_STARTING_WINDOW) {
2001 Slog.v(TAG, "Add starting " + this + ": startingData=" + startingData);
2002 }
2003
2004 WindowManagerPolicy.StartingSurface surface = null;
2005 try {
2006 surface = startingData.createStartingSurface(AppWindowToken.this);
2007 } catch (Exception e) {
2008 Slog.w(TAG, "Exception when adding starting window", e);
2009 }
2010 if (surface != null) {
2011 boolean abort = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002012 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002013 // If the window was successfully added, then
2014 // we need to remove it.
2015 if (removed || startingData == null) {
2016 if (DEBUG_STARTING_WINDOW) {
2017 Slog.v(TAG, "Aborted starting " + AppWindowToken.this
2018 + ": removed=" + removed + " startingData=" + startingData);
2019 }
2020 startingWindow = null;
2021 startingData = null;
2022 abort = true;
2023 } else {
2024 startingSurface = surface;
2025 }
2026 if (DEBUG_STARTING_WINDOW && !abort) {
2027 Slog.v(TAG, "Added starting " + AppWindowToken.this + ": startingWindow="
2028 + startingWindow + " startingView=" + startingSurface);
2029 }
2030 }
2031 if (abort) {
2032 surface.remove();
2033 }
2034 } else if (DEBUG_STARTING_WINDOW) {
2035 Slog.v(TAG, "Surface returned was null: " + AppWindowToken.this);
2036 }
2037 }
2038 };
2039
2040 private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
2041 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents,
2042 ActivityManager.TaskSnapshot snapshot) {
2043 if (getDisplayContent().mAppTransition.getAppTransition()
2044 == TRANSIT_DOCK_TASK_FROM_RECENTS) {
2045 // TODO(b/34099271): Remove this statement to add back the starting window and figure
2046 // out why it causes flickering, the starting window appears over the thumbnail while
2047 // the docked from recents transition occurs
2048 return STARTING_WINDOW_TYPE_NONE;
2049 } else if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
2050 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2051 } else if (taskSwitch && allowTaskSnapshot) {
Kevin716a9db2018-12-18 16:53:39 -08002052 if (mWmService.mLowRamTaskSnapshotsAndRecents) {
Kevin58b47f12018-12-17 14:09:01 -08002053 // For low RAM devices, we use the splash screen starting window instead of the
2054 // task snapshot starting window.
2055 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2056 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002057 return snapshot == null ? STARTING_WINDOW_TYPE_NONE
2058 : snapshotOrientationSameAsTask(snapshot) || fromRecents
2059 ? STARTING_WINDOW_TYPE_SNAPSHOT : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2060 } else {
2061 return STARTING_WINDOW_TYPE_NONE;
2062 }
2063 }
2064
2065
2066 private boolean snapshotOrientationSameAsTask(ActivityManager.TaskSnapshot snapshot) {
2067 if (snapshot == null) {
2068 return false;
2069 }
2070 return getTask().getConfiguration().orientation == snapshot.getOrientation();
2071 }
2072
2073 void removeStartingWindow() {
2074 if (startingWindow == null) {
2075 if (startingData != null) {
2076 // Starting window has not been added yet, but it is scheduled to be added.
2077 // Go ahead and cancel the request.
2078 if (DEBUG_STARTING_WINDOW) {
2079 Slog.v(TAG_WM, "Clearing startingData for token=" + this);
2080 }
2081 startingData = null;
2082 }
2083 return;
2084 }
2085
2086 final WindowManagerPolicy.StartingSurface surface;
2087 if (startingData != null) {
2088 surface = startingSurface;
2089 startingData = null;
2090 startingSurface = null;
2091 startingWindow = null;
2092 startingDisplayed = false;
2093 if (surface == null) {
2094 if (DEBUG_STARTING_WINDOW) {
2095 Slog.v(TAG_WM, "startingWindow was set but startingSurface==null, couldn't "
2096 + "remove");
2097 }
2098 return;
2099 }
2100 } else {
2101 if (DEBUG_STARTING_WINDOW) {
2102 Slog.v(TAG_WM, "Tried to remove starting window but startingWindow was null:"
2103 + this);
2104 }
2105 return;
2106 }
2107
2108 if (DEBUG_STARTING_WINDOW) {
2109 Slog.v(TAG_WM, "Schedule remove starting " + this
2110 + " startingWindow=" + startingWindow
2111 + " startingView=" + startingSurface
2112 + " Callers=" + Debug.getCallers(5));
2113 }
2114
2115 // Use the same thread to remove the window as we used to add it, as otherwise we end up
2116 // with things in the view hierarchy being called from different threads.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002117 mWmService.mAnimationHandler.post(() -> {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002118 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Removing startingView=" + surface);
2119 try {
2120 surface.remove();
2121 } catch (Exception e) {
2122 Slog.w(TAG_WM, "Exception when removing starting window", e);
2123 }
2124 });
2125 }
2126
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002127 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -07002128 boolean fillsParent() {
2129 return mFillsParent;
2130 }
2131
2132 void setFillsParent(boolean fillsParent) {
2133 mFillsParent = fillsParent;
2134 }
2135
Jorim Jaggife762342016-10-13 14:33:27 +02002136 boolean containsDismissKeyguardWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002137 // Window state is transient during relaunch. We are not guaranteed to be frozen during the
2138 // entirety of the relaunch.
2139 if (isRelaunching()) {
2140 return mLastContainsDismissKeyguardWindow;
2141 }
2142
Jorim Jaggife762342016-10-13 14:33:27 +02002143 for (int i = mChildren.size() - 1; i >= 0; i--) {
2144 if ((mChildren.get(i).mAttrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
2145 return true;
2146 }
2147 }
2148 return false;
2149 }
2150
2151 boolean containsShowWhenLockedWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002152 // When we are relaunching, it is possible for us to be unfrozen before our previous
2153 // windows have been added back. Using the cached value ensures that our previous
2154 // showWhenLocked preference is honored until relaunching is complete.
2155 if (isRelaunching()) {
2156 return mLastContainsShowWhenLockedWindow;
2157 }
2158
Jorim Jaggife762342016-10-13 14:33:27 +02002159 for (int i = mChildren.size() - 1; i >= 0; i--) {
2160 if ((mChildren.get(i).mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
2161 return true;
2162 }
2163 }
Bryce Lee081554b2017-05-25 07:52:12 -07002164
Jorim Jaggife762342016-10-13 14:33:27 +02002165 return false;
2166 }
2167
2168 void checkKeyguardFlagsChanged() {
2169 final boolean containsDismissKeyguard = containsDismissKeyguardWindow();
2170 final boolean containsShowWhenLocked = containsShowWhenLockedWindow();
2171 if (containsDismissKeyguard != mLastContainsDismissKeyguardWindow
2172 || containsShowWhenLocked != mLastContainsShowWhenLockedWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002173 mWmService.notifyKeyguardFlagsChanged(null /* callback */,
lumark588a3e82018-07-20 18:53:54 +08002174 getDisplayContent().getDisplayId());
Jorim Jaggife762342016-10-13 14:33:27 +02002175 }
2176 mLastContainsDismissKeyguardWindow = containsDismissKeyguard;
2177 mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
2178 }
2179
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002180 WindowState getImeTargetBelowWindow(WindowState w) {
2181 final int index = mChildren.indexOf(w);
2182 if (index > 0) {
2183 final WindowState target = mChildren.get(index - 1);
2184 if (target.canBeImeTarget()) {
2185 return target;
2186 }
2187 }
2188 return null;
2189 }
2190
2191 WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
2192 WindowState candidate = null;
2193 for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
2194 final WindowState w = mChildren.get(i);
2195 if (w.mRemoved) {
2196 continue;
2197 }
Jorim Jaggi35d328a2018-08-14 17:00:20 +02002198 if (candidate == null) {
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002199 candidate = w;
2200 }
2201 }
2202 return candidate;
2203 }
2204
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002205 /**
2206 * See {@link Activity#setDisablePreviewScreenshots}.
2207 */
2208 void setDisablePreviewScreenshots(boolean disable) {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002209 mDisablePreviewScreenshots = disable;
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002210 }
2211
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002212 /**
chaviwd3bf08d2017-08-01 17:24:59 -07002213 * Sets whether the current launch can turn the screen on. See {@link #canTurnScreenOn()}
2214 */
2215 void setCanTurnScreenOn(boolean canTurnScreenOn) {
2216 mCanTurnScreenOn = canTurnScreenOn;
2217 }
2218
2219 /**
2220 * Indicates whether the current launch can turn the screen on. This is to prevent multiple
2221 * relayouts from turning the screen back on. The screen should only turn on at most
2222 * once per activity resume.
2223 *
2224 * @return true if the screen can be turned on.
2225 */
2226 boolean canTurnScreenOn() {
2227 return mCanTurnScreenOn;
2228 }
2229
2230 /**
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002231 * Retrieves whether we'd like to generate a snapshot that's based solely on the theme. This is
2232 * the case when preview screenshots are disabled {@link #setDisablePreviewScreenshots} or when
2233 * we can't take a snapshot for other reasons, for example, if we have a secure window.
2234 *
2235 * @return True if we need to generate an app theme snapshot, false if we'd like to take a real
2236 * screenshot.
2237 */
2238 boolean shouldUseAppThemeSnapshot() {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002239 return mDisablePreviewScreenshots || forAllWindows(w -> (w.mAttrs.flags & FLAG_SECURE) != 0,
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002240 true /* topToBottom */);
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002241 }
2242
Jorim Jaggibe418292018-03-26 16:14:12 +02002243 SurfaceControl getAppAnimationLayer() {
Jorim Jaggi391790622018-04-18 15:30:44 +02002244 return getAppAnimationLayer(isActivityTypeHome() ? ANIMATION_LAYER_HOME
2245 : needsZBoost() ? ANIMATION_LAYER_BOOSTED
2246 : ANIMATION_LAYER_STANDARD);
Jorim Jaggibe418292018-03-26 16:14:12 +02002247 }
2248
chaviw23ee71c2017-12-18 11:29:41 -08002249 @Override
Jorim Jaggi596a1992017-12-29 14:48:02 +01002250 public SurfaceControl getAnimationLeashParent() {
Robert Carrb9506032018-02-13 13:54:00 -08002251 // All normal app transitions take place in an animation layer which is below the pinned
2252 // stack but may be above the parent stacks of the given animating apps.
2253 // For transitions in the pinned stack (menu activity) we just let them occur as a child
2254 // of the pinned stack.
2255 if (!inPinnedWindowingMode()) {
2256 return getAppAnimationLayer();
2257 } else {
2258 return getStack().getSurfaceControl();
2259 }
chaviw23ee71c2017-12-18 11:29:41 -08002260 }
2261
Jorim Jaggic6976f02018-04-18 16:31:07 +02002262 private boolean shouldAnimate(int transit) {
2263 final boolean isSplitScreenPrimary =
2264 getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
2265 final boolean allowSplitScreenPrimaryAnimation = transit != TRANSIT_WALLPAPER_OPEN;
2266
2267 // We animate always if it's not split screen primary, and only some special cases in split
2268 // screen primary because it causes issues with stack clipping when we run an un-minimize
2269 // animation at the same time.
2270 return !isSplitScreenPrimary || allowSplitScreenPrimaryAnimation;
2271 }
2272
Vishnu Naira2977262018-07-26 13:31:26 -07002273 /**
2274 * Creates a layer to apply crop to an animation.
2275 */
2276 private SurfaceControl createAnimationBoundsLayer(Transaction t) {
2277 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.i(TAG, "Creating animation bounds layer");
2278 final SurfaceControl.Builder builder = makeAnimationLeash()
2279 .setParent(getAnimationLeashParent())
Vishnu Naire86bd982018-11-28 13:23:17 -08002280 .setName(getSurfaceControl() + " - animation-bounds");
Vishnu Naira2977262018-07-26 13:31:26 -07002281 final SurfaceControl boundsLayer = builder.build();
2282 t.show(boundsLayer);
2283 return boundsLayer;
2284 }
2285
Riddle Hsua118b3a2018-10-11 22:05:06 +08002286 /** Get position and crop region of animation. */
2287 @VisibleForTesting
2288 void getAnimationBounds(Point outPosition, Rect outBounds) {
2289 outPosition.set(0, 0);
2290 outBounds.setEmpty();
2291
2292 final TaskStack stack = getStack();
2293 final Task task = getTask();
2294 if (task != null && task.inFreeformWindowingMode()) {
Evan Roskyed6767f2018-10-26 17:21:06 -07002295 task.getRelativeDisplayedPosition(outPosition);
Riddle Hsua118b3a2018-10-11 22:05:06 +08002296 } else if (stack != null) {
Evan Roskyed6767f2018-10-26 17:21:06 -07002297 stack.getRelativeDisplayedPosition(outPosition);
Riddle Hsua118b3a2018-10-11 22:05:06 +08002298 }
2299
2300 // Always use stack bounds in order to have the ability to animate outside the task region.
2301 // It also needs to be consistent when {@link #mNeedsAnimationBoundsLayer} is set that crops
2302 // according to the bounds.
2303 if (stack != null) {
2304 stack.getBounds(outBounds);
2305 }
2306 // We have the relative position so the local position can be removed from bounds.
2307 outBounds.offsetTo(0, 0);
2308 }
2309
Evan Roskyed6767f2018-10-26 17:21:06 -07002310 @Override
2311 Rect getDisplayedBounds() {
2312 final Task task = getTask();
2313 if (task != null) {
2314 final Rect overrideDisplayedBounds = task.getOverrideDisplayedBounds();
2315 if (!overrideDisplayedBounds.isEmpty()) {
2316 return overrideDisplayedBounds;
2317 }
2318 }
2319 return getBounds();
2320 }
2321
Evan Rosky2289ba12018-11-19 18:28:18 -08002322 private static boolean isChangeTransition(int transit) {
2323 return transit == TRANSIT_TASK_CHANGE_WINDOWING_MODE;
2324 }
2325
2326 private int getDefaultChangeTransitionDuration() {
2327 return (int) (AppTransition.DEFAULT_APP_TRANSITION_DURATION
2328 * mWmService.getTransitionAnimationScaleLocked());
2329 }
2330
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002331 boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter,
2332 boolean isVoiceInteraction) {
2333
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002334 if (mWmService.mDisableTransitionAnimation || !shouldAnimate(transit)) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002335 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
Jorim Jaggic6976f02018-04-18 16:31:07 +02002336 Slog.v(TAG_WM, "applyAnimation: transition animation is disabled or skipped."
2337 + " atoken=" + this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002338 }
2339 cancelAnimation();
2340 return false;
2341 }
2342
2343 // Only apply an animation if the display isn't frozen. If it is frozen, there is no reason
2344 // to animate and it can cause strange artifacts when we unfreeze the display if some
2345 // different animation is running.
2346 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#applyAnimationLocked");
2347 if (okToAnimate()) {
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002348 final AnimationAdapter adapter;
Evan Rosky2289ba12018-11-19 18:28:18 -08002349 AnimationAdapter thumbnailAdapter = null;
Riddle Hsua118b3a2018-10-11 22:05:06 +08002350 getAnimationBounds(mTmpPoint, mTmpRect);
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002351
Evan Rosky2289ba12018-11-19 18:28:18 -08002352 boolean isChanging = isChangeTransition(transit) && mThumbnail != null;
2353
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002354 // Delaying animation start isn't compatible with remote animations at all.
lumark588a3e82018-07-20 18:53:54 +08002355 if (getDisplayContent().mAppTransition.getRemoteAnimationController() != null
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002356 && !mSurfaceAnimator.isAnimationStartDelayed()) {
Evan Rosky2289ba12018-11-19 18:28:18 -08002357 RemoteAnimationRecord adapters =
2358 getDisplayContent().mAppTransition.getRemoteAnimationController()
2359 .createRemoteAnimationRecord(this, mTmpPoint, mTmpRect,
2360 (isChanging ? mTransitStartRect : null));
2361 adapter = adapters.mAdapter;
2362 thumbnailAdapter = adapters.mThumbnailAdapter;
2363 } else if (isChanging) {
2364 int duration = getDefaultChangeTransitionDuration();
2365 mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y);
2366 adapter = new LocalAnimationAdapter(
2367 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
2368 getDisplayContent().getDisplayInfo(), duration,
2369 true /* isAppAnimation */, false /* isThumbnail */),
2370 mWmService.mSurfaceAnimationRunner);
2371 thumbnailAdapter = new LocalAnimationAdapter(
2372 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
2373 getDisplayContent().getDisplayInfo(), duration,
2374 true /* isAppAnimation */, true /* isThumbnail */),
2375 mWmService.mSurfaceAnimationRunner);
2376 mTransit = transit;
2377 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002378 } else {
lumark588a3e82018-07-20 18:53:54 +08002379 final int appStackClipMode =
2380 getDisplayContent().mAppTransition.getAppStackClipMode();
Vishnu Naira2977262018-07-26 13:31:26 -07002381 mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM);
2382
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002383 final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
2384 if (a != null) {
2385 adapter = new LocalAnimationAdapter(
2386 new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
lumark588a3e82018-07-20 18:53:54 +08002387 getDisplayContent().mAppTransition.canSkipFirstFrame(),
Vishnu Naira2977262018-07-26 13:31:26 -07002388 appStackClipMode,
Jorim Jaggiaa763cd2018-03-22 23:20:36 +01002389 true /* isAppAnimation */),
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002390 mWmService.mSurfaceAnimationRunner);
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002391 if (a.getZAdjustment() == Animation.ZORDER_TOP) {
2392 mNeedsZBoost = true;
2393 }
2394 mTransit = transit;
lumark588a3e82018-07-20 18:53:54 +08002395 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002396 } else {
2397 adapter = null;
chaviw23ee71c2017-12-18 11:29:41 -08002398 }
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002399 }
2400 if (adapter != null) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002401 startAnimation(getPendingTransaction(), adapter, !isVisible());
Jorim Jaggi82c17862018-02-21 17:50:18 +01002402 if (adapter.getShowWallpaper()) {
2403 mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2404 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002405 if (thumbnailAdapter != null) {
2406 mThumbnail.startAnimation(
2407 getPendingTransaction(), thumbnailAdapter, !isVisible());
2408 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002409 }
2410 } else {
2411 cancelAnimation();
2412 }
2413 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2414
2415 return isReallyAnimating();
2416 }
2417
2418 private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
2419 boolean isVoiceInteraction) {
2420 final DisplayContent displayContent = getTask().getDisplayContent();
2421 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2422 final int width = displayInfo.appWidth;
2423 final int height = displayInfo.appHeight;
2424 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG_WM,
2425 "applyAnimation: atoken=" + this);
2426
2427 // Determine the visible rect to calculate the thumbnail clip
2428 final WindowState win = findMainWindow();
2429 final Rect frame = new Rect(0, 0, width, height);
2430 final Rect displayFrame = new Rect(0, 0,
2431 displayInfo.logicalWidth, displayInfo.logicalHeight);
2432 final Rect insets = new Rect();
2433 final Rect stableInsets = new Rect();
2434 Rect surfaceInsets = null;
2435 final boolean freeform = win != null && win.inFreeformWindowingMode();
2436 if (win != null) {
2437 // Containing frame will usually cover the whole screen, including dialog windows.
2438 // For freeform workspace windows it will not cover the whole screen and it also
2439 // won't exactly match the final freeform window frame (e.g. when overlapping with
2440 // the status bar). In that case we need to use the final frame.
2441 if (freeform) {
chaviw492139a2018-07-16 16:07:35 -07002442 frame.set(win.getFrameLw());
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002443 } else if (win.isLetterboxedAppWindow()) {
2444 frame.set(getTask().getBounds());
Winson Chungc1674272018-02-21 10:15:17 -08002445 } else if (win.isDockedResizing()) {
2446 // If we are animating while docked resizing, then use the stack bounds as the
2447 // animation target (which will be different than the task bounds)
2448 frame.set(getTask().getParent().getBounds());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002449 } else {
chaviw553b0212018-07-12 13:37:01 -07002450 frame.set(win.getContainingFrame());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002451 }
2452 surfaceInsets = win.getAttrs().surfaceInsets;
Adrian Roos20e07892018-02-23 19:12:01 +01002453 // XXX(b/72757033): These are insets relative to the window frame, but we're really
2454 // interested in the insets relative to the frame we chose in the if-blocks above.
chaviw9c81e632018-07-31 11:17:52 -07002455 win.getContentInsets(insets);
2456 win.getStableInsets(stableInsets);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002457 }
2458
2459 if (mLaunchTaskBehind) {
2460 // Differentiate the two animations. This one which is briefly on the screen
2461 // gets the !enter animation, and the other activity which remains on the
2462 // screen gets the enter animation. Both appear in the mOpeningApps set.
2463 enter = false;
2464 }
2465 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "Loading animation for app transition."
2466 + " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter
2467 + " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets);
2468 final Configuration displayConfig = displayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08002469 final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002470 displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
2471 surfaceInsets, stableInsets, isVoiceInteraction, freeform, getTask().mTaskId);
2472 if (a != null) {
2473 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
2474 final int containingWidth = frame.width();
2475 final int containingHeight = frame.height();
2476 a.initialize(containingWidth, containingHeight, width, height);
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002477 a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002478 }
2479 return a;
2480 }
2481
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002482 @Override
Jorim Jaggi6de61012018-03-19 14:53:23 +01002483 public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
2484 return mAnimatingAppWindowTokenRegistry != null
2485 && mAnimatingAppWindowTokenRegistry.notifyAboutToFinish(
2486 this, endDeferFinishCallback);
2487 }
2488
2489 @Override
2490 public void onAnimationLeashDestroyed(Transaction t) {
2491 super.onAnimationLeashDestroyed(t);
Vishnu Naira2977262018-07-26 13:31:26 -07002492 if (mAnimationBoundsLayer != null) {
Robert Carr8810b692018-12-11 15:49:48 -08002493 t.reparent(mAnimationBoundsLayer, null);
Vishnu Naira2977262018-07-26 13:31:26 -07002494 mAnimationBoundsLayer = null;
2495 }
2496
Jorim Jaggi6de61012018-03-19 14:53:23 +01002497 if (mAnimatingAppWindowTokenRegistry != null) {
2498 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
2499 }
2500 }
2501
2502 @Override
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002503 protected void setLayer(Transaction t, int layer) {
2504 if (!mSurfaceAnimator.hasLeash()) {
2505 t.setLayer(mSurfaceControl, layer);
2506 }
2507 }
2508
2509 @Override
2510 protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
2511 if (!mSurfaceAnimator.hasLeash()) {
2512 t.setRelativeLayer(mSurfaceControl, relativeTo, layer);
2513 }
2514 }
2515
2516 @Override
2517 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
2518 if (!mSurfaceAnimator.hasLeash()) {
Robert Carr10584fa2019-01-14 15:55:19 -08002519 t.reparent(mSurfaceControl, newParent);
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002520 }
2521 }
2522
2523 @Override
2524 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002525 // The leash is parented to the animation layer. We need to preserve the z-order by using
2526 // the prefix order index, but we boost if necessary.
Robert Carrb9506032018-02-13 13:54:00 -08002527 int layer = 0;
2528 if (!inPinnedWindowingMode()) {
2529 layer = getPrefixOrderIndex();
2530 } else {
2531 // Pinned stacks have animations take place within themselves rather than an animation
2532 // layer so we need to preserve the order relative to the stack (e.g. the order of our
2533 // task/parent).
2534 layer = getParent().getPrefixOrderIndex();
2535 }
2536
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002537 if (mNeedsZBoost) {
2538 layer += Z_BOOST_BASE;
2539 }
2540 leash.setLayer(layer);
Robert Carr2f8aa392018-01-31 14:46:51 -08002541
2542 final DisplayContent dc = getDisplayContent();
Jorim Jaggibe418292018-03-26 16:14:12 +02002543 dc.assignStackOrdering();
Evan Rosky2289ba12018-11-19 18:28:18 -08002544
2545 if (leash == mTransitChangeLeash) {
2546 // This is a temporary state so skip any animation notifications
2547 return;
2548 } else if (mTransitChangeLeash != null) {
2549 // unparent mTransitChangeLeash for clean-up
2550 t.hide(mTransitChangeLeash);
2551 t.reparent(mTransitChangeLeash, null);
2552 mTransitChangeLeash = null;
2553 }
2554
Jorim Jaggi6de61012018-03-19 14:53:23 +01002555 if (mAnimatingAppWindowTokenRegistry != null) {
2556 mAnimatingAppWindowTokenRegistry.notifyStarting(this);
2557 }
Vishnu Naira2977262018-07-26 13:31:26 -07002558
2559 // If the animation needs to be cropped then an animation bounds layer is created as a child
2560 // of the pinned stack or animation layer. The leash is then reparented to this new layer.
2561 if (mNeedsAnimationBoundsLayer) {
2562 final TaskStack stack = getStack();
2563 if (stack == null) {
2564 return;
2565 }
2566 mAnimationBoundsLayer = createAnimationBoundsLayer(t);
2567
2568 // Set clip rect to stack bounds.
2569 mTmpRect.setEmpty();
2570 stack.getBounds(mTmpRect);
2571
2572 // Crop to stack bounds.
2573 t.setWindowCrop(mAnimationBoundsLayer, mTmpRect);
2574
2575 // Reparent leash to animation bounds layer.
Robert Carr10584fa2019-01-14 15:55:19 -08002576 t.reparent(leash, mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002577 }
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002578 }
2579
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002580 /**
2581 * This must be called while inside a transaction.
2582 */
2583 void showAllWindowsLocked() {
2584 forAllWindows(windowState -> {
2585 if (DEBUG_VISIBILITY) Slog.v(TAG, "performing show on: " + windowState);
2586 windowState.performShowLocked();
2587 }, false /* traverseTopToBottom */);
Jorim Jaggia5e10572017-11-15 14:36:26 +01002588 }
2589
2590 @Override
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002591 protected void onAnimationFinished() {
2592 super.onAnimationFinished();
2593
2594 mTransit = TRANSIT_UNSET;
2595 mTransitFlags = 0;
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002596 mNeedsZBoost = false;
Vishnu Naira2977262018-07-26 13:31:26 -07002597 mNeedsAnimationBoundsLayer = false;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002598
2599 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER,
2600 "AppWindowToken");
2601
Jorim Jaggi988f6682017-11-17 17:46:43 +01002602 clearThumbnail();
Jorim Jaggi752cd822018-03-29 16:29:18 +02002603 setClientHidden(isHidden() && hiddenRequested);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002604
lumarkff0ab692018-11-05 20:32:30 +08002605 getDisplayContent().computeImeTargetIfNeeded(this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002606
2607 if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + this
2608 + ": reportedVisible=" + reportedVisible
2609 + " okToDisplay=" + okToDisplay()
2610 + " okToAnimate=" + okToAnimate()
2611 + " startingDisplayed=" + startingDisplayed);
2612
Evan Rosky2289ba12018-11-19 18:28:18 -08002613 // clean up thumbnail window
2614 if (mThumbnail != null) {
2615 mThumbnail.destroy();
2616 mThumbnail = null;
2617 }
2618
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002619 // WindowState.onExitAnimationDone might modify the children list, so make a copy and then
2620 // traverse the copy.
2621 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
2622 children.forEach(WindowState::onExitAnimationDone);
2623
lumark588a3e82018-07-20 18:53:54 +08002624 getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002625 scheduleAnimation();
2626 }
2627
2628 @Override
2629 boolean isAppAnimating() {
2630 return isSelfAnimating();
2631 }
2632
2633 @Override
2634 boolean isSelfAnimating() {
2635 // If we are about to start a transition, we also need to be considered animating.
2636 return isWaitingForTransitionStart() || isReallyAnimating();
2637 }
2638
2639 /**
2640 * @return True if and only if we are actually running an animation. Note that
2641 * {@link #isSelfAnimating} also returns true if we are waiting for an animation to
2642 * start.
2643 */
2644 private boolean isReallyAnimating() {
2645 return super.isSelfAnimating();
2646 }
2647
Jorim Jaggi988f6682017-11-17 17:46:43 +01002648 @Override
2649 void cancelAnimation() {
Evan Rosky2289ba12018-11-19 18:28:18 -08002650 cancelAnimationOnly();
Jorim Jaggi988f6682017-11-17 17:46:43 +01002651 clearThumbnail();
Evan Rosky2289ba12018-11-19 18:28:18 -08002652 if (mTransitChangeLeash != null) {
2653 getPendingTransaction().hide(mTransitChangeLeash);
2654 getPendingTransaction().reparent(mTransitChangeLeash, null);
2655 mTransitChangeLeash = null;
2656 }
2657 }
2658
2659 /**
2660 * This only cancels the animation. It doesn't do other teardown like cleaning-up thumbnail
2661 * or interim leashes.
2662 * <p>
2663 * Used when canceling in preparation for starting a new animation.
2664 */
2665 void cancelAnimationOnly() {
2666 super.cancelAnimation();
Jorim Jaggi988f6682017-11-17 17:46:43 +01002667 }
2668
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002669 boolean isWaitingForTransitionStart() {
lumark588a3e82018-07-20 18:53:54 +08002670 return getDisplayContent().mAppTransition.isTransitionSet()
2671 && (getDisplayContent().mOpeningApps.contains(this)
Evan Rosky2289ba12018-11-19 18:28:18 -08002672 || getDisplayContent().mClosingApps.contains(this)
2673 || getDisplayContent().mChangingApps.contains(this));
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002674 }
2675
2676 public int getTransit() {
2677 return mTransit;
2678 }
2679
2680 int getTransitFlags() {
2681 return mTransitFlags;
2682 }
2683
Jorim Jaggi988f6682017-11-17 17:46:43 +01002684 void attachThumbnailAnimation() {
2685 if (!isReallyAnimating()) {
2686 return;
2687 }
2688 final int taskId = getTask().mTaskId;
2689 final GraphicBuffer thumbnailHeader =
lumark588a3e82018-07-20 18:53:54 +08002690 getDisplayContent().mAppTransition.getAppTransitionThumbnailHeader(taskId);
Jorim Jaggi988f6682017-11-17 17:46:43 +01002691 if (thumbnailHeader == null) {
2692 if (DEBUG_APP_TRANSITIONS) Slog.d(TAG, "No thumbnail header bitmap for: " + taskId);
2693 return;
2694 }
2695 clearThumbnail();
2696 mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnailHeader);
2697 mThumbnail.startAnimation(getPendingTransaction(), loadThumbnailAnimation(thumbnailHeader));
2698 }
2699
Tony Mak64b8d562017-12-28 17:44:02 +00002700 /**
2701 * Attaches a surface with a thumbnail for the
2702 * {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation.
2703 */
2704 void attachCrossProfileAppsThumbnailAnimation() {
2705 if (!isReallyAnimating()) {
2706 return;
2707 }
2708 clearThumbnail();
2709
2710 final WindowState win = findMainWindow();
2711 if (win == null) {
2712 return;
2713 }
chaviw492139a2018-07-16 16:07:35 -07002714 final Rect frame = win.getFrameLw();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002715 final int thumbnailDrawableRes = getTask().mUserId == mWmService.mCurrentUserId
Tony Mak64b8d562017-12-28 17:44:02 +00002716 ? R.drawable.ic_account_circle
Tony Makda4af232018-04-27 11:01:10 +01002717 : R.drawable.ic_corp_badge;
Tony Mak64b8d562017-12-28 17:44:02 +00002718 final GraphicBuffer thumbnail =
lumark588a3e82018-07-20 18:53:54 +08002719 getDisplayContent().mAppTransition
Tony Mak64b8d562017-12-28 17:44:02 +00002720 .createCrossProfileAppsThumbnail(thumbnailDrawableRes, frame);
2721 if (thumbnail == null) {
2722 return;
2723 }
2724 mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnail);
2725 final Animation animation =
lumark588a3e82018-07-20 18:53:54 +08002726 getDisplayContent().mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(
chaviw492139a2018-07-16 16:07:35 -07002727 win.getFrameLw());
Tony Mak64b8d562017-12-28 17:44:02 +00002728 mThumbnail.startAnimation(getPendingTransaction(), animation, new Point(frame.left,
2729 frame.top));
2730 }
2731
Jorim Jaggi988f6682017-11-17 17:46:43 +01002732 private Animation loadThumbnailAnimation(GraphicBuffer thumbnailHeader) {
2733 final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
2734
2735 // If this is a multi-window scenario, we use the windows frame as
2736 // destination of the thumbnail header animation. If this is a full screen
2737 // window scenario, we use the whole display as the target.
2738 WindowState win = findMainWindow();
2739 Rect appRect = win != null ? win.getContentFrameLw() :
2740 new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
chaviw9c81e632018-07-31 11:17:52 -07002741 final Rect insets = win != null ? win.getContentInsets() : null;
Jorim Jaggi988f6682017-11-17 17:46:43 +01002742 final Configuration displayConfig = mDisplayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08002743 return getDisplayContent().mAppTransition.createThumbnailAspectScaleAnimationLocked(
Jorim Jaggi988f6682017-11-17 17:46:43 +01002744 appRect, insets, thumbnailHeader, getTask().mTaskId, displayConfig.uiMode,
2745 displayConfig.orientation);
2746 }
2747
2748 private void clearThumbnail() {
2749 if (mThumbnail == null) {
2750 return;
2751 }
2752 mThumbnail.destroy();
2753 mThumbnail = null;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002754 }
2755
Jorim Jaggif84e2f62018-01-16 14:17:59 +01002756 void registerRemoteAnimations(RemoteAnimationDefinition definition) {
2757 mRemoteAnimationDefinition = definition;
2758 }
2759
2760 RemoteAnimationDefinition getRemoteAnimationDefinition() {
2761 return mRemoteAnimationDefinition;
2762 }
2763
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002764 @Override
2765 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
2766 super.dump(pw, prefix, dumpAll);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002767 if (appToken != null) {
Wale Ogunwale72919d22016-12-08 18:58:50 -08002768 pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002769 }
Winson Chung48b25652018-10-22 14:04:30 -07002770 pw.println(prefix + "component=" + mActivityComponent.flattenToShortString());
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08002771 pw.print(prefix); pw.print("task="); pw.println(getTask());
Wale Ogunwale51362492016-09-08 17:49:17 -07002772 pw.print(prefix); pw.print(" mFillsParent="); pw.print(mFillsParent);
2773 pw.print(" mOrientation="); pw.println(mOrientation);
Wale Ogunwale89973222017-04-23 18:39:45 -07002774 pw.println(prefix + "hiddenRequested=" + hiddenRequested + " mClientHidden=" + mClientHidden
2775 + ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "")
2776 + " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible);
Craig Mautner59431632012-04-04 11:56:44 -07002777 if (paused) {
2778 pw.print(prefix); pw.print("paused="); pw.println(paused);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002779 }
Wale Ogunwale9017ec02016-02-25 08:55:25 -08002780 if (mAppStopped) {
2781 pw.print(prefix); pw.print("mAppStopped="); pw.println(mAppStopped);
2782 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002783 if (mNumInterestingWindows != 0 || mNumDrawnWindows != 0
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002784 || allDrawn || mLastAllDrawn) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002785 pw.print(prefix); pw.print("mNumInterestingWindows=");
2786 pw.print(mNumInterestingWindows);
2787 pw.print(" mNumDrawnWindows="); pw.print(mNumDrawnWindows);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002788 pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
Craig Mautner6fbda632012-07-03 09:26:39 -07002789 pw.print(" allDrawn="); pw.print(allDrawn);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002790 pw.print(" lastAllDrawn="); pw.print(mLastAllDrawn);
Craig Mautner6fbda632012-07-03 09:26:39 -07002791 pw.println(")");
2792 }
2793 if (inPendingTransaction) {
2794 pw.print(prefix); pw.print("inPendingTransaction=");
2795 pw.println(inPendingTransaction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002796 }
Craig Mautner799bc1d2015-01-14 10:33:48 -08002797 if (startingData != null || removed || firstWindowDrawn || mIsExiting) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002798 pw.print(prefix); pw.print("startingData="); pw.print(startingData);
2799 pw.print(" removed="); pw.print(removed);
Craig Mautner3d7ca312015-01-08 10:56:00 -08002800 pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
Craig Mautner799bc1d2015-01-14 10:33:48 -08002801 pw.print(" mIsExiting="); pw.println(mIsExiting);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002802 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08002803 if (startingWindow != null || startingSurface != null
Wale Ogunwale6c459212017-05-17 08:56:03 -07002804 || startingDisplayed || startingMoved || mHiddenSetFromTransferredStartingWindow) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002805 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08002806 pw.print(" startingSurface="); pw.print(startingSurface);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002807 pw.print(" startingDisplayed="); pw.print(startingDisplayed);
Wale Ogunwale6c459212017-05-17 08:56:03 -07002808 pw.print(" startingMoved="); pw.print(startingMoved);
2809 pw.println(" mHiddenSetFromTransferredStartingWindow="
2810 + mHiddenSetFromTransferredStartingWindow);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002811 }
Jorim Jaggi0429f352015-12-22 16:29:16 +01002812 if (!mFrozenBounds.isEmpty()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08002813 pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
Jorim Jaggi26c8c422016-05-09 19:57:25 -07002814 pw.print(prefix); pw.print("mFrozenMergedConfig="); pw.println(mFrozenMergedConfig);
Chong Zhangd78ddb42016-03-02 17:01:14 -08002815 }
2816 if (mPendingRelaunchCount != 0) {
2817 pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount);
Jorim Jaggi0429f352015-12-22 16:29:16 +01002818 }
Wale Ogunwalee287e192017-04-21 09:30:12 -07002819 if (mRemovingFromDisplay) {
2820 pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay);
2821 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002822 }
2823
2824 @Override
2825 void setHidden(boolean hidden) {
2826 super.setHidden(hidden);
Winson Chunge55c0192017-08-24 14:50:48 -07002827
2828 if (hidden) {
2829 // Once the app window is hidden, reset the last saved PiP snap fraction
2830 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(this);
2831 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002832 scheduleAnimation();
2833 }
2834
2835 @Override
2836 void prepareSurfaces() {
2837 // isSelfAnimating also returns true when we are about to start a transition, so we need
2838 // to check super here.
2839 final boolean reallyAnimating = super.isSelfAnimating();
2840 final boolean show = !isHidden() || reallyAnimating;
2841 if (show && !mLastSurfaceShowing) {
2842 mPendingTransaction.show(mSurfaceControl);
2843 } else if (!show && mLastSurfaceShowing) {
2844 mPendingTransaction.hide(mSurfaceControl);
Jorim Jaggi4d1835d2017-08-31 17:28:27 +02002845 }
Jorim Jaggi988f6682017-11-17 17:46:43 +01002846 if (mThumbnail != null) {
2847 mThumbnail.setShowing(mPendingTransaction, show);
2848 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002849 mLastSurfaceShowing = show;
2850 super.prepareSurfaces();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002851 }
2852
Jorim Jaggi77d0f36c2018-03-16 17:49:49 +01002853 /**
2854 * @return Whether our {@link #getSurfaceControl} is currently showing.
2855 */
2856 boolean isSurfaceShowing() {
2857 return mLastSurfaceShowing;
2858 }
2859
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002860 boolean isFreezingScreen() {
2861 return mFreezingScreen;
2862 }
2863
2864 @Override
2865 boolean needsZBoost() {
2866 return mNeedsZBoost || super.needsZBoost();
2867 }
2868
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07002869 @CallSuper
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002870 @Override
Adrian Roos4921ccf2017-09-28 16:54:06 +02002871 public void writeToProto(ProtoOutputStream proto, long fieldId, boolean trim) {
Steven Timotiusaf03df62017-07-18 16:56:43 -07002872 final long token = proto.start(fieldId);
2873 writeNameToProto(proto, NAME);
Adrian Roos4921ccf2017-09-28 16:54:06 +02002874 super.writeToProto(proto, WINDOW_TOKEN, trim);
Vishnu Nair04ab4392018-01-10 11:00:06 -08002875 proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing);
2876 proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart());
2877 proto.write(IS_REALLY_ANIMATING, isReallyAnimating());
2878 if (mThumbnail != null){
2879 mThumbnail.writeToProto(proto, THUMBNAIL);
2880 }
2881 proto.write(FILLS_PARENT, mFillsParent);
2882 proto.write(APP_STOPPED, mAppStopped);
2883 proto.write(HIDDEN_REQUESTED, hiddenRequested);
2884 proto.write(CLIENT_HIDDEN, mClientHidden);
2885 proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient);
2886 proto.write(REPORTED_DRAWN, reportedDrawn);
2887 proto.write(REPORTED_VISIBLE, reportedVisible);
2888 proto.write(NUM_INTERESTING_WINDOWS, mNumInterestingWindows);
2889 proto.write(NUM_DRAWN_WINDOWS, mNumDrawnWindows);
2890 proto.write(ALL_DRAWN, allDrawn);
2891 proto.write(LAST_ALL_DRAWN, mLastAllDrawn);
2892 proto.write(REMOVED, removed);
2893 if (startingWindow != null){
2894 startingWindow.writeIdentifierToProto(proto, STARTING_WINDOW);
2895 }
2896 proto.write(STARTING_DISPLAYED, startingDisplayed);
2897 proto.write(STARTING_MOVED, startingMoved);
2898 proto.write(HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW,
2899 mHiddenSetFromTransferredStartingWindow);
2900 for (Rect bounds : mFrozenBounds) {
2901 bounds.writeToProto(proto, FROZEN_BOUNDS);
2902 }
Steven Timotiusaf03df62017-07-18 16:56:43 -07002903 proto.end(token);
2904 }
2905
2906 void writeNameToProto(ProtoOutputStream proto, long fieldId) {
2907 if (appToken == null) {
2908 return;
2909 }
2910 try {
2911 proto.write(fieldId, appToken.getName());
2912 } catch (RemoteException e) {
2913 // This shouldn't happen, but in this case fall back to outputting nothing
2914 Slog.e(TAG, e.toString());
2915 }
2916 }
2917
2918 @Override
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002919 public String toString() {
2920 if (stringName == null) {
2921 StringBuilder sb = new StringBuilder();
2922 sb.append("AppWindowToken{");
2923 sb.append(Integer.toHexString(System.identityHashCode(this)));
2924 sb.append(" token="); sb.append(token); sb.append('}');
2925 stringName = sb.toString();
2926 }
Wale Ogunwaleba51ca22016-09-23 06:06:54 -07002927 return stringName + ((mIsExiting) ? " mIsExiting=" : "");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08002928 }
Adrian Roos20e07892018-02-23 19:12:01 +01002929
2930 Rect getLetterboxInsets() {
2931 if (mLetterbox != null) {
2932 return mLetterbox.getInsets();
2933 } else {
2934 return new Rect();
2935 }
2936 }
Adrian Roos23df3a32018-03-15 15:41:13 +01002937
2938 /**
2939 * @eturn true if there is a letterbox and any part of that letterbox overlaps with
2940 * the given {@code rect}.
2941 */
2942 boolean isLetterboxOverlappingWith(Rect rect) {
2943 return mLetterbox != null && mLetterbox.isOverlappingWith(rect);
2944 }
chaviw4ad54912018-05-30 11:05:44 -07002945
2946 /**
2947 * Sets if this AWT is in the process of closing or entering PIP.
2948 * {@link #mWillCloseOrEnterPip}}
2949 */
2950 void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
2951 mWillCloseOrEnterPip = willCloseOrEnterPip;
2952 }
2953
2954 /**
2955 * Returns whether this AWT is considered closing. Conditions are either
2956 * 1. Is this app animating and was requested to be hidden
2957 * 2. App is delayed closing since it might enter PIP.
2958 */
2959 boolean isClosingOrEnteringPip() {
2960 return (isAnimating() && hiddenRequested) || mWillCloseOrEnterPip;
2961 }
Jorim Jaggiaf0d6d22018-06-08 15:25:35 +02002962
2963 /**
2964 * @return Whether we are allowed to show non-starting windows at the moment. We disallow
2965 * showing windows during transitions in case we have windows that have wide-color-gamut
2966 * color mode set to avoid jank in the middle of the transition.
2967 */
2968 boolean canShowWindows() {
2969 return allDrawn && !(isReallyAnimating() && hasNonDefaultColorWindow());
2970 }
2971
2972 /**
2973 * @return true if we have a window that has a non-default color mode set; false otherwise.
2974 */
2975 private boolean hasNonDefaultColorWindow() {
2976 return forAllWindows(ws -> ws.mAttrs.getColorMode() != COLOR_MODE_DEFAULT,
2977 true /* topToBottom */);
2978 }
lumark588a3e82018-07-20 18:53:54 +08002979
2980 void removeFromPendingTransition() {
2981 if (isWaitingForTransitionStart() && mDisplayContent != null) {
2982 mDisplayContent.mOpeningApps.remove(this);
Evan Rosky2289ba12018-11-19 18:28:18 -08002983 mDisplayContent.mChangingApps.remove(this);
lumark588a3e82018-07-20 18:53:54 +08002984 mDisplayContent.mClosingApps.remove(this);
2985 }
2986 }
chaviwdcf76ec2019-01-11 16:48:46 -08002987
2988 private void updateColorTransform() {
2989 if (mSurfaceControl != null && mLastAppSaturationInfo != null) {
2990 mPendingTransaction.setColorTransform(mSurfaceControl, mLastAppSaturationInfo.mMatrix,
2991 mLastAppSaturationInfo.mTranslation);
2992 mWmService.scheduleAnimationLocked();
2993 }
2994 }
2995
2996 private static class AppSaturationInfo {
2997 float[] mMatrix = new float[9];
2998 float[] mTranslation = new float[3];
2999
3000 void setSaturation(@Size(9) float[] matrix, @Size(3) float[] translation) {
3001 System.arraycopy(matrix, 0, mMatrix, 0, mMatrix.length);
3002 System.arraycopy(translation, 0, mTranslation, 0, mTranslation.length);
3003 }
3004 }
Jeff Browne9bdb312012-04-05 15:30:10 -07003005}