blob: 80a295d8f0ad438931428b5af60c5426af5c7f4f [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 Ogunwaleda8b8272018-11-29 19:37:37 -080024import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
25import static android.content.pm.ActivityInfo.FLAG_INHERIT_SHOW_WHEN_LOCKED;
26import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
27import static android.content.pm.ActivityInfo.FLAG_TURN_SCREEN_ON;
28import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
29import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -070030import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
Wale Ogunwale51362492016-09-08 17:49:17 -070031import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -080032import static android.os.Build.VERSION_CODES.HONEYCOMB;
Jorim Jaggif5f9e122017-10-24 18:21:09 +020033import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
Jorim Jaggife762342016-10-13 14:33:27 +020034import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
Jorim Jaggid635a4a2017-05-03 15:21:26 +020035import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080036import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
Jorim Jaggife762342016-10-13 14:33:27 +020037import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
Wale Ogunwaled1c37912016-08-16 03:19:39 -070038import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080039import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -070040import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -080041import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
Evan Rosky2289ba12018-11-19 18:28:18 -080042import static android.view.WindowManager.TRANSIT_TASK_CHANGE_WINDOWING_MODE;
Louis Chang37317152019-05-09 09:53:58 +080043import static android.view.WindowManager.TRANSIT_TASK_OPEN_BEHIND;
chaviw9c81e632018-07-31 11:17:52 -070044import static android.view.WindowManager.TRANSIT_UNSET;
Jorim Jaggic6976f02018-04-18 16:31:07 +020045import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
chaviw9c81e632018-07-31 11:17:52 -070046
Adrian Roose99bc052017-11-20 17:55:31 +010047import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
48import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070049import static com.android.server.wm.AppWindowTokenProto.ALL_DRAWN;
50import static com.android.server.wm.AppWindowTokenProto.APP_STOPPED;
51import static com.android.server.wm.AppWindowTokenProto.CLIENT_HIDDEN;
52import static com.android.server.wm.AppWindowTokenProto.DEFER_HIDING_CLIENT;
53import static com.android.server.wm.AppWindowTokenProto.FILLS_PARENT;
54import static com.android.server.wm.AppWindowTokenProto.FROZEN_BOUNDS;
55import static com.android.server.wm.AppWindowTokenProto.HIDDEN_REQUESTED;
56import static com.android.server.wm.AppWindowTokenProto.HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW;
57import static com.android.server.wm.AppWindowTokenProto.IS_REALLY_ANIMATING;
58import static com.android.server.wm.AppWindowTokenProto.IS_WAITING_FOR_TRANSITION_START;
59import static com.android.server.wm.AppWindowTokenProto.LAST_ALL_DRAWN;
60import static com.android.server.wm.AppWindowTokenProto.LAST_SURFACE_SHOWING;
61import static com.android.server.wm.AppWindowTokenProto.NAME;
62import static com.android.server.wm.AppWindowTokenProto.NUM_DRAWN_WINDOWS;
63import static com.android.server.wm.AppWindowTokenProto.NUM_INTERESTING_WINDOWS;
64import static com.android.server.wm.AppWindowTokenProto.REMOVED;
65import static com.android.server.wm.AppWindowTokenProto.REPORTED_DRAWN;
66import static com.android.server.wm.AppWindowTokenProto.REPORTED_VISIBLE;
67import static com.android.server.wm.AppWindowTokenProto.STARTING_DISPLAYED;
68import static com.android.server.wm.AppWindowTokenProto.STARTING_MOVED;
69import static com.android.server.wm.AppWindowTokenProto.STARTING_WINDOW;
70import static com.android.server.wm.AppWindowTokenProto.THUMBNAIL;
71import static com.android.server.wm.AppWindowTokenProto.WINDOW_TOKEN;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -080072import static com.android.server.wm.IdentifierProto.HASH_CODE;
73import static com.android.server.wm.IdentifierProto.TITLE;
74import static com.android.server.wm.IdentifierProto.USER_ID;
Adrian Roosb125e0b2019-10-02 14:55:14 +020075import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
76import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
77import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
78import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
79import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
80import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
chaviw9c81e632018-07-31 11:17:52 -070081import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
chaviw9c81e632018-07-31 11:17:52 -070082import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
chaviw9c81e632018-07-31 11:17:52 -070083import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
chaviw9c81e632018-07-31 11:17:52 -070084import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
chaviw9c81e632018-07-31 11:17:52 -070085import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
86import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
87import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN;
88import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
89import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
90import static com.android.server.wm.WindowManagerService.logWithStack;
chaviw15ad49f2019-04-24 15:05:39 -070091import static com.android.server.wm.WindowState.LEGACY_POLICY_VISIBILITY;
Jorim Jaggi6ec52d42019-07-03 15:45:59 +020092import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
Vishnu Naira2977262018-07-26 13:31:26 -070093import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
Evan Rosky641daea2019-04-24 14:45:24 -070094import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080095
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070096import android.annotation.CallSuper;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -080097import android.annotation.Nullable;
chaviwdcf76ec2019-01-11 16:48:46 -080098import android.annotation.Size;
Jorim Jaggid635a4a2017-05-03 15:21:26 +020099import android.app.Activity;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800100import android.app.ActivityManager;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800101import android.app.ActivityOptions;
Winson Chung48b25652018-10-22 14:04:30 -0700102import android.content.ComponentName;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800103import android.content.Intent;
104import android.content.pm.ActivityInfo;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800105import android.content.res.CompatibilityInfo;
Jorim Jaggi26c8c422016-05-09 19:57:25 -0700106import android.content.res.Configuration;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800107import android.content.res.Resources;
Jorim Jaggi988f6682017-11-17 17:46:43 +0100108import android.graphics.GraphicBuffer;
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -0700109import android.graphics.PixelFormat;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200110import android.graphics.Point;
Jorim Jaggi0429f352015-12-22 16:29:16 +0100111import android.graphics.Rect;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700112import android.os.Binder;
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800113import android.os.Build;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800114import android.os.Debug;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700115import android.os.IBinder;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800116import android.os.SystemClock;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200117import android.os.Trace;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800118import android.os.UserHandle;
Evan Rosky2289ba12018-11-19 18:28:18 -0800119import android.util.ArraySet;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800120import android.util.Slog;
Steven Timotiusaf03df62017-07-18 16:56:43 -0700121import android.util.proto.ProtoOutputStream;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200122import android.view.DisplayInfo;
Robert Carr788f5742018-07-30 17:46:45 -0700123import android.view.InputApplicationHandle;
Evan Rosky966759f2019-01-15 10:33:58 -0800124import android.view.RemoteAnimationAdapter;
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100125import android.view.RemoteAnimationDefinition;
Robert Carr6914f082017-03-20 19:04:30 -0700126import android.view.SurfaceControl;
Tony Mak64b8d562017-12-28 17:44:02 +0000127import android.view.SurfaceControl.Transaction;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800128import android.view.WindowManager;
Jorim Jaggi87fdbcb2017-08-17 13:41:11 +0200129import android.view.WindowManager.LayoutParams;
Tony Mak64b8d562017-12-28 17:44:02 +0000130import android.view.animation.Animation;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800131
Tony Mak64b8d562017-12-28 17:44:02 +0000132import com.android.internal.R;
Riddle Hsua118b3a2018-10-11 22:05:06 +0800133import com.android.internal.annotations.VisibleForTesting;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800134import com.android.internal.util.ToBooleanFunction;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800135import com.android.server.AttributeCache;
chaviwdcf76ec2019-01-11 16:48:46 -0800136import com.android.server.LocalServices;
Christine Franks0ada2772019-02-25 13:54:57 -0800137import com.android.server.display.color.ColorDisplayService;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800138import com.android.server.policy.WindowManagerPolicy;
Adrian Roose99bc052017-11-20 17:55:31 +0100139import com.android.server.policy.WindowManagerPolicy.StartingSurface;
Adrian Roosb125e0b2019-10-02 14:55:14 +0200140import com.android.server.protolog.common.ProtoLog;
Evan Rosky2289ba12018-11-19 18:28:18 -0800141import com.android.server.wm.RemoteAnimationController.RemoteAnimationRecord;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800142import com.android.server.wm.WindowManagerService.H;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800143
144import java.io.PrintWriter;
chaviwdcf76ec2019-01-11 16:48:46 -0800145import java.lang.ref.WeakReference;
Jorim Jaggi0429f352015-12-22 16:29:16 +0100146import java.util.ArrayDeque;
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800147import java.util.ArrayList;
lumark588a3e82018-07-20 18:53:54 +0800148import java.util.function.Consumer;
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800149
150class AppTokenList extends ArrayList<AppWindowToken> {
151}
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800152
153/**
154 * Version of WindowToken that is specifically for a particular application (or
155 * really activity) that is displaying windows.
156 */
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800157// TODO: Fully merge this class into ActivityRecord class since they are really the same thing...
158class AppWindowToken extends WindowToken implements WindowManagerService.AppFreezeListener {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800159 private static final String TAG = TAG_WITH_CLASS_NAME ? "AppWindowToken" : TAG_WM;
160
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100161 /**
162 * Value to increment the z-layer when boosting a layer during animations. BOOST in l33tsp34k.
163 */
Jorim Jaggi9cd99132019-04-24 17:41:35 +0200164 @VisibleForTesting static final int Z_BOOST_BASE = 800570000;
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100165
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800166 final ActivityTaskManagerService mAtmService;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800167 // Non-null only for application tokens.
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800168 // TODO: rename to mActivityToken
169 final ActivityRecord.Token appToken;
170 // All about me
171 final ActivityInfo mActivityInfo;
172 // Which user is this running for?
173 final int mUserId;
174 // The package implementing intent's component
175 // TODO: rename to mPackageName
176 final String packageName;
177 // the intent component, or target of an alias.
Winson Chung48b25652018-10-22 14:04:30 -0700178 final ComponentName mActivityComponent;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800179 boolean mVoiceInteraction;
Dianne Hackborne30e02f2014-05-27 18:24:45 -0700180
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -0700181 /**
182 * The activity is opaque and fills the entire space of this task.
183 * @see WindowContainer#fillsParent()
184 */
185 private boolean mOccludesParent;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800186 // Has a wallpaper window as a background.
187 // TODO: Rename to mHasWallpaper and also see if it possible to combine this with the
188 // mOccludesParent field.
189 final boolean hasWallpaper;
190 // activity is not displayed?
191 // TODO: rename to mNoDisplay
192 @VisibleForTesting
193 boolean noDisplay;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800194 boolean mShowForAllUsers;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800195 // TODO: Make this final
Wale Ogunwale72919d22016-12-08 18:58:50 -0800196 int mTargetSdk;
Craig Mautnera2c77052012-03-26 12:14:43 -0700197
Bryce Lee6d410262017-02-28 15:30:17 -0800198 // Flag set while reparenting to prevent actions normally triggered by an individual parent
199 // change.
200 private boolean mReparenting;
201
Wale Ogunwalee287e192017-04-21 09:30:12 -0700202 // True if we are current in the process of removing this app token from the display
203 private boolean mRemovingFromDisplay = false;
204
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800205 // The input dispatching timeout for this application token in nanoseconds.
Wale Ogunwale72919d22016-12-08 18:58:50 -0800206 long mInputDispatchingTimeoutNanos;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800207
208 // These are used for determining when all windows associated with
209 // an activity have been drawn, so they can be made visible together
210 // at the same time.
Craig Mautner764983d2012-03-22 11:37:36 -0700211 // initialize so that it doesn't match mTransactionSequence which is an int.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700212 private long mLastTransactionSequence = Long.MIN_VALUE;
213 private int mNumInterestingWindows;
214 private int mNumDrawnWindows;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800215 boolean inPendingTransaction;
216 boolean allDrawn;
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000217 private boolean mLastAllDrawn;
Tiger Huangc9d0d002019-05-29 22:55:29 +0800218 private boolean mUseTransferredAnimation;
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000219
Craig Mautner7636dfb2012-11-16 15:24:11 -0800220 // Set to true when this app creates a surface while in the middle of an animation. In that
221 // case do not clear allDrawn until the animation completes.
222 boolean deferClearAllDrawn;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800223
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800224 // Is this window's surface needed? This is almost like hidden, except
225 // it will sometimes be true a little earlier: when the token has
226 // been shown, but is still waiting for its app transition to execute
227 // before making its windows shown.
228 boolean hiddenRequested;
229
230 // Have we told the window clients to hide themselves?
Wale Ogunwale89973222017-04-23 18:39:45 -0700231 private boolean mClientHidden;
232
233 // If true we will defer setting mClientHidden to true and reporting to the client that it is
234 // hidden.
235 boolean mDeferHidingClient;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800236
237 // Last visibility state we reported to the app token.
238 boolean reportedVisible;
239
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700240 // Last drawn state we reported to the app token.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700241 private boolean reportedDrawn;
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700242
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800243 // Set to true when the token has been removed from the window mgr.
244 boolean removed;
245
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800246 // Information about an application starting window if displayed.
Tarandeep Singh69ab1042019-07-30 13:30:03 -0700247 // Note: these are de-referenced before the starting window animates away.
chaviwa8f07a72019-05-01 16:25:39 -0700248 StartingData mStartingData;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800249 WindowState startingWindow;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800250 StartingSurface startingSurface;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800251 boolean startingDisplayed;
252 boolean startingMoved;
Jorim Jaggi60f9c972018-02-01 19:21:07 +0100253
Wale Ogunwale6c459212017-05-17 08:56:03 -0700254 // True if the hidden state of this token was forced to false due to a transferred starting
255 // window.
256 private boolean mHiddenSetFromTransferredStartingWindow;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800257 boolean firstWindowDrawn;
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700258 private final WindowState.UpdateReportedVisibilityResults mReportedVisibilityResults =
259 new WindowState.UpdateReportedVisibilityResults();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800260
261 // Input application handle used by the input dispatcher.
Jeff Brown9302c872011-07-13 22:51:29 -0700262 final InputApplicationHandle mInputApplicationHandle;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800263
Wale Ogunwale571771c2016-08-26 13:18:50 -0700264 // TODO: Have a WindowContainer state for tracking exiting/deferred removal.
Craig Mautner799bc1d2015-01-14 10:33:48 -0800265 boolean mIsExiting;
Craig Mautner9ef471f2014-02-07 13:11:47 -0800266
Craig Mautnerbb742462014-07-07 15:28:55 -0700267 boolean mLaunchTaskBehind;
Craig Mautner8746a472014-07-24 15:12:54 -0700268 boolean mEnteringAnimation;
Craig Mautnerbb742462014-07-07 15:28:55 -0700269
Robert Carre12aece2016-02-02 22:43:27 -0800270 boolean mAppStopped;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800271 // A hint to override the window specified rotation animation, or -1 to use the window specified
272 // value. We use this so that we can select the right animation in the cases of starting
273 // windows, where the app hasn't had time to set a value on the window.
274 int mRotationAnimationHint = -1;
275
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -0700276 private int mPendingRelaunchCount;
Robert Carre12aece2016-02-02 22:43:27 -0800277
Jorim Jaggife762342016-10-13 14:33:27 +0200278 private boolean mLastContainsShowWhenLockedWindow;
279 private boolean mLastContainsDismissKeyguardWindow;
280
Jorim Jaggi0429f352015-12-22 16:29:16 +0100281 ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
Jorim Jaggi26c8c422016-05-09 19:57:25 -0700282 ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
Jorim Jaggi0429f352015-12-22 16:29:16 +0100283
Riddle Hsub398da32019-01-21 21:48:16 +0800284 /**
285 * The scale to fit at least one side of the activity to its parent. If the activity uses
286 * 1920x1080, and the actually size on the screen is 960x540, then the scale is 0.5.
287 */
288 private float mSizeCompatScale = 1f;
289 /**
290 * The bounds in global coordinates for activity in size compatibility mode.
291 * @see ActivityRecord#inSizeCompatMode
292 */
293 private Rect mSizeCompatBounds;
294
Wale Ogunwale6c459212017-05-17 08:56:03 -0700295 private boolean mDisablePreviewScreenshots;
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +0100296
Wale Ogunwale034a8ec2017-09-02 17:14:40 -0700297 private Task mLastParent;
Robert Carred3e83b2017-04-21 13:26:55 -0700298
chaviwd3bf08d2017-08-01 17:24:59 -0700299 /**
Riddle Hsu4bb06be2019-07-02 01:03:07 +0800300 * @see #currentLaunchCanTurnScreenOn()
chaviwd3bf08d2017-08-01 17:24:59 -0700301 */
Riddle Hsu4bb06be2019-07-02 01:03:07 +0800302 private boolean mCurrentLaunchCanTurnScreenOn = true;
chaviwd3bf08d2017-08-01 17:24:59 -0700303
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200304 /**
305 * If we are running an animation, this determines the transition type. Must be one of
306 * AppTransition.TRANSIT_* constants.
307 */
308 private int mTransit;
309
310 /**
311 * If we are running an animation, this determines the flags during this animation. Must be a
312 * bitwise combination of AppTransition.TRANSIT_FLAG_* constants.
313 */
314 private int mTransitFlags;
315
316 /** Whether our surface was set to be showing in the last call to {@link #prepareSurfaces} */
Jorim Jaggifd1891462017-12-29 15:41:36 +0100317 private boolean mLastSurfaceShowing = true;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200318
Evan Rosky2289ba12018-11-19 18:28:18 -0800319 /**
320 * This gets used during some open/close transitions as well as during a change transition
321 * where it represents the starting-state snapshot.
322 */
Jorim Jaggi988f6682017-11-17 17:46:43 +0100323 private AppWindowThumbnail mThumbnail;
Evan Rosky2289ba12018-11-19 18:28:18 -0800324 private final Rect mTransitStartRect = new Rect();
325
326 /**
327 * This leash is used to "freeze" the app surface in place after the state change, but before
328 * the animation is ready to start.
329 */
330 private SurfaceControl mTransitChangeLeash = null;
Jorim Jaggi988f6682017-11-17 17:46:43 +0100331
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000332 /** Have we been asked to have this token keep the screen frozen? */
333 private boolean mFreezingScreen;
334
335 /** Whether this token should be boosted at the top of all app window tokens. */
Jorim Jaggi9cd99132019-04-24 17:41:35 +0200336 @VisibleForTesting boolean mNeedsZBoost;
Adrian Roos4d18a2e2017-12-19 19:08:05 +0100337 private Letterbox mLetterbox;
Jorim Jaggib0fc8172017-11-23 17:04:08 +0000338
chaviw23ee71c2017-12-18 11:29:41 -0800339 private final Point mTmpPoint = new Point();
chaviw23012112017-12-20 15:29:04 -0800340 private final Rect mTmpRect = new Rect();
Evan Rosky2289ba12018-11-19 18:28:18 -0800341 private final Rect mTmpPrevBounds = new Rect();
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100342 private RemoteAnimationDefinition mRemoteAnimationDefinition;
Jorim Jaggi6de61012018-03-19 14:53:23 +0100343 private AnimatingAppWindowTokenRegistry mAnimatingAppWindowTokenRegistry;
chaviw23ee71c2017-12-18 11:29:41 -0800344
chaviw4ad54912018-05-30 11:05:44 -0700345 /**
346 * A flag to determine if this AWT is in the process of closing or entering PIP. This is needed
347 * to help AWT know that the app is in the process of closing but hasn't yet started closing on
348 * the WM side.
349 */
350 private boolean mWillCloseOrEnterPip;
351
Vishnu Naira2977262018-07-26 13:31:26 -0700352 /** Layer used to constrain the animation to a token's stack bounds. */
353 SurfaceControl mAnimationBoundsLayer;
354
355 /** Whether this token needs to create mAnimationBoundsLayer for cropping animations. */
356 boolean mNeedsAnimationBoundsLayer;
357
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800358 private static final int STARTING_WINDOW_TYPE_NONE = 0;
359 private static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
360 private static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
361
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800362 private boolean mShowWhenLocked;
363 private boolean mInheritShownWhenLocked;
364 private boolean mTurnScreenOn;
365
chaviwdcf76ec2019-01-11 16:48:46 -0800366 private AppSaturationInfo mLastAppSaturationInfo;
367
368 private final ColorDisplayService.ColorTransformController mColorTransformController =
369 (matrix, translation) -> mWmService.mH.post(() -> {
370 synchronized (mWmService.mGlobalLock) {
371 if (mLastAppSaturationInfo == null) {
372 mLastAppSaturationInfo = new AppSaturationInfo();
373 }
374
375 mLastAppSaturationInfo.setSaturation(matrix, translation);
376 updateColorTransform();
377 }
378 });
379
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800380 AppWindowToken(WindowManagerService service, ActivityTaskManagerService atm,
381 ActivityRecord.Token token, ActivityInfo aInfo, ActivityOptions options, Intent intent,
382 DisplayContent dc) {
383 super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true, dc,
384 false /* ownerCanManageAppTokens */);
385 mAtmService = atm;
386 appToken = token;
387 mActivityInfo = aInfo;
388 mUserId = UserHandle.getUserId(mActivityInfo.applicationInfo.uid);
389 packageName = mActivityInfo.applicationInfo.packageName;
390 mInputApplicationHandle = new InputApplicationHandle(appToken);
391
392 // If the class name in the intent doesn't match that of the target, this is probably an
393 // alias. We have to create a new ComponentName object to keep track of the real activity
394 // name, so that FLAG_ACTIVITY_CLEAR_TOP is handled properly.
395 if (mActivityInfo.targetActivity == null
396 || (mActivityInfo.targetActivity.equals(intent.getComponent().getClassName())
397 && (mActivityInfo.launchMode == LAUNCH_MULTIPLE
398 || mActivityInfo.launchMode == LAUNCH_SINGLE_TOP))) {
399 mActivityComponent = intent.getComponent();
400 } else {
401 mActivityComponent =
402 new ComponentName(mActivityInfo.packageName, mActivityInfo.targetActivity);
403 }
404
405 mTargetSdk = mActivityInfo.applicationInfo.targetSdkVersion;
406 mShowForAllUsers = (mActivityInfo.flags & FLAG_SHOW_FOR_ALL_USERS) != 0;
407 setOrientation(mActivityInfo.screenOrientation);
408 mRotationAnimationHint = mActivityInfo.rotationAnimation;
409
410 mShowWhenLocked = (aInfo.flags & ActivityInfo.FLAG_SHOW_WHEN_LOCKED) != 0;
411 mInheritShownWhenLocked = (aInfo.privateFlags & FLAG_INHERIT_SHOW_WHEN_LOCKED) != 0;
412 mTurnScreenOn = (aInfo.flags & FLAG_TURN_SCREEN_ON) != 0;
413
414 int realTheme = mActivityInfo.getThemeResource();
415 if (realTheme == Resources.ID_NULL) {
416 realTheme = aInfo.applicationInfo.targetSdkVersion < HONEYCOMB
417 ? android.R.style.Theme : android.R.style.Theme_Holo;
418 }
419
420 final AttributeCache.Entry ent = AttributeCache.instance().get(packageName,
421 realTheme, com.android.internal.R.styleable.Window, mUserId);
422
423 if (ent != null) {
424 mOccludesParent = !ActivityInfo.isTranslucentOrFloating(ent.array);
425 hasWallpaper = ent.array.getBoolean(R.styleable.Window_windowShowWallpaper, false);
426 noDisplay = ent.array.getBoolean(R.styleable.Window_windowNoDisplay, false);
427 } else {
428 hasWallpaper = false;
429 noDisplay = false;
430 }
431
432 if (options != null) {
433 mLaunchTaskBehind = options.getLaunchTaskBehind();
434
435 final int rotationAnimation = options.getRotationAnimationHint();
436 // Only override manifest supplied option if set.
437 if (rotationAnimation >= 0) {
438 mRotationAnimationHint = rotationAnimation;
439 }
440 }
Wale Ogunwale72919d22016-12-08 18:58:50 -0800441
442 // Application tokens start out hidden.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200443 setHidden(true);
Wale Ogunwale72919d22016-12-08 18:58:50 -0800444 hiddenRequested = true;
chaviwdcf76ec2019-01-11 16:48:46 -0800445
446 ColorDisplayService.ColorDisplayServiceInternal cds = LocalServices.getService(
447 ColorDisplayService.ColorDisplayServiceInternal.class);
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800448 cds.attachColorTransformController(packageName, mUserId,
chaviwdcf76ec2019-01-11 16:48:46 -0800449 new WeakReference<>(mColorTransformController));
Wale Ogunwale72919d22016-12-08 18:58:50 -0800450 }
451
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800452 void onAttachToTask(boolean voiceInteraction, DisplayContent dc,
453 long inputDispatchingTimeoutNanos) {
454 mInputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800455 mVoiceInteraction = voiceInteraction;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800456 onDisplayChanged(dc);
457
458 // Application tokens start out hidden.
459 setHidden(true);
460 hiddenRequested = true;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800461 }
462
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800463 void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
464 firstWindowDrawn = true;
465
466 // We now have a good window to show, remove dead placeholders
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700467 removeDeadWindows();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800468
Jorim Jaggi02886a82016-12-06 09:10:06 -0800469 if (startingWindow != null) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200470 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Finish starting %s"
471 + ": first real window is shown, no animation", win.mToken);
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800472 // If this initial window is animating, stop it -- we will do an animation to reveal
473 // it from behind the starting window, so there is no need for it to also be doing its
474 // own stuff.
Jorim Jaggia5e10572017-11-15 14:36:26 +0100475 win.cancelAnimation();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800476 }
chaviwa8f07a72019-05-01 16:25:39 -0700477 removeStartingWindow();
Wale Ogunwale9017ec02016-02-25 08:55:25 -0800478 updateReportedVisibilityLocked();
479 }
480
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800481 void updateReportedVisibilityLocked() {
482 if (appToken == null) {
483 return;
484 }
485
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700486 if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700487 final int count = mChildren.size();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800488
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700489 mReportedVisibilityResults.reset();
490
491 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700492 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700493 win.updateReportedVisibility(mReportedVisibilityResults);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800494 }
495
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700496 int numInteresting = mReportedVisibilityResults.numInteresting;
497 int numVisible = mReportedVisibilityResults.numVisible;
498 int numDrawn = mReportedVisibilityResults.numDrawn;
499 boolean nowGone = mReportedVisibilityResults.nowGone;
500
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700501 boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200502 boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting && !isHidden();
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700503 if (!nowGone) {
504 // If the app is not yet gone, then it can only become visible/drawn.
505 if (!nowDrawn) {
506 nowDrawn = reportedDrawn;
507 }
508 if (!nowVisible) {
509 nowVisible = reportedVisible;
510 }
511 }
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800512 if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800513 + numInteresting + " visible=" + numVisible);
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700514 if (nowDrawn != reportedDrawn) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800515 onWindowsDrawn(nowDrawn, SystemClock.uptimeMillis());
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -0700516 reportedDrawn = nowDrawn;
517 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800518 if (nowVisible != reportedVisible) {
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700519 if (DEBUG_VISIBILITY) Slog.v(TAG,
520 "Visibility changed in " + this + ": vis=" + nowVisible);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800521 reportedVisible = nowVisible;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800522 if (nowVisible) {
523 onWindowsVisible();
524 } else {
525 onWindowsGone();
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800526 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800527 }
528 }
529
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800530 // Mostly implemented in ActivityRecord.
531 void onWindowsDrawn(boolean drawn, long timestamp) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800532 }
533
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800534 // Mostly implemented in ActivityRecord. Keeping here for the logpoint.
535 void onWindowsGone() {
536 if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting gone in " + appToken);
537 }
538
539 // Mostly implemented in ActivityRecord. Keeping here for the logpoint.
540 void onWindowsVisible() {
541 if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting visible in " + appToken);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800542 }
543
Wale Ogunwale89973222017-04-23 18:39:45 -0700544 boolean isClientHidden() {
545 return mClientHidden;
546 }
547
548 void setClientHidden(boolean hideClient) {
549 if (mClientHidden == hideClient || (hideClient && mDeferHidingClient)) {
550 return;
551 }
Adrian Roosb125e0b2019-10-02 14:55:14 +0200552 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
553 "setClientHidden: %s clientHidden=%b Callers=%s", this, hideClient,
554 Debug.getCallers(5));
Wale Ogunwale89973222017-04-23 18:39:45 -0700555 mClientHidden = hideClient;
556 sendAppVisibilityToClients();
557 }
558
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800559 void setVisibility(boolean visible, boolean deferHidingClient) {
560 final AppTransition appTransition = getDisplayContent().mAppTransition;
561
562 // Don't set visibility to false if we were already not visible. This prevents WM from
563 // adding the app to the closing app list which doesn't make sense for something that is
564 // already not visible. However, set visibility to true even if we are already visible.
565 // This makes sure the app is added to the opening apps list so that the right
566 // transition can be selected.
567 // TODO: Probably a good idea to separate the concept of opening/closing apps from the
568 // concept of setting visibility...
569 if (!visible && hiddenRequested) {
570
571 if (!deferHidingClient && mDeferHidingClient) {
572 // We previously deferred telling the client to hide itself when visibility was
573 // initially set to false. Now we would like it to hide, so go ahead and set it.
574 mDeferHidingClient = deferHidingClient;
575 setClientHidden(true);
576 }
577 return;
578 }
579
Adrian Roosb125e0b2019-10-02 14:55:14 +0200580 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
581 "setAppVisibility(%s, visible=%b): %s hidden=%b hiddenRequested=%b Callers=%s",
582 appToken, visible, appTransition, isHidden(), hiddenRequested,
583 Debug.getCallers(6));
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800584
585 final DisplayContent displayContent = getDisplayContent();
586 displayContent.mOpeningApps.remove(this);
587 displayContent.mClosingApps.remove(this);
Evan Roskyb1e75f72019-04-26 20:23:26 -0700588 if (isInChangeTransition()) {
589 clearChangeLeash(getPendingTransaction(), true /* cancel */);
590 }
591 displayContent.mChangingApps.remove(this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800592 waitingToShow = false;
593 hiddenRequested = !visible;
594 mDeferHidingClient = deferHidingClient;
595
596 if (!visible) {
597 // If the app is dead while it was visible, we kept its dead window on screen.
598 // Now that the app is going invisible, we can remove it. It will be restarted
599 // if made visible again.
600 removeDeadWindows();
601 } else {
602 if (!appTransition.isTransitionSet()
603 && appTransition.isReady()) {
604 // Add the app mOpeningApps if transition is unset but ready. This means
605 // we're doing a screen freeze, and the unfreeze will wait for all opening
606 // apps to be ready.
607 displayContent.mOpeningApps.add(this);
608 }
609 startingMoved = false;
610 // If the token is currently hidden (should be the common case), or has been
611 // stopped, then we need to set up to wait for its windows to be ready.
612 if (isHidden() || mAppStopped) {
613 clearAllDrawn();
614
615 // If the app was already visible, don't reset the waitingToShow state.
616 if (isHidden()) {
617 waitingToShow = true;
Jorim Jaggi6ec52d42019-07-03 15:45:59 +0200618
wilsonshih78e55422019-09-10 09:44:51 +0800619 // If the client isn't hidden, we don't need to reset the drawing state.
620 if (isClientHidden()) {
621 // Let's reset the draw state in order to prevent the starting window to be
622 // immediately dismissed when the app still has the surface.
623 forAllWindows(w -> {
624 if (w.mWinAnimator.mDrawState == HAS_DRAWN) {
625 w.mWinAnimator.resetDrawState();
Jorim Jaggi6ec52d42019-07-03 15:45:59 +0200626
wilsonshih78e55422019-09-10 09:44:51 +0800627 // Force add to mResizingWindows, so that we are guaranteed to get
628 // another reportDrawn callback.
629 w.resetLastContentInsets();
630 }
631 }, true /* traverseTopToBottom */);
632 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800633 }
634 }
635
636 // In the case where we are making an app visible but holding off for a transition,
637 // we still need to tell the client to make its windows visible so they get drawn.
638 // Otherwise, we will wait on performing the transition until all windows have been
639 // drawn, they never will be, and we are sad.
640 setClientHidden(false);
641
642 requestUpdateWallpaperIfNeeded();
643
Adrian Roosb125e0b2019-10-02 14:55:14 +0200644 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "No longer Stopped: %s", this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800645 mAppStopped = false;
646
647 transferStartingWindowFromHiddenAboveTokenIfNeeded();
648 }
649
650 // If we are preparing an app transition, then delay changing
651 // the visibility of this token until we execute that transition.
652 if (okToAnimate() && appTransition.isTransitionSet()) {
653 inPendingTransaction = true;
654 if (visible) {
655 displayContent.mOpeningApps.add(this);
656 mEnteringAnimation = true;
657 } else {
658 displayContent.mClosingApps.add(this);
659 mEnteringAnimation = false;
660 }
Louis Chang37317152019-05-09 09:53:58 +0800661 if (appTransition.getAppTransition() == TRANSIT_TASK_OPEN_BEHIND) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800662 // We're launchingBehind, add the launching activity to mOpeningApps.
663 final WindowState win = getDisplayContent().findFocusedWindow();
664 if (win != null) {
665 final AppWindowToken focusedToken = win.mAppToken;
666 if (focusedToken != null) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200667 ProtoLog.d(WM_DEBUG_APP_TRANSITIONS,
668 "TRANSIT_TASK_OPEN_BEHIND, adding %s to mOpeningApps",
669 focusedToken);
670
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800671 // Force animation to be loaded.
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800672 displayContent.mOpeningApps.add(focusedToken);
673 }
674 }
675 }
676 return;
677 }
678
679 commitVisibility(null, visible, TRANSIT_UNSET, true, mVoiceInteraction);
680 updateReportedVisibilityLocked();
681 }
682
683 boolean commitVisibility(WindowManager.LayoutParams lp,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700684 boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
685
686 boolean delayed = false;
687 inPendingTransaction = false;
Wale Ogunwale9e4721f2017-05-23 19:37:30 -0700688 // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually
689 // been set by the app now.
690 mHiddenSetFromTransferredStartingWindow = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700691
692 // Allow for state changes and animation to be applied if:
693 // * token is transitioning visibility state
694 // * or the token was marked as hidden and is exiting before we had a chance to play the
695 // transition animation
Louis Chang37317152019-05-09 09:53:58 +0800696 // * or this is an opening app and windows are being replaced
697 // * or the token is the opening app and visible while opening task behind existing one.
698 final DisplayContent displayContent = getDisplayContent();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700699 boolean visibilityChanged = false;
Louis Chang37317152019-05-09 09:53:58 +0800700 if (isHidden() == visible || (isHidden() && mIsExiting)
701 || (visible && waitingForReplacement())
702 || (visible && displayContent.mOpeningApps.contains(this)
703 && displayContent.mAppTransition.getAppTransition() == TRANSIT_TASK_OPEN_BEHIND)) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800704 final AccessibilityController accessibilityController =
705 mWmService.mAccessibilityController;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700706 boolean changed = false;
Adrian Roosb125e0b2019-10-02 14:55:14 +0200707 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
708 "Changing app %s hidden=%b performLayout=%b", this, isHidden(),
709 performLayout);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700710
711 boolean runningAppAnimation = false;
712
Jorim Jaggif84e2f62018-01-16 14:17:59 +0100713 if (transit != WindowManager.TRANSIT_UNSET) {
Tiger Huangc9d0d002019-05-29 22:55:29 +0800714 if (mUseTransferredAnimation) {
715 runningAppAnimation = isReallyAnimating();
716 } else if (applyAnimationLocked(lp, transit, visible, isVoiceInteraction)) {
717 runningAppAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700718 }
Tiger Huangc9d0d002019-05-29 22:55:29 +0800719 delayed = runningAppAnimation;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700720 final WindowState window = findMainWindow();
Rhed Jao02655dc2018-10-30 20:44:52 +0800721 if (window != null && accessibilityController != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700722 accessibilityController.onAppWindowTransitionLocked(window, transit);
723 }
724 changed = true;
725 }
726
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700727 final int windowsCount = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700728 for (int i = 0; i < windowsCount; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700729 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700730 changed |= win.onAppVisibilityChanged(visible, runningAppAnimation);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700731 }
732
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200733 setHidden(!visible);
734 hiddenRequested = !visible;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700735 visibilityChanged = true;
736 if (!visible) {
737 stopFreezingScreen(true, true);
738 } else {
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700739 // If we are being set visible, and the starting window is not yet displayed,
740 // then make sure it doesn't get displayed.
741 if (startingWindow != null && !startingWindow.isDrawnLw()) {
chaviw15ad49f2019-04-24 15:05:39 -0700742 startingWindow.clearPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY);
743 startingWindow.mLegacyPolicyVisibilityAfterAnim = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700744 }
Jorim Jaggi38d44ec2017-06-14 16:04:59 -0700745
746 // We are becoming visible, so better freeze the screen with the windows that are
747 // getting visible so we also wait for them.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800748 forAllWindows(mWmService::makeWindowFreezingScreenIfNeededLocked, true);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700749 }
750
Adrian Roosb125e0b2019-10-02 14:55:14 +0200751 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
752 "commitVisibility: %s: hidden=%b hiddenRequested=%b", this,
753 isHidden(), hiddenRequested);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700754
755 if (changed) {
Louis Chang37317152019-05-09 09:53:58 +0800756 displayContent.getInputMonitor().setUpdateInputWindowsNeededLw();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700757 if (performLayout) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800758 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700759 false /*updateInputWindows*/);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800760 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700761 }
Louis Chang37317152019-05-09 09:53:58 +0800762 displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700763 }
764 }
Tiger Huangc9d0d002019-05-29 22:55:29 +0800765 mUseTransferredAnimation = false;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700766
lumarkd14173e2019-03-27 19:14:33 +0800767 if (isReallyAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700768 delayed = true;
Jorim Jaggiab9fcb22018-03-15 23:46:12 +0100769 } else {
770
771 // We aren't animating anything, but exiting windows rely on the animation finished
772 // callback being called in case the AppWindowToken was pretending to be animating,
773 // which we might have done because we were in closing/opening apps list.
774 onAnimationFinished();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700775 }
776
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700777 for (int i = mChildren.size() - 1; i >= 0 && !delayed; i--) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100778 if ((mChildren.get(i)).isSelfOrChildAnimating()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700779 delayed = true;
780 }
781 }
782
783 if (visibilityChanged) {
784 if (visible && !delayed) {
785 // The token was made immediately visible, there will be no entrance animation.
786 // We need to inform the client the enter animation was finished.
787 mEnteringAnimation = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800788 mWmService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(
789 token);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700790 }
Robert Carr61b81112017-07-17 18:08:15 -0700791
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800792 // If we're becoming visible, immediately change client visibility as well. there seem
793 // to be some edge cases where we change our visibility but client visibility never gets
794 // updated.
Jorim Jaggi110839b2018-01-22 12:49:04 +0100795 // If we're becoming invisible, update the client visibility if we are not running an
796 // animation. Otherwise, we'll update client visibility in onAnimationFinished.
Jorim Jaggi3cad57f2018-02-20 18:32:01 +0100797 if (visible || !isReallyAnimating()) {
Jorim Jaggi110839b2018-01-22 12:49:04 +0100798 setClientHidden(!visible);
Jorim Jaggi4876b4a2018-01-11 15:43:49 +0100799 }
800
Louis Chang37317152019-05-09 09:53:58 +0800801 if (!displayContent.mClosingApps.contains(this)
802 && !displayContent.mOpeningApps.contains(this)) {
chaviwa953fcf2018-03-01 12:00:39 -0800803 // The token is not closing nor opening, so even if there is an animation set, that
804 // doesn't mean that it goes through the normal app transition cycle so we have
805 // to inform the docked controller about visibility change.
806 // TODO(multi-display): notify docked divider on all displays where visibility was
807 // affected.
Louis Chang37317152019-05-09 09:53:58 +0800808 displayContent.getDockedDividerController().notifyAppVisibilityChanged();
chaviwa953fcf2018-03-01 12:00:39 -0800809
810 // Take the screenshot before possibly hiding the WSA, otherwise the screenshot
811 // will not be taken.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800812 mWmService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible);
chaviwa953fcf2018-03-01 12:00:39 -0800813 }
814
Robert Carre7cc44d2017-03-20 19:04:30 -0700815 // If we are hidden but there is no delay needed we immediately
816 // apply the Surface transaction so that the ActivityManager
Robert Carr61b81112017-07-17 18:08:15 -0700817 // can have some guarantee on the Surface state following
818 // setting the visibility. This captures cases like dismissing
819 // the docked or pinned stack where there is no app transition.
820 //
821 // In the case of a "Null" animation, there will be
822 // no animation but there will still be a transition set.
823 // We still need to delay hiding the surface such that it
824 // can be synchronized with showing the next surface in the transition.
Louis Chang37317152019-05-09 09:53:58 +0800825 if (isHidden() && !delayed && !displayContent.mAppTransition.isTransitionSet()) {
Robert Carr6914f082017-03-20 19:04:30 -0700826 SurfaceControl.openTransaction();
827 for (int i = mChildren.size() - 1; i >= 0; i--) {
828 mChildren.get(i).mWinAnimator.hide("immediately hidden");
829 }
830 SurfaceControl.closeTransaction();
831 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -0700832 }
833
834 return delayed;
835 }
836
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800837 boolean mayFreezeScreenLocked() {
838 return false;
839 }
840
841 void reportDescendantOrientationChangeIfNeeded() {
Garfield Tanb6776602019-02-20 14:44:26 -0800842 // Orientation request is exposed only when we're visible. Therefore visibility change
843 // will change requested orientation. Notify upward the hierarchy ladder to adjust
844 // configuration. This is important to cases where activities with incompatible
845 // orientations launch, or user goes back from an activity of bi-orientation to an
846 // activity with specified orientation.
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800847 if (getRequestedOrientation() == SCREEN_ORIENTATION_UNSET) {
Garfield Tanb6776602019-02-20 14:44:26 -0800848 return;
849 }
850
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800851 final IBinder freezeToken = mayFreezeScreenLocked() ? appToken : null;
852 onDescendantOrientationChanged(freezeToken, this);
Garfield Tanb6776602019-02-20 14:44:26 -0800853 }
854
Jorim Jaggi87fdbcb2017-08-17 13:41:11 +0200855 /**
856 * @return The to top most child window for which {@link LayoutParams#isFullscreen()} returns
857 * true.
858 */
859 WindowState getTopFullscreenWindow() {
860 for (int i = mChildren.size() - 1; i >= 0; i--) {
861 final WindowState win = mChildren.get(i);
862 if (win != null && win.mAttrs.isFullscreen()) {
863 return win;
864 }
865 }
866 return null;
867 }
868
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800869 WindowState findMainWindow() {
Matthew Ng53e66b22018-01-12 17:13:13 -0800870 return findMainWindow(true);
871 }
872
873 /**
874 * Finds the main window that either has type base application or application starting if
875 * requested.
876 *
877 * @param includeStartingApp Allow to search application-starting windows to also be returned.
878 * @return The main window of type base application or application starting if requested.
879 */
880 WindowState findMainWindow(boolean includeStartingApp) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700881 WindowState candidate = null;
Matthew Ng53e66b22018-01-12 17:13:13 -0800882 for (int j = mChildren.size() - 1; j >= 0; --j) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700883 final WindowState win = mChildren.get(j);
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700884 final int type = win.mAttrs.type;
885 // No need to loop through child window as base application and starting types can't be
886 // child windows.
Matthew Ng53e66b22018-01-12 17:13:13 -0800887 if (type == TYPE_BASE_APPLICATION
888 || (includeStartingApp && type == TYPE_APPLICATION_STARTING)) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700889 // In cases where there are multiple windows, we prefer the non-exiting window. This
Sungsoo Lim0d3d1f82015-12-02 14:47:59 +0900890 // happens for example when replacing windows during an activity relaunch. When
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700891 // constructing the animation, we want the new window, not the exiting one.
Wale Ogunwalec48a3542016-02-19 15:18:45 -0800892 if (win.mAnimatingExit) {
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700893 candidate = win;
894 } else {
895 return win;
896 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800897 }
898 }
Filip Gruszczynski55a309f2015-09-04 17:15:01 -0700899 return candidate;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800900 }
901
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800902 boolean isAlwaysFocusable() {
903 return (mActivityInfo.flags & FLAG_ALWAYS_FOCUSABLE) != 0;
904 }
905
906 // TODO: Does this really need to be different from isAlwaysFocusable()? For the activity side
907 // focusable means resumeable. I guess with that in mind maybe we should rename the other
908 // method to isResumeable() or something like that.
Wale Ogunwale6cae7652015-12-26 07:36:26 -0800909 boolean windowsAreFocusable() {
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800910 if (mTargetSdk < Build.VERSION_CODES.Q) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800911 final int pid = getPid();
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800912 final AppWindowToken topFocusedAppOfMyProcess =
913 mWmService.mRoot.mTopFocusedAppByProcess.get(pid);
914 if (topFocusedAppOfMyProcess != null && topFocusedAppOfMyProcess != this) {
915 // For the apps below Q, there can be only one app which has the focused window per
916 // process, because legacy apps may not be ready for a multi-focus system.
917 return false;
918 }
919 }
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800920 return getWindowConfiguration().canReceiveKeys() || isAlwaysFocusable();
921 }
922
923 // Mostly implemented in ActivityRecord...
924 int getPid() {
925 return 0;
Wale Ogunwaled045c822015-12-02 09:14:28 -0800926 }
927
Wale Ogunwale571771c2016-08-26 13:18:50 -0700928 @Override
Wale Ogunwale44f21802016-09-02 12:49:48 -0700929 boolean isVisible() {
Wale Ogunwalee471be62016-10-03 07:53:55 -0700930 // If the app token isn't hidden then it is considered visible and there is no need to check
931 // its children windows to see if they are visible.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200932 return !isHidden();
Wale Ogunwale44f21802016-09-02 12:49:48 -0700933 }
934
935 @Override
Wale Ogunwalee287e192017-04-21 09:30:12 -0700936 void removeImmediately() {
937 onRemovedFromDisplay();
938 super.removeImmediately();
939 }
940
941 @Override
Wale Ogunwale571771c2016-08-26 13:18:50 -0700942 void removeIfPossible() {
Craig Mautnere3119b72015-01-20 15:02:36 -0800943 mIsExiting = false;
Wale Ogunwale3d0bfd92016-12-05 11:38:02 -0800944 removeAllWindowsIfPossible();
Bryce Lee6d410262017-02-28 15:30:17 -0800945 removeImmediately();
Craig Mautnere3119b72015-01-20 15:02:36 -0800946 }
947
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700948 @Override
949 boolean checkCompleteDeferredRemoval() {
950 if (mIsExiting) {
951 removeIfPossible();
952 }
953 return super.checkCompleteDeferredRemoval();
954 }
955
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700956 void onRemovedFromDisplay() {
Wale Ogunwalee287e192017-04-21 09:30:12 -0700957 if (mRemovingFromDisplay) {
958 return;
959 }
960 mRemovingFromDisplay = true;
961
Adrian Roosb125e0b2019-10-02 14:55:14 +0200962 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Removing app token: %s", this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700963
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800964 boolean delayed = commitVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700965
lumark588a3e82018-07-20 18:53:54 +0800966 getDisplayContent().mOpeningApps.remove(this);
Evan Rosky2289ba12018-11-19 18:28:18 -0800967 getDisplayContent().mChangingApps.remove(this);
lumark588a3e82018-07-20 18:53:54 +0800968 getDisplayContent().mUnknownAppVisibilityController.appRemovedOrHidden(this);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800969 mWmService.mTaskSnapshotController.onAppRemoved(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700970 waitingToShow = false;
lumark588a3e82018-07-20 18:53:54 +0800971 if (getDisplayContent().mClosingApps.contains(this)) {
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700972 delayed = true;
lumark588a3e82018-07-20 18:53:54 +0800973 } else if (getDisplayContent().mAppTransition.isTransitionSet()) {
974 getDisplayContent().mClosingApps.add(this);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700975 delayed = true;
976 }
977
Adrian Roosb125e0b2019-10-02 14:55:14 +0200978 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
979 "Removing app %s delayed=%b animation=%s animating=%b", this, delayed,
980 getAnimation(), isSelfAnimating());
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700981
Adrian Roosb125e0b2019-10-02 14:55:14 +0200982 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "removeAppToken: %s"
983 + " delayed=%b Callers=%s", this, delayed, Debug.getCallers(4));
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700984
chaviwa8f07a72019-05-01 16:25:39 -0700985 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -0800986 removeStartingWindow();
Jorim Jaggi19be6052017-08-03 18:33:43 +0200987 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800988
Winson Chung87e5d552017-04-05 11:49:38 -0700989 // If this window was animating, then we need to ensure that the app transition notifies
lumark588a3e82018-07-20 18:53:54 +0800990 // that animations have completed in DisplayContent.handleAnimatingStoppedAndTransition(),
991 // so add to that list now
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200992 if (isSelfAnimating()) {
lumark588a3e82018-07-20 18:53:54 +0800993 getDisplayContent().mNoAnimationNotifyOnTransitionFinished.add(token);
Winson Chung87e5d552017-04-05 11:49:38 -0700994 }
995
Wale Ogunwalee287e192017-04-21 09:30:12 -0700996 final TaskStack stack = getStack();
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700997 if (delayed && !isEmpty()) {
998 // set the token aside because it has an active animation to be finished
Adrian Roosb125e0b2019-10-02 14:55:14 +0200999 ProtoLog.v(WM_DEBUG_ADD_REMOVE,
1000 "removeAppToken make exiting: %s", this);
Wale Ogunwalee287e192017-04-21 09:30:12 -07001001 if (stack != null) {
1002 stack.mExitingAppTokens.add(this);
1003 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -07001004 mIsExiting = true;
1005 } else {
1006 // Make sure there is no animation running on this token, so any windows associated
1007 // with it will be removed as soon as their animations are complete
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001008 cancelAnimation();
Wale Ogunwale3106ae012017-05-16 08:56:37 -07001009 if (stack != null) {
1010 stack.mExitingAppTokens.remove(this);
1011 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -07001012 removeIfPossible();
1013 }
1014
1015 removed = true;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -07001016 stopFreezingScreen(true, true);
Bryce Lee6d410262017-02-28 15:30:17 -08001017
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001018 final DisplayContent dc = getDisplayContent();
1019 if (dc.mFocusedApp == this) {
Adrian Roosb125e0b2019-10-02 14:55:14 +02001020 ProtoLog.v(WM_DEBUG_FOCUS_LIGHT,
1021 "Removing focused app token:%s displayId=%d", this,
1022 dc.getDisplayId());
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001023 dc.setFocusedApp(null);
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001024 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
Wale Ogunwaleac2561e2016-11-01 15:43:46 -07001025 }
Riddle Hsu192fe762019-01-15 23:41:57 +08001026 if (mLetterbox != null) {
1027 mLetterbox.destroy();
1028 mLetterbox = null;
1029 }
Wale Ogunwaleac2561e2016-11-01 15:43:46 -07001030
1031 if (!delayed) {
1032 updateReportedVisibilityLocked();
1033 }
Wale Ogunwalee287e192017-04-21 09:30:12 -07001034
Hongwei Wang75b6e6c2019-09-17 10:07:56 -07001035 // Reset the last saved PiP snap fraction on removal.
1036 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(mActivityComponent);
1037
Wale Ogunwalee287e192017-04-21 09:30:12 -07001038 mRemovingFromDisplay = false;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -07001039 }
1040
Chong Zhange05bcb12016-07-26 17:47:29 -07001041 void clearAnimatingFlags() {
Chong Zhangb0d26702016-08-12 16:03:29 -07001042 boolean wallpaperMightChange = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001043 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001044 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001045 wallpaperMightChange |= win.clearAnimatingFlags();
Chong Zhange05bcb12016-07-26 17:47:29 -07001046 }
Chong Zhangb0d26702016-08-12 16:03:29 -07001047 if (wallpaperMightChange) {
1048 requestUpdateWallpaperIfNeeded();
1049 }
Chong Zhange05bcb12016-07-26 17:47:29 -07001050 }
1051
Robert Carre12aece2016-02-02 22:43:27 -08001052 void destroySurfaces() {
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001053 destroySurfaces(false /*cleanupOnResume*/);
1054 }
1055
1056 /**
1057 * Destroy surfaces which have been marked as eligible by the animator, taking care to ensure
1058 * the client has finished with them.
1059 *
1060 * @param cleanupOnResume whether this is done when app is resumed without fully stopped. If
1061 * set to true, destroy only surfaces of removed windows, and clear relevant flags of the
1062 * others so that they are ready to be reused. If set to false (common case), destroy all
1063 * surfaces that's eligible, if the app is already stopped.
1064 */
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001065 private void destroySurfaces(boolean cleanupOnResume) {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001066 boolean destroyedSomething = false;
Jorim Jaggia5e10572017-11-15 14:36:26 +01001067
1068 // Copying to a different list as multiple children can be removed.
Jorim Jaggi59f3e922018-01-05 15:40:32 +01001069 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
Jorim Jaggia5e10572017-11-15 14:36:26 +01001070 for (int i = children.size() - 1; i >= 0; i--) {
1071 final WindowState win = children.get(i);
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001072 destroyedSomething |= win.destroySurface(cleanupOnResume, mAppStopped);
Robert Carre12aece2016-02-02 22:43:27 -08001073 }
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001074 if (destroyedSomething) {
1075 final DisplayContent dc = getDisplayContent();
Wale Ogunwalec69694a2016-10-18 13:51:15 -07001076 dc.assignWindowLayers(true /*setLayoutNeeded*/);
Adrian Roos23df3a32018-03-15 15:41:13 +01001077 updateLetterboxSurface(null);
Robert Carre12aece2016-02-02 22:43:27 -08001078 }
1079 }
1080
Wale Ogunwale8d5a5422016-03-03 18:28:21 -08001081 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001082 * Notify that the app is now resumed, and it was not stopped before, perform a clean
1083 * up of the surfaces
Wale Ogunwale8d5a5422016-03-03 18:28:21 -08001084 */
Jorim Jaggibae01b12017-04-11 16:29:10 -07001085 void notifyAppResumed(boolean wasStopped) {
Adrian Roosb125e0b2019-10-02 14:55:14 +02001086 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "notifyAppResumed: wasStopped=%b %s",
1087 wasStopped, this);
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001088 mAppStopped = false;
chaviwd3bf08d2017-08-01 17:24:59 -07001089 // Allow the window to turn the screen on once the app is resumed again.
Riddle Hsu4bb06be2019-07-02 01:03:07 +08001090 setCurrentLaunchCanTurnScreenOn(true);
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001091 if (!wasStopped) {
1092 destroySurfaces(true /*cleanupOnResume*/);
Wale Ogunwale8d5a5422016-03-03 18:28:21 -08001093 }
Robert Carre12aece2016-02-02 22:43:27 -08001094 }
1095
Chong Zhangbef461f2015-10-27 11:38:24 -07001096 /**
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001097 * Notify that the app has stopped, and it is okay to destroy any surfaces which were
1098 * keeping alive in case they were still being used.
1099 */
1100 void notifyAppStopped() {
Adrian Roosb125e0b2019-10-02 14:55:14 +02001101 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "notifyAppStopped: %s", this);
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001102 mAppStopped = true;
Hongwei Wanga5799f82019-07-01 15:52:50 -07001103 // Reset the last saved PiP snap fraction on app stop.
Hongwei Wang43a752b2019-09-17 20:20:30 +00001104 mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(mActivityComponent);
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001105 destroySurfaces();
1106 // Remove any starting window that was added for this app if they are still around.
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001107 removeStartingWindow();
Chong Zhang45e6d2d2016-07-20 18:33:56 -07001108 }
1109
Chong Zhang92147042016-05-09 12:47:11 -07001110 void clearAllDrawn() {
1111 allDrawn = false;
1112 deferClearAllDrawn = false;
Chong Zhangbef461f2015-10-27 11:38:24 -07001113 }
1114
Bryce Lee6d410262017-02-28 15:30:17 -08001115 Task getTask() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001116 return (Task) getParent();
Bryce Lee6d410262017-02-28 15:30:17 -08001117 }
1118
Jorim Jaggi3878ca32017-02-02 17:13:05 -08001119 TaskStack getStack() {
1120 final Task task = getTask();
1121 if (task != null) {
1122 return task.mStack;
1123 } else {
1124 return null;
1125 }
1126 }
1127
Bryce Lee6d410262017-02-28 15:30:17 -08001128 @Override
Riddle Hsu3a4bb612019-01-31 00:02:22 +08001129 void onParentChanged() {
1130 super.onParentChanged();
Bryce Lee6d410262017-02-28 15:30:17 -08001131
Robert Carred3e83b2017-04-21 13:26:55 -07001132 final Task task = getTask();
1133
Bryce Lee6d410262017-02-28 15:30:17 -08001134 // When the associated task is {@code null}, the {@link AppWindowToken} can no longer
1135 // access visual elements like the {@link DisplayContent}. We must remove any associations
1136 // such as animations.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001137 if (!mReparenting) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001138 if (task == null) {
1139 // It is possible we have been marked as a closing app earlier. We must remove ourselves
1140 // from this list so we do not participate in any future animations.
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001141 if (getDisplayContent() != null) {
1142 getDisplayContent().mClosingApps.remove(this);
1143 }
Robert Carred3e83b2017-04-21 13:26:55 -07001144 } else if (mLastParent != null && mLastParent.mStack != null) {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001145 task.mStack.mExitingAppTokens.remove(this);
1146 }
Bryce Lee6d410262017-02-28 15:30:17 -08001147 }
Jorim Jaggi6de61012018-03-19 14:53:23 +01001148 final TaskStack stack = getStack();
1149
1150 // If we reparent, make sure to remove ourselves from the old animation registry.
1151 if (mAnimatingAppWindowTokenRegistry != null) {
1152 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
1153 }
1154 mAnimatingAppWindowTokenRegistry = stack != null
1155 ? stack.getAnimatingAppWindowTokenRegistry()
1156 : null;
1157
Robert Carred3e83b2017-04-21 13:26:55 -07001158 mLastParent = task;
chaviwdcf76ec2019-01-11 16:48:46 -08001159
1160 updateColorTransform();
Bryce Lee6d410262017-02-28 15:30:17 -08001161 }
1162
Wale Ogunwalefa854eb2016-09-20 13:43:52 -07001163 void postWindowRemoveStartingWindowCleanup(WindowState win) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001164 // TODO: Something smells about the code below...Is there a better way?
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001165 if (startingWindow == win) {
Adrian Roosb125e0b2019-10-02 14:55:14 +02001166 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Notify removed startingWindow %s", win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001167 removeStartingWindow();
Wale Ogunwale6c459212017-05-17 08:56:03 -07001168 } else if (mChildren.size() == 0) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001169 // If this is the last window and we had requested a starting transition window,
1170 // well there is no point now.
Adrian Roosb125e0b2019-10-02 14:55:14 +02001171 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Nulling last startingData");
chaviwa8f07a72019-05-01 16:25:39 -07001172 mStartingData = null;
Wale Ogunwale6c459212017-05-17 08:56:03 -07001173 if (mHiddenSetFromTransferredStartingWindow) {
1174 // We set the hidden state to false for the token from a transferred starting window.
1175 // We now reset it back to true since the starting window was the last window in the
1176 // token.
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001177 setHidden(true);
Wale Ogunwale6c459212017-05-17 08:56:03 -07001178 }
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01001179 } else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001180 // If this is the last window except for a starting transition window,
1181 // we need to get rid of the starting transition.
Adrian Roosb125e0b2019-10-02 14:55:14 +02001182 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Last window, removing starting window %s", win);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001183 removeStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001184 }
1185 }
1186
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001187 void removeDeadWindows() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001188 for (int winNdx = mChildren.size() - 1; winNdx >= 0; --winNdx) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001189 WindowState win = mChildren.get(winNdx);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001190 if (win.mAppDied) {
Adrian Roosb125e0b2019-10-02 14:55:14 +02001191 ProtoLog.w(WM_DEBUG_ADD_REMOVE,
1192 "removeDeadWindows: %s", win);
Chong Zhang112eb8c2015-11-02 11:17:00 -08001193 // Set mDestroying, we don't want any animation or delayed removal here.
1194 win.mDestroying = true;
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001195 // Also removes child windows.
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001196 win.removeIfPossible();
Chong Zhang112eb8c2015-11-02 11:17:00 -08001197 }
1198 }
1199 }
1200
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001201 boolean hasWindowsAlive() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001202 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001203 // No need to loop through child windows as the answer should be the same as that of the
1204 // parent window.
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001205 if (!(mChildren.get(i)).mAppDied) {
Wale Ogunwalee42d0e12016-05-02 16:40:59 -07001206 return true;
1207 }
1208 }
1209 return false;
1210 }
1211
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001212 void setWillReplaceWindows(boolean animate) {
Adrian Roosb125e0b2019-10-02 14:55:14 +02001213 ProtoLog.d(WM_DEBUG_ADD_REMOVE,
1214 "Marking app token %s with replacing windows.", this);
Robert Carra1eb4392015-12-10 12:43:51 -08001215
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001216 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001217 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001218 w.setWillReplaceWindow(animate);
Robert Carra1eb4392015-12-10 12:43:51 -08001219 }
Robert Carra1eb4392015-12-10 12:43:51 -08001220 }
1221
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001222 void setWillReplaceChildWindows() {
Adrian Roosb125e0b2019-10-02 14:55:14 +02001223 ProtoLog.d(WM_DEBUG_ADD_REMOVE, "Marking app token %s"
1224 + " with replacing child windows.", this);
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001225 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001226 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001227 w.setWillReplaceChildWindows();
Robert Carr23fa16b2016-01-13 13:19:58 -08001228 }
1229 }
1230
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001231 void clearWillReplaceWindows() {
Adrian Roosb125e0b2019-10-02 14:55:14 +02001232 ProtoLog.d(WM_DEBUG_ADD_REMOVE,
1233 "Resetting app token %s of replacing window marks.", this);
Chong Zhangf596cd52016-01-05 13:42:44 -08001234
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001235 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001236 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001237 w.clearWillReplaceWindow();
Chong Zhangf596cd52016-01-05 13:42:44 -08001238 }
1239 }
1240
Chong Zhang4d7369a2016-04-25 16:09:14 -07001241 void requestUpdateWallpaperIfNeeded() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001242 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001243 final WindowState w = mChildren.get(i);
Chong Zhang4d7369a2016-04-25 16:09:14 -07001244 w.requestUpdateWallpaperIfNeeded();
1245 }
1246 }
1247
Chong Zhangd78ddb42016-03-02 17:01:14 -08001248 boolean isRelaunching() {
1249 return mPendingRelaunchCount > 0;
1250 }
1251
Robert Carr68375192017-06-13 12:41:53 -07001252 boolean shouldFreezeBounds() {
1253 final Task task = getTask();
1254
1255 // For freeform windows, we can't freeze the bounds at the moment because this would make
1256 // the resizing unresponsive.
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001257 if (task == null || task.inFreeformWindowingMode()) {
Robert Carr68375192017-06-13 12:41:53 -07001258 return false;
1259 }
1260
1261 // We freeze the bounds while drag resizing to deal with the time between
1262 // the divider/drag handle being released, and the handling it's new
1263 // configuration. If we are relaunched outside of the drag resizing state,
1264 // we need to be careful not to do this.
1265 return getTask().isDragResizing();
1266 }
1267
Chong Zhangd78ddb42016-03-02 17:01:14 -08001268 void startRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001269 if (shouldFreezeBounds()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08001270 freezeBounds();
1271 }
Robert Carrd5c7dd62017-03-08 10:39:30 -08001272
1273 // In the process of tearing down before relaunching, the app will
1274 // try and clean up it's child surfaces. We need to prevent this from
1275 // happening, so we sever the children, transfering their ownership
1276 // from the client it-self to the parent surface (owned by us).
Robert Carr29daa922018-04-27 11:56:48 -07001277 detachChildren();
1278
1279 mPendingRelaunchCount++;
1280 }
1281
1282 void detachChildren() {
Robert Carrfd8e93b2018-05-10 13:40:25 -07001283 SurfaceControl.openTransaction();
Robert Carrd5c7dd62017-03-08 10:39:30 -08001284 for (int i = mChildren.size() - 1; i >= 0; i--) {
1285 final WindowState w = mChildren.get(i);
1286 w.mWinAnimator.detachChildren();
1287 }
Robert Carrfd8e93b2018-05-10 13:40:25 -07001288 SurfaceControl.closeTransaction();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001289 }
1290
1291 void finishRelaunching() {
Robert Carr68375192017-06-13 12:41:53 -07001292 unfreezeBounds();
1293
Chong Zhangd78ddb42016-03-02 17:01:14 -08001294 if (mPendingRelaunchCount > 0) {
1295 mPendingRelaunchCount--;
Bryce Lee081554b2017-05-25 07:52:12 -07001296 } else {
1297 // Update keyguard flags upon finishing relaunch.
1298 checkKeyguardFlagsChanged();
Chong Zhangd78ddb42016-03-02 17:01:14 -08001299 }
1300 }
1301
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001302 void clearRelaunching() {
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001303 if (mPendingRelaunchCount == 0) {
1304 return;
1305 }
Robert Carr68375192017-06-13 12:41:53 -07001306 unfreezeBounds();
Wale Ogunwale8fd75422016-06-24 14:20:37 -07001307 mPendingRelaunchCount = 0;
1308 }
1309
Wale Ogunwale07bcab72016-10-14 15:30:09 -07001310 /**
1311 * Returns true if the new child window we are adding to this token is considered greater than
1312 * the existing child window in this token in terms of z-order.
1313 */
1314 @Override
1315 protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
1316 WindowState existingWindow) {
1317 final int type1 = newWindow.mAttrs.type;
1318 final int type2 = existingWindow.mAttrs.type;
1319
1320 // Base application windows should be z-ordered BELOW all other windows in the app token.
1321 if (type1 == TYPE_BASE_APPLICATION && type2 != TYPE_BASE_APPLICATION) {
1322 return false;
1323 } else if (type1 != TYPE_BASE_APPLICATION && type2 == TYPE_BASE_APPLICATION) {
1324 return true;
1325 }
1326
1327 // Starting windows should be z-ordered ABOVE all other windows in the app token.
1328 if (type1 == TYPE_APPLICATION_STARTING && type2 != TYPE_APPLICATION_STARTING) {
1329 return true;
1330 } else if (type1 != TYPE_APPLICATION_STARTING && type2 == TYPE_APPLICATION_STARTING) {
1331 return false;
1332 }
1333
1334 // Otherwise the new window is greater than the existing window.
1335 return true;
1336 }
1337
Tarandeep Singh69ab1042019-07-30 13:30:03 -07001338 /**
1339 * @return {@code true} if starting window is in app's hierarchy.
1340 */
1341 boolean hasStartingWindow() {
1342 if (startingDisplayed || mStartingData != null) {
1343 return true;
1344 }
1345 for (int i = mChildren.size() - 1; i >= 0; i--) {
1346 if (getChildAt(i).mAttrs.type == TYPE_APPLICATION_STARTING) {
1347 return true;
1348 }
1349 }
1350 return false;
1351 }
1352
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001353 @Override
Robert Carra1eb4392015-12-10 12:43:51 -08001354 void addWindow(WindowState w) {
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001355 super.addWindow(w);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001356
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001357 boolean gotReplacementWindow = false;
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001358 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001359 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001360 gotReplacementWindow |= candidate.setReplacementWindowIfNeeded(w);
1361 }
Wale Ogunwale92fc3722016-08-05 12:19:08 -07001362
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001363 // if we got a replacement window, reset the timeout to give drawing more time
1364 if (gotReplacementWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001365 mWmService.scheduleWindowReplacementTimeouts(this);
Robert Carra1eb4392015-12-10 12:43:51 -08001366 }
Jorim Jaggife762342016-10-13 14:33:27 +02001367 checkKeyguardFlagsChanged();
1368 }
1369
1370 @Override
1371 void removeChild(WindowState child) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001372 if (!mChildren.contains(child)) {
1373 // This can be true when testing.
1374 return;
1375 }
Jorim Jaggife762342016-10-13 14:33:27 +02001376 super.removeChild(child);
1377 checkKeyguardFlagsChanged();
Adrian Roos23df3a32018-03-15 15:41:13 +01001378 updateLetterboxSurface(child);
Robert Carra1eb4392015-12-10 12:43:51 -08001379 }
1380
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001381 private boolean waitingForReplacement() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001382 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001383 final WindowState candidate = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001384 if (candidate.waitingForReplacement()) {
Robert Carra1eb4392015-12-10 12:43:51 -08001385 return true;
1386 }
1387 }
1388 return false;
1389 }
1390
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001391 void onWindowReplacementTimeout() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001392 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001393 (mChildren.get(i)).onWindowReplacementTimeout();
Robert Carra1eb4392015-12-10 12:43:51 -08001394 }
1395 }
1396
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001397 void reparent(Task task, int position) {
Adrian Roosb125e0b2019-10-02 14:55:14 +02001398 ProtoLog.i(WM_DEBUG_ADD_REMOVE, "reparent: moving app token=%s"
1399 + " to task=%d at %d", this, task.mTaskId, position);
1400
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001401 if (task == null) {
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001402 throw new IllegalArgumentException("reparent: could not find task");
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001403 }
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001404 final Task currentTask = getTask();
1405 if (task == currentTask) {
Winson Chung30480042017-01-26 10:55:34 -08001406 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001407 "window token=" + this + " already child of task=" + currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001408 }
Bryce Lee6d410262017-02-28 15:30:17 -08001409
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001410 if (currentTask.mStack != task.mStack) {
Bryce Lee6d410262017-02-28 15:30:17 -08001411 throw new IllegalArgumentException(
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001412 "window token=" + this + " current task=" + currentTask
Bryce Lee6d410262017-02-28 15:30:17 -08001413 + " belongs to a different stack than " + task);
1414 }
1415
Adrian Roosb125e0b2019-10-02 14:55:14 +02001416 ProtoLog.i(WM_DEBUG_ADD_REMOVE, "reParentWindowToken: removing window token=%s"
1417 + " from task=%s" , this, currentTask);
Winson Chung30480042017-01-26 10:55:34 -08001418 final DisplayContent prevDisplayContent = getDisplayContent();
1419
Bryce Lee6d410262017-02-28 15:30:17 -08001420 mReparenting = true;
1421
Winson Chung30480042017-01-26 10:55:34 -08001422 getParent().removeChild(this);
Wale Ogunwale3198da42019-10-10 14:45:03 +02001423 task.addChild((ActivityRecord) this, position);
Winson Chung30480042017-01-26 10:55:34 -08001424
Bryce Lee6d410262017-02-28 15:30:17 -08001425 mReparenting = false;
1426
Winson Chung30480042017-01-26 10:55:34 -08001427 // Relayout display(s).
1428 final DisplayContent displayContent = task.getDisplayContent();
1429 displayContent.setLayoutNeeded();
1430 if (prevDisplayContent != displayContent) {
1431 onDisplayChanged(displayContent);
1432 prevDisplayContent.setLayoutNeeded();
1433 }
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001434 getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
Winson Chung30480042017-01-26 10:55:34 -08001435 }
1436
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001437 @Override
1438 void onDisplayChanged(DisplayContent dc) {
1439 DisplayContent prevDc = mDisplayContent;
1440 super.onDisplayChanged(dc);
Evan Roskyb1e75f72019-04-26 20:23:26 -07001441 if (prevDc == null || prevDc == mDisplayContent) {
Evan Rosky25b56192019-02-06 16:10:56 -08001442 return;
1443 }
Wale Ogunwaleb8e6b632019-06-28 15:19:25 +00001444
1445 if (prevDc.mOpeningApps.remove(this)) {
1446 // Transfer opening transition to new display.
1447 mDisplayContent.mOpeningApps.add(this);
1448 mDisplayContent.prepareAppTransition(prevDc.mAppTransition.getAppTransition(), true);
1449 mDisplayContent.executeAppTransition();
1450 }
1451
1452 if (prevDc.mChangingApps.remove(this)) {
Evan Rosky25b56192019-02-06 16:10:56 -08001453 // This gets called *after* the AppWindowToken has been reparented to the new display.
1454 // That reparenting resulted in this window changing modes (eg. FREEFORM -> FULLSCREEN),
1455 // so this token is now "frozen" while waiting for the animation to start on prevDc
1456 // (which will be cancelled since the window is no-longer a child). However, since this
1457 // is no longer a child of prevDc, this won't be notified of the cancelled animation,
1458 // so we need to cancel the change transition here.
1459 clearChangeLeash(getPendingTransaction(), true /* cancel */);
1460 }
Wale Ogunwaleb8e6b632019-06-28 15:19:25 +00001461 prevDc.mClosingApps.remove(this);
1462
Evan Rosky25b56192019-02-06 16:10:56 -08001463 if (prevDc.mFocusedApp == this) {
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001464 prevDc.setFocusedApp(null);
lumarkbf844642018-11-23 17:11:36 +08001465 final TaskStack stack = dc.getTopStack();
1466 if (stack != null) {
1467 final Task task = stack.getTopChild();
1468 if (task != null && task.getTopChild() == this) {
1469 dc.setFocusedApp(this);
1470 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001471 }
1472 }
Riddle Hsu192fe762019-01-15 23:41:57 +08001473
Evan Roskyb1e75f72019-04-26 20:23:26 -07001474 if (mLetterbox != null) {
Riddle Hsu192fe762019-01-15 23:41:57 +08001475 mLetterbox.onMovedToDisplay(mDisplayContent.getDisplayId());
1476 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001477 }
1478
Jorim Jaggi0429f352015-12-22 16:29:16 +01001479 /**
1480 * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds
1481 * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even
1482 * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen
1483 * with a queue.
1484 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001485 private void freezeBounds() {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001486 final Task task = getTask();
1487 mFrozenBounds.offer(new Rect(task.mPreparedFrozenBounds));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001488
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001489 if (task.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001490 // We didn't call prepareFreezingBounds on the task, so use the current value.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001491 mFrozenMergedConfig.offer(new Configuration(task.getConfiguration()));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001492 } else {
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001493 mFrozenMergedConfig.offer(new Configuration(task.mPreparedFrozenMergedConfig));
Jorim Jaggi26c8c422016-05-09 19:57:25 -07001494 }
Andrii Kulianb10330d2016-09-16 13:51:46 -07001495 // Calling unset() to make it equal to Configuration.EMPTY.
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08001496 task.mPreparedFrozenMergedConfig.unset();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001497 }
1498
1499 /**
1500 * Unfreezes the previously frozen bounds. See {@link #freezeBounds}.
1501 */
Chong Zhangd78ddb42016-03-02 17:01:14 -08001502 private void unfreezeBounds() {
Robert Carr68375192017-06-13 12:41:53 -07001503 if (mFrozenBounds.isEmpty()) {
1504 return;
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001505 }
Robert Carr68375192017-06-13 12:41:53 -07001506 mFrozenBounds.remove();
Wale Ogunwale37dbafc2016-06-27 10:15:20 -07001507 if (!mFrozenMergedConfig.isEmpty()) {
1508 mFrozenMergedConfig.remove();
1509 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001510 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001511 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001512 win.onUnfreezeBounds();
Jorim Jaggi4846ee32016-01-07 17:39:12 +01001513 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001514 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Jorim Jaggi0429f352015-12-22 16:29:16 +01001515 }
1516
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001517 void setAppLayoutChanges(int changes, String reason) {
1518 if (!mChildren.isEmpty()) {
1519 final DisplayContent dc = getDisplayContent();
1520 dc.pendingLayoutChanges |= changes;
1521 if (DEBUG_LAYOUT_REPEATS) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001522 mWmService.mWindowPlacerLocked.debugLayoutRepeats(reason, dc.pendingLayoutChanges);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001523 }
1524 }
1525 }
1526
1527 void removeReplacedWindowIfNeeded(WindowState replacement) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001528 for (int i = mChildren.size() - 1; i >= 0; i--) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001529 final WindowState win = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001530 if (win.removeReplacedWindowIfNeeded(replacement)) {
1531 return;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001532 }
1533 }
1534 }
1535
1536 void startFreezingScreen() {
Adrian Roosb125e0b2019-10-02 14:55:14 +02001537 ProtoLog.i(WM_DEBUG_ORIENTATION,
1538 "Set freezing of %s: hidden=%b freezing=%b hiddenRequested=%b. %s",
1539 appToken, isHidden(), mFreezingScreen, hiddenRequested,
1540 new RuntimeException().fillInStackTrace());
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001541 if (!hiddenRequested) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001542 if (!mFreezingScreen) {
1543 mFreezingScreen = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001544 mWmService.registerAppFreezeListener(this);
1545 mWmService.mAppsFreezingScreen++;
1546 if (mWmService.mAppsFreezingScreen == 1) {
1547 mWmService.startFreezingDisplayLocked(0, 0, getDisplayContent());
1548 mWmService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
1549 mWmService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001550 }
1551 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001552 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001553 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001554 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001555 w.onStartFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001556 }
1557 }
1558 }
1559
1560 void stopFreezingScreen(boolean unfreezeSurfaceNow, boolean force) {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001561 if (!mFreezingScreen) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001562 return;
1563 }
Adrian Roosb125e0b2019-10-02 14:55:14 +02001564 ProtoLog.v(WM_DEBUG_ORIENTATION,
1565 "Clear freezing of %s force=%b", this, force);
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001566 final int count = mChildren.size();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001567 boolean unfrozeWindows = false;
1568 for (int i = 0; i < count; i++) {
Wale Ogunwaled90546a2016-09-09 23:28:03 -07001569 final WindowState w = mChildren.get(i);
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001570 unfrozeWindows |= w.onStopFreezingScreen();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001571 }
1572 if (force || unfrozeWindows) {
Adrian Roosb125e0b2019-10-02 14:55:14 +02001573 ProtoLog.v(WM_DEBUG_ORIENTATION, "No longer freezing: %s", this);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001574 mFreezingScreen = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001575 mWmService.unregisterAppFreezeListener(this);
1576 mWmService.mAppsFreezingScreen--;
1577 mWmService.mLastFinishedFreezeSource = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001578 }
1579 if (unfreezeSurfaceNow) {
1580 if (unfrozeWindows) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001581 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001582 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001583 mWmService.stopFreezingDisplayLocked();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001584 }
1585 }
1586
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001587 @Override
1588 public void onAppFreezeTimeout() {
1589 Slog.w(TAG_WM, "Force clearing freeze: " + this);
1590 stopFreezingScreen(true, true);
1591 }
1592
Jorim Jaggi60f9c972018-02-01 19:21:07 +01001593 /**
1594 * Tries to transfer the starting window from a token that's above ourselves in the task but
1595 * not visible anymore. This is a common scenario apps use: Trampoline activity T start main
1596 * activity M in the same task. Now, when reopening the task, T starts on top of M but then
1597 * immediately finishes after, so we have to transfer T to M.
1598 */
1599 void transferStartingWindowFromHiddenAboveTokenIfNeeded() {
1600 final Task task = getTask();
1601 for (int i = task.mChildren.size() - 1; i >= 0; i--) {
1602 final AppWindowToken fromToken = task.mChildren.get(i);
1603 if (fromToken == this) {
1604 return;
1605 }
1606 if (fromToken.hiddenRequested && transferStartingWindow(fromToken.token)) {
1607 return;
1608 }
1609 }
1610 }
1611
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001612 boolean transferStartingWindow(IBinder transferFrom) {
Wale Ogunwale02319a62016-09-26 15:21:22 -07001613 final AppWindowToken fromToken = getDisplayContent().getAppWindowToken(transferFrom);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001614 if (fromToken == null) {
1615 return false;
1616 }
1617
1618 final WindowState tStartingWindow = fromToken.startingWindow;
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08001619 if (tStartingWindow != null && fromToken.startingSurface != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001620 // In this case, the starting icon has already been displayed, so start
1621 // letting windows get shown immediately without any more transitions.
lumark588a3e82018-07-20 18:53:54 +08001622 getDisplayContent().mSkipAppTransitionAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001623
Adrian Roosb125e0b2019-10-02 14:55:14 +02001624 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Moving existing starting %s"
1625 + " from %s to %s", tStartingWindow, fromToken, this);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001626
1627 final long origId = Binder.clearCallingIdentity();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001628 try {
1629 // Transfer the starting window over to the new token.
chaviwa8f07a72019-05-01 16:25:39 -07001630 mStartingData = fromToken.mStartingData;
Peter Visontay3556a3b2017-11-01 17:23:17 +00001631 startingSurface = fromToken.startingSurface;
1632 startingDisplayed = fromToken.startingDisplayed;
1633 fromToken.startingDisplayed = false;
1634 startingWindow = tStartingWindow;
1635 reportedVisible = fromToken.reportedVisible;
chaviwa8f07a72019-05-01 16:25:39 -07001636 fromToken.mStartingData = null;
Peter Visontay3556a3b2017-11-01 17:23:17 +00001637 fromToken.startingSurface = null;
1638 fromToken.startingWindow = null;
1639 fromToken.startingMoved = true;
1640 tStartingWindow.mToken = this;
1641 tStartingWindow.mAppToken = this;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001642
Adrian Roosb125e0b2019-10-02 14:55:14 +02001643 ProtoLog.v(WM_DEBUG_ADD_REMOVE,
1644 "Removing starting %s from %s", tStartingWindow, fromToken);
Peter Visontay3556a3b2017-11-01 17:23:17 +00001645 fromToken.removeChild(tStartingWindow);
1646 fromToken.postWindowRemoveStartingWindowCleanup(tStartingWindow);
1647 fromToken.mHiddenSetFromTransferredStartingWindow = false;
1648 addWindow(tStartingWindow);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001649
Peter Visontay3556a3b2017-11-01 17:23:17 +00001650 // Propagate other interesting state between the tokens. If the old token is displayed,
1651 // we should immediately force the new one to be displayed. If it is animating, we need
1652 // to move that animation to the new one.
1653 if (fromToken.allDrawn) {
1654 allDrawn = true;
1655 deferClearAllDrawn = fromToken.deferClearAllDrawn;
1656 }
1657 if (fromToken.firstWindowDrawn) {
1658 firstWindowDrawn = true;
1659 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001660 if (!fromToken.isHidden()) {
1661 setHidden(false);
Peter Visontay3556a3b2017-11-01 17:23:17 +00001662 hiddenRequested = false;
1663 mHiddenSetFromTransferredStartingWindow = true;
1664 }
1665 setClientHidden(fromToken.mClientHidden);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001666
Jorim Jaggi980c9de2017-11-17 01:41:37 +01001667 transferAnimation(fromToken);
1668
1669 // When transferring an animation, we no longer need to apply an animation to the
Tiger Huangc9d0d002019-05-29 22:55:29 +08001670 // the token we transfer the animation over. Thus, set this flag to indicate we've
1671 // transferred the animation.
1672 mUseTransferredAnimation = true;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001673
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001674 mWmService.updateFocusedWindowLocked(
Peter Visontay3556a3b2017-11-01 17:23:17 +00001675 UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/);
1676 getDisplayContent().setLayoutNeeded();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001677 mWmService.mWindowPlacerLocked.performSurfacePlacement();
Peter Visontay3556a3b2017-11-01 17:23:17 +00001678 } finally {
1679 Binder.restoreCallingIdentity(origId);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001680 }
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001681 return true;
chaviwa8f07a72019-05-01 16:25:39 -07001682 } else if (fromToken.mStartingData != null) {
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001683 // The previous app was getting ready to show a
1684 // starting window, but hasn't yet done so. Steal it!
Adrian Roosb125e0b2019-10-02 14:55:14 +02001685 ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
1686 "Moving pending starting from %s to %s", fromToken, this);
chaviwa8f07a72019-05-01 16:25:39 -07001687 mStartingData = fromToken.mStartingData;
1688 fromToken.mStartingData = null;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001689 fromToken.startingMoved = true;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001690 scheduleAddStartingWindow();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001691 return true;
1692 }
1693
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001694 // TODO: Transfer thumbnail
1695
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001696 return false;
1697 }
1698
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001699 boolean isLastWindow(WindowState win) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07001700 return mChildren.size() == 1 && mChildren.get(0) == win;
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001701 }
1702
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001703 @Override
1704 void onAppTransitionDone() {
1705 sendingToBottom = false;
1706 }
1707
Wale Ogunwale51362492016-09-08 17:49:17 -07001708 /**
1709 * We override because this class doesn't want its children affecting its reported orientation
1710 * in anyway.
1711 */
1712 @Override
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001713 int getOrientation(int candidate) {
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001714 if (candidate == SCREEN_ORIENTATION_BEHIND) {
1715 // Allow app to specify orientation regardless of its visibility state if the current
1716 // candidate want us to use orientation behind. I.e. the visible app on-top of this one
1717 // wants us to use the orientation of the app behind it.
1718 return mOrientation;
1719 }
1720
Bryce Lee61fbcbc2017-03-10 14:14:03 -08001721 // The {@link AppWindowToken} should only specify an orientation when it is not closing or
1722 // going to the bottom. Allowing closing {@link AppWindowToken} to participate can lead to
1723 // an Activity in another task being started in the wrong orientation during the transition.
lumark588a3e82018-07-20 18:53:54 +08001724 if (!(sendingToBottom || getDisplayContent().mClosingApps.contains(this))
1725 && (isVisible() || getDisplayContent().mOpeningApps.contains(this))) {
Bryce Leea163b762017-01-24 11:05:01 -08001726 return mOrientation;
Wale Ogunwale51362492016-09-08 17:49:17 -07001727 }
Bryce Leea163b762017-01-24 11:05:01 -08001728
1729 return SCREEN_ORIENTATION_UNSET;
Wale Ogunwale51362492016-09-08 17:49:17 -07001730 }
1731
Wale Ogunwaleb198b742016-12-01 08:44:09 -08001732 /** Returns the app's preferred orientation regardless of its currently visibility state. */
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001733 int getRequestedOrientation() {
Wale Ogunwaleb198b742016-12-01 08:44:09 -08001734 return mOrientation;
1735 }
1736
Riddle Hsub398da32019-01-21 21:48:16 +08001737 /** @return {@code true} if the compatibility bounds is taking effect. */
Riddle Hsu6b76cd32019-10-08 00:37:19 +08001738 boolean hasSizeCompatBounds() {
Riddle Hsub398da32019-01-21 21:48:16 +08001739 return mSizeCompatBounds != null;
1740 }
1741
1742 @Override
1743 float getSizeCompatScale() {
Riddle Hsu6b76cd32019-10-08 00:37:19 +08001744 return hasSizeCompatBounds() ? mSizeCompatScale : super.getSizeCompatScale();
Riddle Hsub398da32019-01-21 21:48:16 +08001745 }
1746
Craig Mautnerdbb79912012-03-01 18:59:14 -08001747 @Override
Winson Chunge55c0192017-08-24 14:50:48 -07001748 public void onConfigurationChanged(Configuration newParentConfig) {
1749 final int prevWinMode = getWindowingMode();
Evan Rosky2289ba12018-11-19 18:28:18 -08001750 mTmpPrevBounds.set(getBounds());
Winson Chunge55c0192017-08-24 14:50:48 -07001751 super.onConfigurationChanged(newParentConfig);
Riddle Hsub398da32019-01-21 21:48:16 +08001752
1753 final Task task = getTask();
1754 final Rect overrideBounds = getResolvedOverrideBounds();
1755 if (task != null && !overrideBounds.isEmpty()
1756 // If the changes come from change-listener, the incoming parent configuration is
1757 // still the old one. Make sure their orientations are the same to reduce computing
1758 // the compatibility bounds for the intermediate state.
Riddle Hsu04164182019-03-07 18:03:27 +08001759 && (task.mTaskRecord == null || task.mTaskRecord
1760 .getConfiguration().orientation == newParentConfig.orientation)) {
Riddle Hsub398da32019-01-21 21:48:16 +08001761 final Rect taskBounds = task.getBounds();
1762 // Since we only center the activity horizontally, if only the fixed height is smaller
1763 // than its container, the override bounds don't need to take effect.
1764 if ((overrideBounds.width() != taskBounds.width()
1765 || overrideBounds.height() > taskBounds.height())) {
1766 calculateCompatBoundsTransformation(newParentConfig);
1767 updateSurfacePosition();
1768 } else if (mSizeCompatBounds != null) {
1769 mSizeCompatBounds = null;
1770 mSizeCompatScale = 1f;
1771 updateSurfacePosition();
1772 }
1773 }
1774
Winson Chunge55c0192017-08-24 14:50:48 -07001775 final int winMode = getWindowingMode();
1776
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001777 if (prevWinMode == winMode || mDisplayContent == null) {
Winson Chunge55c0192017-08-24 14:50:48 -07001778 return;
1779 }
1780
Hongwei Wang43a752b2019-09-17 20:20:30 +00001781 if (prevWinMode == WINDOWING_MODE_PINNED && winMode != WINDOWING_MODE_UNDEFINED
Winson Chung82267ce2018-04-06 16:38:26 -07001782 && !isHidden()) {
Winson Chunge55c0192017-08-24 14:50:48 -07001783 // Leaving PiP to fullscreen, save the snap fraction based on the pre-animation bounds
1784 // for the next re-entry into PiP (assuming the activity is not hidden or destroyed)
1785 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
1786 if (pinnedStack != null) {
Winson Chung8efa1652018-06-06 09:34:23 -07001787 final Rect stackBounds;
1788 if (pinnedStack.lastAnimatingBoundsWasToFullscreen()) {
1789 // We are animating the bounds, use the pre-animation bounds to save the snap
1790 // fraction
1791 stackBounds = pinnedStack.mPreAnimationBounds;
1792 } else {
1793 // We skip the animation if the fullscreen configuration is not compatible, so
1794 // use the current bounds to calculate the saved snap fraction instead
1795 // (see PinnedActivityStack.skipResizeAnimation())
1796 stackBounds = mTmpRect;
1797 pinnedStack.getBounds(stackBounds);
1798 }
Hongwei Wang43a752b2019-09-17 20:20:30 +00001799 mDisplayContent.mPinnedStackControllerLocked.saveReentrySnapFraction(
1800 mActivityComponent, stackBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001801 }
Evan Rosky2289ba12018-11-19 18:28:18 -08001802 } else if (shouldStartChangeTransition(prevWinMode, winMode)) {
1803 initializeChangeTransition(mTmpPrevBounds);
Winson Chunge55c0192017-08-24 14:50:48 -07001804 }
1805 }
1806
Evan Rosky2289ba12018-11-19 18:28:18 -08001807 private boolean shouldStartChangeTransition(int prevWinMode, int newWinMode) {
Evan Rosky25b56192019-02-06 16:10:56 -08001808 if (mWmService.mDisableTransitionAnimation
1809 || !isVisible()
1810 || getDisplayContent().mAppTransition.isTransitionSet()
1811 || getSurfaceControl() == null) {
Evan Rosky2289ba12018-11-19 18:28:18 -08001812 return false;
1813 }
1814 // Only do an animation into and out-of freeform mode for now. Other mode
1815 // transition animations are currently handled by system-ui.
1816 return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
1817 }
1818
1819 /**
1820 * Initializes a change transition. Because the app is visible already, there is a small period
1821 * of time where the user can see the app content/window update before the transition starts.
1822 * To prevent this, we immediately take a snapshot and place the app/snapshot into a leash which
1823 * "freezes" the location/crop until the transition starts.
1824 * <p>
1825 * Here's a walk-through of the process:
1826 * 1. Create a temporary leash ("interim-change-leash") and reparent the app to it.
1827 * 2. Set the temporary leash's position/crop to the current state.
1828 * 3. Create a snapshot and place that at the top of the leash to cover up content changes.
1829 * 4. Once the transition is ready, it will reparent the app to the animation leash.
1830 * 5. Detach the interim-change-leash.
1831 */
1832 private void initializeChangeTransition(Rect startBounds) {
1833 mDisplayContent.prepareAppTransition(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
1834 false /* alwaysKeepCurrent */, 0, false /* forceOverride */);
1835 mDisplayContent.mChangingApps.add(this);
1836 mTransitStartRect.set(startBounds);
1837
1838 final SurfaceControl.Builder builder = makeAnimationLeash()
1839 .setParent(getAnimationLeashParent())
1840 .setName(getSurfaceControl() + " - interim-change-leash");
1841 mTransitChangeLeash = builder.build();
1842 Transaction t = getPendingTransaction();
1843 t.setWindowCrop(mTransitChangeLeash, startBounds.width(), startBounds.height());
1844 t.setPosition(mTransitChangeLeash, startBounds.left, startBounds.top);
1845 t.show(mTransitChangeLeash);
1846 t.reparent(getSurfaceControl(), mTransitChangeLeash);
1847 onAnimationLeashCreated(t, mTransitChangeLeash);
1848
Evan Rosky966759f2019-01-15 10:33:58 -08001849 // Skip creating snapshot if this transition is controlled by a remote animator which
1850 // doesn't need it.
1851 ArraySet<Integer> activityTypes = new ArraySet<>();
1852 activityTypes.add(getActivityType());
1853 RemoteAnimationAdapter adapter =
1854 mDisplayContent.mAppTransitionController.getRemoteAnimationOverride(
1855 this, TRANSIT_TASK_CHANGE_WINDOWING_MODE, activityTypes);
1856 if (adapter != null && !adapter.getChangeNeedsSnapshot()) {
1857 return;
1858 }
1859
Evan Rosky08e20932019-05-14 10:54:07 -07001860 Task task = getTask();
1861 if (mThumbnail == null && task != null && !hasCommittedReparentToAnimationLeash()) {
1862 SurfaceControl.ScreenshotGraphicBuffer snapshot =
1863 mWmService.mTaskSnapshotController.createTaskSnapshot(
1864 task, 1 /* scaleFraction */);
Yunfan Chendcb1fcf2019-02-07 19:08:41 +09001865 if (snapshot != null) {
Vishnu Nair33197392019-08-30 10:29:37 -07001866 mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory, t, this,
1867 snapshot.getGraphicBuffer(), true /* relative */);
Yunfan Chendcb1fcf2019-02-07 19:08:41 +09001868 }
Evan Rosky2289ba12018-11-19 18:28:18 -08001869 }
1870 }
1871
1872 boolean isInChangeTransition() {
Evan Roskyec9488c2019-03-01 19:32:12 -08001873 return mTransitChangeLeash != null || AppTransition.isChangeTransit(mTransit);
Evan Rosky2289ba12018-11-19 18:28:18 -08001874 }
1875
Evan Rosky966759f2019-01-15 10:33:58 -08001876 @VisibleForTesting
1877 AppWindowThumbnail getThumbnail() {
1878 return mThumbnail;
1879 }
1880
Riddle Hsub398da32019-01-21 21:48:16 +08001881 /**
1882 * Calculates the scale and offset to horizontal center the size compatibility bounds into the
1883 * region which is available to application.
1884 */
1885 private void calculateCompatBoundsTransformation(Configuration newParentConfig) {
1886 final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds();
Riddle Hsu74826262019-04-17 14:57:42 +08001887 final Rect parentBounds = newParentConfig.windowConfiguration.getBounds();
1888 final Rect viewportBounds = parentAppBounds != null ? parentAppBounds : parentBounds;
Riddle Hsu04164182019-03-07 18:03:27 +08001889 final Rect appBounds = getWindowConfiguration().getAppBounds();
1890 final Rect contentBounds = appBounds != null ? appBounds : getResolvedOverrideBounds();
Riddle Hsub398da32019-01-21 21:48:16 +08001891 final float contentW = contentBounds.width();
1892 final float contentH = contentBounds.height();
1893 final float viewportW = viewportBounds.width();
1894 final float viewportH = viewportBounds.height();
1895 // Only allow to scale down.
1896 mSizeCompatScale = (contentW <= viewportW && contentH <= viewportH)
1897 ? 1 : Math.min(viewportW / contentW, viewportH / contentH);
1898 final int offsetX = (int) ((viewportW - contentW * mSizeCompatScale + 1) * 0.5f)
1899 + viewportBounds.left;
1900
1901 if (mSizeCompatBounds == null) {
1902 mSizeCompatBounds = new Rect();
1903 }
1904 mSizeCompatBounds.set(contentBounds);
1905 mSizeCompatBounds.offsetTo(0, 0);
1906 mSizeCompatBounds.scale(mSizeCompatScale);
Riddle Hsu74826262019-04-17 14:57:42 +08001907 // Ensure to align the top with the parent.
1908 mSizeCompatBounds.top = parentBounds.top;
Riddle Hsu04164182019-03-07 18:03:27 +08001909 // The decor inset is included in height.
1910 mSizeCompatBounds.bottom += viewportBounds.top;
Riddle Hsub398da32019-01-21 21:48:16 +08001911 mSizeCompatBounds.left += offsetX;
1912 mSizeCompatBounds.right += offsetX;
1913 }
1914
1915 @Override
1916 public Rect getBounds() {
1917 if (mSizeCompatBounds != null) {
1918 return mSizeCompatBounds;
1919 }
1920 return super.getBounds();
1921 }
1922
1923 @Override
1924 public boolean matchParentBounds() {
1925 if (super.matchParentBounds()) {
1926 return true;
1927 }
1928 // An activity in size compatibility mode may have override bounds which equals to its
1929 // parent bounds, so the exact bounds should also be checked.
1930 final WindowContainer parent = getParent();
1931 return parent == null || parent.getBounds().equals(getResolvedOverrideBounds());
1932 }
1933
Winson Chunge55c0192017-08-24 14:50:48 -07001934 @Override
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001935 void checkAppWindowsReadyToShow() {
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001936 if (allDrawn == mLastAllDrawn) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001937 return;
1938 }
1939
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001940 mLastAllDrawn = allDrawn;
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001941 if (!allDrawn) {
1942 return;
1943 }
1944
1945 // The token has now changed state to having all windows shown... what to do, what to do?
Jorim Jaggib0fc8172017-11-23 17:04:08 +00001946 if (mFreezingScreen) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001947 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001948 stopFreezingScreen(false, true);
Adrian Roosb125e0b2019-10-02 14:55:14 +02001949 ProtoLog.i(WM_DEBUG_ORIENTATION,
1950 "Setting mOrientationChangeComplete=true because wtoken %s "
1951 + "numInteresting=%d numDrawn=%d",
1952 this, mNumInterestingWindows, mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001953 // This will set mOrientationChangeComplete and cause a pass through layout.
1954 setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001955 "checkAppWindowsReadyToShow: freezingScreen");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001956 } else {
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001957 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001958
1959 // We can now show all of the drawn windows!
lumark588a3e82018-07-20 18:53:54 +08001960 if (!getDisplayContent().mOpeningApps.contains(this) && canShowWindows()) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001961 showAllWindowsLocked();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001962 }
1963 }
1964 }
1965
Matthew Ng5d23afa2017-06-21 16:16:24 -07001966 /**
Bryce Leed390deb2017-06-22 13:14:28 -07001967 * Returns whether the drawn window states of this {@link AppWindowToken} has considered every
1968 * child {@link WindowState}. A child is considered if it has been passed into
1969 * {@link #updateDrawnWindowStates(WindowState)} after being added. This is used to determine
1970 * whether states, such as {@code allDrawn}, can be set, which relies on state variables such as
1971 * {@code mNumInterestingWindows}, which depend on all {@link WindowState}s being considered.
1972 *
1973 * @return {@code true} If all children have been considered, {@code false}.
1974 */
1975 private boolean allDrawnStatesConsidered() {
Bryce Lee6311c4b2017-07-06 14:09:29 -07001976 for (int i = mChildren.size() - 1; i >= 0; --i) {
1977 final WindowState child = mChildren.get(i);
Jorim Jaggie7d2b852017-08-28 17:55:15 +02001978 if (child.mightAffectAllDrawn() && !child.getDrawnStateEvaluated()) {
Bryce Leed390deb2017-06-22 13:14:28 -07001979 return false;
1980 }
1981 }
1982 return true;
1983 }
1984
1985 /**
Matthew Ng5d23afa2017-06-21 16:16:24 -07001986 * Determines if the token has finished drawing. This should only be called from
1987 * {@link DisplayContent#applySurfaceChangesTransaction}
1988 */
Matthew Ng498c71d2017-04-18 13:55:45 -07001989 void updateAllDrawn() {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001990 if (!allDrawn) {
Matthew Ng498c71d2017-04-18 13:55:45 -07001991 // Number of drawn windows can be less when a window is being relaunched, wait for
Bryce Leed390deb2017-06-22 13:14:28 -07001992 // all windows to be launched and drawn for this token be considered all drawn.
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07001993 final int numInteresting = mNumInterestingWindows;
Bryce Leed390deb2017-06-22 13:14:28 -07001994
1995 // We must make sure that all present children have been considered (determined by
1996 // {@link #allDrawnStatesConsidered}) before evaluating whether everything has been
1997 // drawn.
1998 if (numInteresting > 0 && allDrawnStatesConsidered()
1999 && mNumDrawnWindows >= numInteresting && !isRelaunching()) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07002000 if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawn: " + this
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002001 + " interesting=" + numInteresting + " drawn=" + mNumDrawnWindows);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07002002 allDrawn = true;
2003 // Force an additional layout pass where
2004 // WindowStateAnimator#commitFinishDrawingLocked() will call performShowLocked().
Matthew Ng498c71d2017-04-18 13:55:45 -07002005 if (mDisplayContent != null) {
2006 mDisplayContent.setLayoutNeeded();
2007 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002008 mWmService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
Robert Carrecc06b32017-04-18 14:25:10 -07002009
Winson Chunge7ba6862017-05-24 12:13:33 -07002010 // Notify the pinned stack upon all windows drawn. If there was an animation in
2011 // progress then this signal will resume that animation.
Wale Ogunwale61911492017-10-11 08:50:50 -07002012 final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
Winson Chunge7ba6862017-05-24 12:13:33 -07002013 if (pinnedStack != null) {
2014 pinnedStack.onAllWindowsDrawn();
Robert Carrecc06b32017-04-18 14:25:10 -07002015 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07002016 }
2017 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07002018 }
2019
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08002020 // Mostly implemented in ActivityRecord...
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002021 boolean keyDispatchingTimedOut(String reason, int windowPid) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08002022 return false;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002023 }
2024
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002025 /**
2026 * Updated this app token tracking states for interesting and drawn windows based on the window.
2027 *
2028 * @return Returns true if the input window is considered interesting and drawn while all the
2029 * windows in this app token where not considered drawn as of the last pass.
2030 */
2031 boolean updateDrawnWindowStates(WindowState w) {
Bryce Leed390deb2017-06-22 13:14:28 -07002032 w.setDrawnStateEvaluated(true /*evaluated*/);
2033
Jorim Jaggie4b0f282017-05-17 15:10:29 +02002034 if (DEBUG_STARTING_WINDOW_VERBOSE && w == startingWindow) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002035 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + w.isOnScreen()
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002036 + " allDrawn=" + allDrawn + " freezingScreen=" + mFreezingScreen);
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002037 }
2038
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002039 if (allDrawn && !mFreezingScreen) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002040 return false;
2041 }
2042
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002043 if (mLastTransactionSequence != mWmService.mTransactionSequence) {
2044 mLastTransactionSequence = mWmService.mTransactionSequence;
Matthew Ng53e66b22018-01-12 17:13:13 -08002045 mNumDrawnWindows = 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002046 startingDisplayed = false;
Matthew Ng53e66b22018-01-12 17:13:13 -08002047
2048 // There is the main base application window, even if it is exiting, wait for it
2049 mNumInterestingWindows = findMainWindow(false /* includeStartingApp */) != null ? 1 : 0;
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002050 }
2051
2052 final WindowStateAnimator winAnimator = w.mWinAnimator;
2053
2054 boolean isInterestingAndDrawn = false;
2055
Jorim Jaggie7d2b852017-08-28 17:55:15 +02002056 if (!allDrawn && w.mightAffectAllDrawn()) {
Adrian Roosb125e0b2019-10-02 14:55:14 +02002057 if (DEBUG_VISIBILITY || WM_DEBUG_ORIENTATION.isLogToLogcat()) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002058 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002059 + ", isAnimationSet=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002060 if (!w.isDrawnLw()) {
2061 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController
chaviw15ad49f2019-04-24 15:05:39 -07002062 + " pv=" + w.isVisibleByPolicy()
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002063 + " mDrawState=" + winAnimator.drawStateToString()
2064 + " ph=" + w.isParentWindowHidden() + " th=" + hiddenRequested
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002065 + " a=" + isSelfAnimating());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002066 }
2067 }
2068
2069 if (w != startingWindow) {
2070 if (w.isInteresting()) {
Matthew Ng53e66b22018-01-12 17:13:13 -08002071 // Add non-main window as interesting since the main app has already been added
2072 if (findMainWindow(false /* includeStartingApp */) != w) {
2073 mNumInterestingWindows++;
2074 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002075 if (w.isDrawnLw()) {
2076 mNumDrawnWindows++;
2077
Adrian Roosb125e0b2019-10-02 14:55:14 +02002078 if (DEBUG_VISIBILITY || WM_DEBUG_ORIENTATION.isLogToLogcat()) {
2079 Slog.v(TAG, "tokenMayBeDrawn: "
2080 + this + " w=" + w + " numInteresting=" + mNumInterestingWindows
2081 + " freezingScreen=" + mFreezingScreen
2082 + " mAppFreezing=" + w.mAppFreezing);
2083 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002084
2085 isInterestingAndDrawn = true;
2086 }
2087 }
2088 } else if (w.isDrawnLw()) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08002089 onStartingWindowDrawn(SystemClock.uptimeMillis());
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002090 startingDisplayed = true;
2091 }
2092 }
2093
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07002094 return isInterestingAndDrawn;
2095 }
2096
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08002097 /** Called when the starting window for this container is drawn. */
2098 private void onStartingWindowDrawn(long timestamp) {
2099 synchronized (mAtmService.mGlobalLock) {
2100 mAtmService.mStackSupervisor.getActivityMetricsLogger().notifyStartingWindowDrawn(
2101 getWindowingMode(), timestamp);
2102 }
2103 }
2104
Adrian Roos23df3a32018-03-15 15:41:13 +01002105 void layoutLetterbox(WindowState winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002106 final WindowState w = findMainWindow();
Adrian Roosf93b6d22018-03-21 13:48:26 +01002107 if (w == null || winHint != null && w != winHint) {
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002108 return;
2109 }
Jorim Jaggia32da382018-03-28 18:01:22 +02002110 final boolean surfaceReady = w.isDrawnLw() // Regular case
Adrian Roosf93b6d22018-03-21 13:48:26 +01002111 || w.mWinAnimator.mSurfaceDestroyDeferred // The preserved surface is still ready.
2112 || w.isDragResizeChanged(); // Waiting for relayoutWindow to call preserveSurface.
Jorim Jaggi4981f152019-03-26 18:58:45 +01002113 final boolean needsLetterbox = surfaceReady && w.isLetterboxedAppWindow() && fillsParent();
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002114 if (needsLetterbox) {
2115 if (mLetterbox == null) {
Vishnu Nair33197392019-08-30 10:29:37 -07002116 mLetterbox = new Letterbox(() -> makeChildSurface(null),
2117 mWmService.mTransactionFactory);
Riddle Hsu192fe762019-01-15 23:41:57 +08002118 mLetterbox.attachInput(w);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002119 }
Adrian Roos7af9d972018-11-30 15:26:27 +01002120 getPosition(mTmpPoint);
Evan Rosky67c15642019-04-24 13:17:28 -07002121 // Get the bounds of the "space-to-fill". In multi-window mode, the task-level
2122 // represents this. In fullscreen-mode, the stack does (since the orientation letterbox
2123 // is also applied to the task).
2124 Rect spaceToFill = (inMultiWindowMode() || getStack() == null)
2125 ? getTask().getDisplayedBounds() : getStack().getDisplayedBounds();
Evan Rosky4fb1e912019-03-06 13:54:43 -08002126 mLetterbox.layout(spaceToFill, w.getFrameLw(), mTmpPoint);
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002127 } else if (mLetterbox != null) {
Adrian Roos23df3a32018-03-15 15:41:13 +01002128 mLetterbox.hide();
2129 }
2130 }
2131
2132 void updateLetterboxSurface(WindowState winHint) {
2133 final WindowState w = findMainWindow();
2134 if (w != winHint && winHint != null && w != null) {
2135 return;
2136 }
2137 layoutLetterbox(winHint);
2138 if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) {
Tiger Huanged6794e2019-05-07 20:07:59 +08002139 mLetterbox.applySurfaceChanges(getPendingTransaction());
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002140 }
2141 }
2142
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07002143 @Override
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002144 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002145 // For legacy reasons we process the TaskStack.mExitingAppTokens first in DisplayContent
2146 // before the non-exiting app tokens. So, we skip the exiting app tokens here.
2147 // TODO: Investigate if we need to continue to do this or if we can just process them
2148 // in-order.
2149 if (mIsExiting && !waitingForReplacement()) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002150 return false;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002151 }
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002152 return forAllWindowsUnchecked(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002153 }
2154
lumark588a3e82018-07-20 18:53:54 +08002155 @Override
2156 void forAllAppWindows(Consumer<AppWindowToken> callback) {
2157 callback.accept(this);
2158 }
2159
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08002160 boolean forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback,
2161 boolean traverseTopToBottom) {
2162 return super.forAllWindows(callback, traverseTopToBottom);
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07002163 }
2164
2165 @Override
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002166 AppWindowToken asAppWindowToken() {
2167 // I am an app window token!
2168 return this;
2169 }
2170
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002171 boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
2172 CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
2173 IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
2174 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
2175 // If the display is frozen, we won't do anything until the actual window is
2176 // displayed so there is no reason to put in the starting window.
2177 if (!okToDisplay()) {
2178 return false;
2179 }
2180
chaviwa8f07a72019-05-01 16:25:39 -07002181 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002182 return false;
2183 }
2184
2185 final WindowState mainWin = findMainWindow();
2186 if (mainWin != null && mainWin.mWinAnimator.getShown()) {
2187 // App already has a visible window...why would you want a starting window?
2188 return false;
2189 }
2190
2191 final ActivityManager.TaskSnapshot snapshot =
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002192 mWmService.mTaskSnapshotController.getSnapshot(
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002193 getTask().mTaskId, getTask().mUserId,
2194 false /* restoreFromDisk */, false /* reducedResolution */);
2195 final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
2196 allowTaskSnapshot, activityCreated, fromRecents, snapshot);
2197
2198 if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
2199 return createSnapshot(snapshot);
2200 }
2201
2202 // If this is a translucent window, then don't show a starting window -- the current
2203 // effect (a full-screen opaque starting window that fades away to the real contents
2204 // when it is ready) does not work for this.
Adrian Roosb125e0b2019-10-02 14:55:14 +02002205 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Checking theme of starting window: 0x%x", theme);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002206 if (theme != 0) {
2207 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
2208 com.android.internal.R.styleable.Window,
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002209 mWmService.mCurrentUserId);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002210 if (ent == null) {
2211 // Whoops! App doesn't exist. Um. Okay. We'll just pretend like we didn't
2212 // see that.
2213 return false;
2214 }
2215 final boolean windowIsTranslucent = ent.array.getBoolean(
2216 com.android.internal.R.styleable.Window_windowIsTranslucent, false);
2217 final boolean windowIsFloating = ent.array.getBoolean(
2218 com.android.internal.R.styleable.Window_windowIsFloating, false);
2219 final boolean windowShowWallpaper = ent.array.getBoolean(
2220 com.android.internal.R.styleable.Window_windowShowWallpaper, false);
2221 final boolean windowDisableStarting = ent.array.getBoolean(
2222 com.android.internal.R.styleable.Window_windowDisablePreview, false);
Adrian Roosb125e0b2019-10-02 14:55:14 +02002223 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Translucent=%s Floating=%s ShowWallpaper=%s",
2224 windowIsTranslucent, windowIsFloating, windowShowWallpaper);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002225 if (windowIsTranslucent) {
2226 return false;
2227 }
2228 if (windowIsFloating || windowDisableStarting) {
2229 return false;
2230 }
2231 if (windowShowWallpaper) {
2232 if (getDisplayContent().mWallpaperController
2233 .getWallpaperTarget() == null) {
2234 // If this theme is requesting a wallpaper, and the wallpaper
2235 // is not currently visible, then this effectively serves as
2236 // an opaque window and our starting window transition animation
2237 // can still work. We just need to make sure the starting window
2238 // is also showing the wallpaper.
2239 windowFlags |= FLAG_SHOW_WALLPAPER;
2240 } else {
2241 return false;
2242 }
2243 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002244 }
Yunfan Chen8a8c0ed2018-12-18 16:46:32 -08002245
2246 if (transferStartingWindow(transferFrom)) {
2247 return true;
2248 }
2249
2250 // There is no existing starting window, and we don't want to create a splash screen, so
2251 // that's it!
2252 if (type != STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
2253 return false;
2254 }
2255
Adrian Roosb125e0b2019-10-02 14:55:14 +02002256 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Creating SplashScreenStartingData");
chaviwa8f07a72019-05-01 16:25:39 -07002257 mStartingData = new SplashScreenStartingData(mWmService, pkg,
Yunfan Chen8a8c0ed2018-12-18 16:46:32 -08002258 theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
2259 getMergedOverrideConfiguration());
2260 scheduleAddStartingWindow();
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002261 return true;
2262 }
2263
2264
2265 private boolean createSnapshot(ActivityManager.TaskSnapshot snapshot) {
2266 if (snapshot == null) {
2267 return false;
2268 }
2269
Adrian Roosb125e0b2019-10-02 14:55:14 +02002270 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Creating SnapshotStartingData");
chaviwa8f07a72019-05-01 16:25:39 -07002271 mStartingData = new SnapshotStartingData(mWmService, snapshot);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002272 scheduleAddStartingWindow();
2273 return true;
2274 }
2275
2276 void scheduleAddStartingWindow() {
2277 // Note: we really want to do sendMessageAtFrontOfQueue() because we
2278 // want to process the message ASAP, before any other queued
2279 // messages.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002280 if (!mWmService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
Adrian Roosb125e0b2019-10-02 14:55:14 +02002281 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Enqueueing ADD_STARTING");
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002282 mWmService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002283 }
2284 }
2285
2286 private final Runnable mAddStartingWindow = new Runnable() {
2287
2288 @Override
2289 public void run() {
chaviwa8f07a72019-05-01 16:25:39 -07002290 // Can be accessed without holding the global lock
2291 final StartingData startingData;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002292 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002293 // There can only be one adding request, silly caller!
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002294 mWmService.mAnimationHandler.removeCallbacks(this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002295
chaviwa8f07a72019-05-01 16:25:39 -07002296 if (mStartingData == null) {
2297 // Animation has been canceled... do nothing.
Adrian Roosb125e0b2019-10-02 14:55:14 +02002298 ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
2299 "startingData was nulled out before handling"
2300 + " mAddStartingWindow: %s", AppWindowToken.this);
chaviwa8f07a72019-05-01 16:25:39 -07002301 return;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002302 }
chaviwa8f07a72019-05-01 16:25:39 -07002303 startingData = mStartingData;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002304 }
2305
Adrian Roosb125e0b2019-10-02 14:55:14 +02002306 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Add starting %s: startingData=%s",
2307 this, startingData);
2308
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002309
2310 WindowManagerPolicy.StartingSurface surface = null;
2311 try {
2312 surface = startingData.createStartingSurface(AppWindowToken.this);
2313 } catch (Exception e) {
2314 Slog.w(TAG, "Exception when adding starting window", e);
2315 }
2316 if (surface != null) {
2317 boolean abort = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002318 synchronized (mWmService.mGlobalLock) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002319 // If the window was successfully added, then
2320 // we need to remove it.
chaviwa8f07a72019-05-01 16:25:39 -07002321 if (removed || mStartingData == null) {
Adrian Roosb125e0b2019-10-02 14:55:14 +02002322 ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
2323 "Aborted starting %s: removed=%b startingData=%s",
2324 AppWindowToken.this, removed, mStartingData);
2325
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002326 startingWindow = null;
chaviwa8f07a72019-05-01 16:25:39 -07002327 mStartingData = null;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002328 abort = true;
2329 } else {
2330 startingSurface = surface;
2331 }
Adrian Roosb125e0b2019-10-02 14:55:14 +02002332 if (!abort) {
2333 ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
2334 "Added starting %s: startingWindow=%s startingView=%s",
2335 AppWindowToken.this, startingWindow, startingSurface);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002336 }
2337 }
2338 if (abort) {
2339 surface.remove();
2340 }
Adrian Roosb125e0b2019-10-02 14:55:14 +02002341 } else {
2342 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Surface returned was null: %s",
2343 AppWindowToken.this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002344 }
2345 }
2346 };
2347
2348 private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
2349 boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents,
2350 ActivityManager.TaskSnapshot snapshot) {
2351 if (getDisplayContent().mAppTransition.getAppTransition()
2352 == TRANSIT_DOCK_TASK_FROM_RECENTS) {
2353 // TODO(b/34099271): Remove this statement to add back the starting window and figure
2354 // out why it causes flickering, the starting window appears over the thumbnail while
2355 // the docked from recents transition occurs
2356 return STARTING_WINDOW_TYPE_NONE;
2357 } else if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
2358 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2359 } else if (taskSwitch && allowTaskSnapshot) {
Kevin716a9db2018-12-18 16:53:39 -08002360 if (mWmService.mLowRamTaskSnapshotsAndRecents) {
Kevin58b47f12018-12-17 14:09:01 -08002361 // For low RAM devices, we use the splash screen starting window instead of the
2362 // task snapshot starting window.
2363 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2364 }
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002365 return snapshot == null ? STARTING_WINDOW_TYPE_NONE
2366 : snapshotOrientationSameAsTask(snapshot) || fromRecents
2367 ? STARTING_WINDOW_TYPE_SNAPSHOT : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
2368 } else {
2369 return STARTING_WINDOW_TYPE_NONE;
2370 }
2371 }
2372
2373
2374 private boolean snapshotOrientationSameAsTask(ActivityManager.TaskSnapshot snapshot) {
2375 if (snapshot == null) {
2376 return false;
2377 }
2378 return getTask().getConfiguration().orientation == snapshot.getOrientation();
2379 }
2380
2381 void removeStartingWindow() {
2382 if (startingWindow == null) {
chaviwa8f07a72019-05-01 16:25:39 -07002383 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002384 // Starting window has not been added yet, but it is scheduled to be added.
2385 // Go ahead and cancel the request.
Adrian Roosb125e0b2019-10-02 14:55:14 +02002386 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Clearing startingData for token=%s", this);
chaviwa8f07a72019-05-01 16:25:39 -07002387 mStartingData = null;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002388 }
2389 return;
2390 }
2391
2392 final WindowManagerPolicy.StartingSurface surface;
chaviwa8f07a72019-05-01 16:25:39 -07002393 if (mStartingData != null) {
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002394 surface = startingSurface;
chaviwa8f07a72019-05-01 16:25:39 -07002395 mStartingData = null;
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002396 startingSurface = null;
2397 startingWindow = null;
2398 startingDisplayed = false;
2399 if (surface == null) {
Adrian Roosb125e0b2019-10-02 14:55:14 +02002400 ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
2401 "startingWindow was set but startingSurface==null, couldn't "
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002402 + "remove");
Adrian Roosb125e0b2019-10-02 14:55:14 +02002403
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002404 return;
2405 }
2406 } else {
Adrian Roosb125e0b2019-10-02 14:55:14 +02002407 ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
2408 "Tried to remove starting window but startingWindow was null: %s",
2409 this);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002410 return;
2411 }
2412
Adrian Roosb125e0b2019-10-02 14:55:14 +02002413 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Schedule remove starting %s startingWindow=%s"
2414 + " startingView=%s Callers=%s",
2415 this, startingWindow, startingSurface, Debug.getCallers(5));
2416
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002417
2418 // Use the same thread to remove the window as we used to add it, as otherwise we end up
2419 // with things in the view hierarchy being called from different threads.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002420 mWmService.mAnimationHandler.post(() -> {
Adrian Roosb125e0b2019-10-02 14:55:14 +02002421 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Removing startingView=%s", surface);
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08002422 try {
2423 surface.remove();
2424 } catch (Exception e) {
2425 Slog.w(TAG_WM, "Exception when removing starting window", e);
2426 }
2427 });
2428 }
2429
Wale Ogunwale2049dbf2016-08-02 21:05:23 -07002430 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -07002431 boolean fillsParent() {
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -07002432 return occludesParent();
Wale Ogunwale51362492016-09-08 17:49:17 -07002433 }
2434
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -07002435 /** Returns true if this activity is opaque and fills the entire space of this task. */
2436 boolean occludesParent() {
2437 return mOccludesParent;
2438 }
2439
2440 boolean setOccludesParent(boolean occludesParent) {
2441 final boolean changed = occludesParent != mOccludesParent;
2442 mOccludesParent = occludesParent;
2443 setMainWindowOpaque(occludesParent);
2444 mWmService.mWindowPlacerLocked.requestTraversal();
2445 return changed;
2446 }
2447
2448 void setMainWindowOpaque(boolean isOpaque) {
2449 final WindowState win = findMainWindow();
2450 if (win == null) {
2451 return;
2452 }
2453 isOpaque = isOpaque & !PixelFormat.formatHasAlpha(win.getAttrs().format);
2454 win.mWinAnimator.setOpaqueLocked(isOpaque);
Wale Ogunwale51362492016-09-08 17:49:17 -07002455 }
2456
Jorim Jaggife762342016-10-13 14:33:27 +02002457 boolean containsDismissKeyguardWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002458 // Window state is transient during relaunch. We are not guaranteed to be frozen during the
2459 // entirety of the relaunch.
2460 if (isRelaunching()) {
2461 return mLastContainsDismissKeyguardWindow;
2462 }
2463
Jorim Jaggife762342016-10-13 14:33:27 +02002464 for (int i = mChildren.size() - 1; i >= 0; i--) {
2465 if ((mChildren.get(i).mAttrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
2466 return true;
2467 }
2468 }
2469 return false;
2470 }
2471
2472 boolean containsShowWhenLockedWindow() {
Bryce Lee081554b2017-05-25 07:52:12 -07002473 // When we are relaunching, it is possible for us to be unfrozen before our previous
2474 // windows have been added back. Using the cached value ensures that our previous
2475 // showWhenLocked preference is honored until relaunching is complete.
2476 if (isRelaunching()) {
2477 return mLastContainsShowWhenLockedWindow;
2478 }
2479
Jorim Jaggife762342016-10-13 14:33:27 +02002480 for (int i = mChildren.size() - 1; i >= 0; i--) {
2481 if ((mChildren.get(i).mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
2482 return true;
2483 }
2484 }
Bryce Lee081554b2017-05-25 07:52:12 -07002485
Jorim Jaggife762342016-10-13 14:33:27 +02002486 return false;
2487 }
2488
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08002489 void setShowWhenLocked(boolean showWhenLocked) {
2490 mShowWhenLocked = showWhenLocked;
2491 mAtmService.mRootActivityContainer.ensureActivitiesVisible(null /* starting */,
2492 0 /* configChanges */, false /* preserveWindows */);
2493 }
2494
2495 void setInheritShowWhenLocked(boolean inheritShowWhenLocked) {
2496 mInheritShownWhenLocked = inheritShowWhenLocked;
2497 mAtmService.mRootActivityContainer.ensureActivitiesVisible(null /* starting */,
2498 0 /* configChanges */, false /* preserveWindows */);
2499 }
2500
2501 /**
2502 * @return {@code true} if the activity windowing mode is not
2503 * {@link android.app.WindowConfiguration#WINDOWING_MODE_PINNED} and a) activity
2504 * contains windows that have {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} set or if the
2505 * activity has set {@link #mShowWhenLocked}, or b) if the activity has set
2506 * {@link #mInheritShownWhenLocked} and the activity behind this satisfies the
2507 * conditions a) above.
2508 * Multi-windowing mode will be exited if {@code true} is returned.
2509 */
2510 boolean canShowWhenLocked() {
2511 if (!inPinnedWindowingMode() && (mShowWhenLocked || containsShowWhenLockedWindow())) {
2512 return true;
2513 } else if (mInheritShownWhenLocked) {
2514 final AppWindowToken r = getActivityBelow();
2515 return r != null && !r.inPinnedWindowingMode() && (r.mShowWhenLocked
2516 || r.containsShowWhenLockedWindow());
2517 } else {
2518 return false;
2519 }
2520 }
2521
2522 /**
2523 * @return an {@link ActivityRecord} of the activity below this activity, or {@code null} if no
2524 * such activity exists.
2525 */
2526 @Nullable
2527 private AppWindowToken getActivityBelow() {
2528 final Task task = getTask();
2529 final int pos = task.mChildren.indexOf(this);
2530 if (pos == -1) {
2531 throw new IllegalStateException("Activity not found in its task");
2532 }
2533 return pos == 0 ? null : task.getChildAt(pos - 1);
2534 }
2535
2536 void setTurnScreenOn(boolean turnScreenOn) {
2537 mTurnScreenOn = turnScreenOn;
2538 }
2539
2540 /** Mostly implemented in ActivityRecord. */
2541 boolean canTurnScreenOn() {
2542 return mTurnScreenOn;
2543 }
2544
2545 boolean getTurnScreenOnFlag() {
2546 return mTurnScreenOn;
2547 }
2548
Jorim Jaggife762342016-10-13 14:33:27 +02002549 void checkKeyguardFlagsChanged() {
2550 final boolean containsDismissKeyguard = containsDismissKeyguardWindow();
2551 final boolean containsShowWhenLocked = containsShowWhenLockedWindow();
2552 if (containsDismissKeyguard != mLastContainsDismissKeyguardWindow
2553 || containsShowWhenLocked != mLastContainsShowWhenLockedWindow) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002554 mWmService.notifyKeyguardFlagsChanged(null /* callback */,
lumark588a3e82018-07-20 18:53:54 +08002555 getDisplayContent().getDisplayId());
Jorim Jaggife762342016-10-13 14:33:27 +02002556 }
2557 mLastContainsDismissKeyguardWindow = containsDismissKeyguard;
2558 mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
2559 }
2560
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002561 WindowState getImeTargetBelowWindow(WindowState w) {
2562 final int index = mChildren.indexOf(w);
2563 if (index > 0) {
2564 final WindowState target = mChildren.get(index - 1);
2565 if (target.canBeImeTarget()) {
2566 return target;
2567 }
2568 }
2569 return null;
2570 }
2571
2572 WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
2573 WindowState candidate = null;
2574 for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
2575 final WindowState w = mChildren.get(i);
2576 if (w.mRemoved) {
2577 continue;
2578 }
Jorim Jaggi35d328a2018-08-14 17:00:20 +02002579 if (candidate == null) {
Wale Ogunwale6213caa2016-12-02 16:47:15 +00002580 candidate = w;
2581 }
2582 }
2583 return candidate;
2584 }
2585
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002586 /**
2587 * See {@link Activity#setDisablePreviewScreenshots}.
2588 */
2589 void setDisablePreviewScreenshots(boolean disable) {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002590 mDisablePreviewScreenshots = disable;
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002591 }
2592
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002593 /**
Riddle Hsu4bb06be2019-07-02 01:03:07 +08002594 * Sets whether the current launch can turn the screen on.
2595 * @see #currentLaunchCanTurnScreenOn()
chaviwd3bf08d2017-08-01 17:24:59 -07002596 */
Riddle Hsu4bb06be2019-07-02 01:03:07 +08002597 void setCurrentLaunchCanTurnScreenOn(boolean currentLaunchCanTurnScreenOn) {
2598 mCurrentLaunchCanTurnScreenOn = currentLaunchCanTurnScreenOn;
chaviwd3bf08d2017-08-01 17:24:59 -07002599 }
2600
2601 /**
2602 * Indicates whether the current launch can turn the screen on. This is to prevent multiple
2603 * relayouts from turning the screen back on. The screen should only turn on at most
2604 * once per activity resume.
Riddle Hsu4bb06be2019-07-02 01:03:07 +08002605 * <p>
2606 * Note this flag is only meaningful when {@link WindowManager.LayoutParams#FLAG_TURN_SCREEN_ON}
2607 * or {@link ActivityRecord#canTurnScreenOn} is set.
chaviwd3bf08d2017-08-01 17:24:59 -07002608 *
Riddle Hsu4bb06be2019-07-02 01:03:07 +08002609 * @return {@code true} if the activity is ready to turn on the screen.
chaviwd3bf08d2017-08-01 17:24:59 -07002610 */
Riddle Hsu4bb06be2019-07-02 01:03:07 +08002611 boolean currentLaunchCanTurnScreenOn() {
2612 return mCurrentLaunchCanTurnScreenOn;
chaviwd3bf08d2017-08-01 17:24:59 -07002613 }
2614
2615 /**
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002616 * Retrieves whether we'd like to generate a snapshot that's based solely on the theme. This is
2617 * the case when preview screenshots are disabled {@link #setDisablePreviewScreenshots} or when
2618 * we can't take a snapshot for other reasons, for example, if we have a secure window.
2619 *
2620 * @return True if we need to generate an app theme snapshot, false if we'd like to take a real
2621 * screenshot.
2622 */
2623 boolean shouldUseAppThemeSnapshot() {
Wale Ogunwale6c459212017-05-17 08:56:03 -07002624 return mDisablePreviewScreenshots || forAllWindows(w -> (w.mAttrs.flags & FLAG_SECURE) != 0,
Jorim Jaggid635a4a2017-05-03 15:21:26 +02002625 true /* topToBottom */);
Jorim Jaggi0fe7ce962017-02-22 16:45:48 +01002626 }
2627
Jorim Jaggibe418292018-03-26 16:14:12 +02002628 SurfaceControl getAppAnimationLayer() {
Jorim Jaggi391790622018-04-18 15:30:44 +02002629 return getAppAnimationLayer(isActivityTypeHome() ? ANIMATION_LAYER_HOME
2630 : needsZBoost() ? ANIMATION_LAYER_BOOSTED
2631 : ANIMATION_LAYER_STANDARD);
Jorim Jaggibe418292018-03-26 16:14:12 +02002632 }
2633
chaviw23ee71c2017-12-18 11:29:41 -08002634 @Override
Jorim Jaggi596a1992017-12-29 14:48:02 +01002635 public SurfaceControl getAnimationLeashParent() {
Robert Carrb9506032018-02-13 13:54:00 -08002636 // For transitions in the pinned stack (menu activity) we just let them occur as a child
2637 // of the pinned stack.
Issei Suzuki71142152019-08-15 14:39:40 +02002638 // All normal app transitions take place in an animation layer which is below the pinned
2639 // stack but may be above the parent stacks of the given animating apps by default. When
2640 // a new hierarchical animation is enabled, we just let them occur as a child of the parent
2641 // stack, i.e. the hierarchy of the surfaces is unchanged.
2642 if (inPinnedWindowingMode()) {
Robert Carrb9506032018-02-13 13:54:00 -08002643 return getStack().getSurfaceControl();
Issei Suzuki71142152019-08-15 14:39:40 +02002644 } else if (WindowManagerService.sHierarchicalAnimations) {
2645 return super.getAnimationLeashParent();
2646 } else {
2647 return getAppAnimationLayer();
Robert Carrb9506032018-02-13 13:54:00 -08002648 }
chaviw23ee71c2017-12-18 11:29:41 -08002649 }
2650
lumarkb5a78b32019-04-25 20:31:30 +08002651
2652 @VisibleForTesting
2653 boolean shouldAnimate(int transit) {
Jorim Jaggic6976f02018-04-18 16:31:07 +02002654 final boolean isSplitScreenPrimary =
2655 getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
2656 final boolean allowSplitScreenPrimaryAnimation = transit != TRANSIT_WALLPAPER_OPEN;
2657
lumarkb5a78b32019-04-25 20:31:30 +08002658 // Don't animate while the task runs recents animation but only if we are in the mode
2659 // where we cancel with deferred screenshot, which means that the controller has
2660 // transformed the task.
lumark54284462019-03-05 20:44:27 +08002661 final RecentsAnimationController controller = mWmService.getRecentsAnimationController();
lumarkb5a78b32019-04-25 20:31:30 +08002662 if (controller != null && controller.isAnimatingTask(getTask())
Winson Chung7a545ae2019-07-16 14:52:13 -07002663 && controller.shouldDeferCancelUntilNextTransition()) {
lumark54284462019-03-05 20:44:27 +08002664 return false;
2665 }
2666
Jorim Jaggic6976f02018-04-18 16:31:07 +02002667 // We animate always if it's not split screen primary, and only some special cases in split
2668 // screen primary because it causes issues with stack clipping when we run an un-minimize
2669 // animation at the same time.
2670 return !isSplitScreenPrimary || allowSplitScreenPrimaryAnimation;
2671 }
2672
Vishnu Naira2977262018-07-26 13:31:26 -07002673 /**
2674 * Creates a layer to apply crop to an animation.
2675 */
2676 private SurfaceControl createAnimationBoundsLayer(Transaction t) {
Adrian Roosb125e0b2019-10-02 14:55:14 +02002677 ProtoLog.i(WM_DEBUG_APP_TRANSITIONS_ANIM, "Creating animation bounds layer");
Vishnu Naira2977262018-07-26 13:31:26 -07002678 final SurfaceControl.Builder builder = makeAnimationLeash()
2679 .setParent(getAnimationLeashParent())
Vishnu Naire86bd982018-11-28 13:23:17 -08002680 .setName(getSurfaceControl() + " - animation-bounds");
Vishnu Naira2977262018-07-26 13:31:26 -07002681 final SurfaceControl boundsLayer = builder.build();
2682 t.show(boundsLayer);
2683 return boundsLayer;
2684 }
2685
Evan Roskyed6767f2018-10-26 17:21:06 -07002686 @Override
2687 Rect getDisplayedBounds() {
2688 final Task task = getTask();
2689 if (task != null) {
2690 final Rect overrideDisplayedBounds = task.getOverrideDisplayedBounds();
2691 if (!overrideDisplayedBounds.isEmpty()) {
2692 return overrideDisplayedBounds;
2693 }
2694 }
2695 return getBounds();
2696 }
2697
Evan Rosky641daea2019-04-24 14:45:24 -07002698 @VisibleForTesting
2699 Rect getAnimationBounds(int appStackClipMode) {
2700 if (appStackClipMode == STACK_CLIP_BEFORE_ANIM && getStack() != null) {
2701 // Using the stack bounds here effectively applies the clipping before animation.
2702 return getStack().getBounds();
2703 }
2704 // Use task-bounds if available so that activity-level letterbox (maxAspectRatio) is
2705 // included in the animation.
2706 return getTask() != null ? getTask().getBounds() : getBounds();
2707 }
2708
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002709 boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter,
2710 boolean isVoiceInteraction) {
2711
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002712 if (mWmService.mDisableTransitionAnimation || !shouldAnimate(transit)) {
Adrian Roosb125e0b2019-10-02 14:55:14 +02002713 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
2714 "applyAnimation: transition animation is disabled or skipped. "
2715 + "atoken=%s", this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002716 cancelAnimation();
2717 return false;
2718 }
2719
2720 // Only apply an animation if the display isn't frozen. If it is frozen, there is no reason
2721 // to animate and it can cause strange artifacts when we unfreeze the display if some
2722 // different animation is running.
2723 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#applyAnimationLocked");
2724 if (okToAnimate()) {
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002725 final AnimationAdapter adapter;
Evan Rosky2289ba12018-11-19 18:28:18 -08002726 AnimationAdapter thumbnailAdapter = null;
Evan Rosky4fb1e912019-03-06 13:54:43 -08002727
Evan Rosky641daea2019-04-24 14:45:24 -07002728 final int appStackClipMode =
2729 getDisplayContent().mAppTransition.getAppStackClipMode();
2730
2731 // Separate position and size for use in animators.
2732 mTmpRect.set(getAnimationBounds(appStackClipMode));
Evan Rosky4fb1e912019-03-06 13:54:43 -08002733 mTmpPoint.set(mTmpRect.left, mTmpRect.top);
2734 mTmpRect.offsetTo(0, 0);
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002735
Evan Roskyec9488c2019-03-01 19:32:12 -08002736 final boolean isChanging = AppTransition.isChangeTransit(transit) && enter
2737 && getDisplayContent().mChangingApps.contains(this);
Evan Rosky2289ba12018-11-19 18:28:18 -08002738
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002739 // Delaying animation start isn't compatible with remote animations at all.
lumark588a3e82018-07-20 18:53:54 +08002740 if (getDisplayContent().mAppTransition.getRemoteAnimationController() != null
Jorim Jaggic4d29f22018-03-22 16:30:56 +01002741 && !mSurfaceAnimator.isAnimationStartDelayed()) {
Evan Rosky2289ba12018-11-19 18:28:18 -08002742 RemoteAnimationRecord adapters =
2743 getDisplayContent().mAppTransition.getRemoteAnimationController()
2744 .createRemoteAnimationRecord(this, mTmpPoint, mTmpRect,
2745 (isChanging ? mTransitStartRect : null));
2746 adapter = adapters.mAdapter;
2747 thumbnailAdapter = adapters.mThumbnailAdapter;
2748 } else if (isChanging) {
Evan Roskycf76bed2019-01-15 10:33:58 -08002749 final float durationScale = mWmService.getTransitionAnimationScaleLocked();
Evan Rosky2289ba12018-11-19 18:28:18 -08002750 mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y);
2751 adapter = new LocalAnimationAdapter(
2752 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
Evan Roskycf76bed2019-01-15 10:33:58 -08002753 getDisplayContent().getDisplayInfo(), durationScale,
Evan Rosky2289ba12018-11-19 18:28:18 -08002754 true /* isAppAnimation */, false /* isThumbnail */),
2755 mWmService.mSurfaceAnimationRunner);
Evan Rosky966759f2019-01-15 10:33:58 -08002756 if (mThumbnail != null) {
2757 thumbnailAdapter = new LocalAnimationAdapter(
2758 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
Evan Roskycf76bed2019-01-15 10:33:58 -08002759 getDisplayContent().getDisplayInfo(), durationScale,
Evan Rosky966759f2019-01-15 10:33:58 -08002760 true /* isAppAnimation */, true /* isThumbnail */),
2761 mWmService.mSurfaceAnimationRunner);
2762 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002763 mTransit = transit;
2764 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002765 } else {
Vishnu Naira2977262018-07-26 13:31:26 -07002766 mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM);
2767
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002768 final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
2769 if (a != null) {
Lucas Dupin95acf432019-04-29 17:55:38 -07002770 // Only apply corner radius to animation if we're not in multi window mode.
2771 // We don't want rounded corners when in pip or split screen.
2772 final float windowCornerRadius = !inMultiWindowMode()
2773 ? getDisplayContent().getWindowCornerRadius()
2774 : 0;
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002775 adapter = new LocalAnimationAdapter(
2776 new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
lumark588a3e82018-07-20 18:53:54 +08002777 getDisplayContent().mAppTransition.canSkipFirstFrame(),
Vishnu Naira2977262018-07-26 13:31:26 -07002778 appStackClipMode,
Lucas Dupin3e1dc202018-12-02 15:14:20 -08002779 true /* isAppAnimation */,
Lucas Dupin95acf432019-04-29 17:55:38 -07002780 windowCornerRadius),
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002781 mWmService.mSurfaceAnimationRunner);
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002782 if (a.getZAdjustment() == Animation.ZORDER_TOP) {
2783 mNeedsZBoost = true;
2784 }
2785 mTransit = transit;
lumark588a3e82018-07-20 18:53:54 +08002786 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002787 } else {
2788 adapter = null;
chaviw23ee71c2017-12-18 11:29:41 -08002789 }
Jorim Jaggi33a701a2017-12-01 14:58:18 +01002790 }
2791 if (adapter != null) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002792 startAnimation(getPendingTransaction(), adapter, !isVisible());
Jorim Jaggi82c17862018-02-21 17:50:18 +01002793 if (adapter.getShowWallpaper()) {
2794 mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2795 }
Evan Rosky2289ba12018-11-19 18:28:18 -08002796 if (thumbnailAdapter != null) {
2797 mThumbnail.startAnimation(
2798 getPendingTransaction(), thumbnailAdapter, !isVisible());
2799 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002800 }
2801 } else {
2802 cancelAnimation();
2803 }
2804 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2805
2806 return isReallyAnimating();
2807 }
2808
2809 private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
2810 boolean isVoiceInteraction) {
2811 final DisplayContent displayContent = getTask().getDisplayContent();
2812 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2813 final int width = displayInfo.appWidth;
2814 final int height = displayInfo.appHeight;
Adrian Roosb125e0b2019-10-02 14:55:14 +02002815 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
2816 "applyAnimation: atoken=%s", this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002817
2818 // Determine the visible rect to calculate the thumbnail clip
2819 final WindowState win = findMainWindow();
2820 final Rect frame = new Rect(0, 0, width, height);
2821 final Rect displayFrame = new Rect(0, 0,
2822 displayInfo.logicalWidth, displayInfo.logicalHeight);
2823 final Rect insets = new Rect();
2824 final Rect stableInsets = new Rect();
2825 Rect surfaceInsets = null;
2826 final boolean freeform = win != null && win.inFreeformWindowingMode();
2827 if (win != null) {
2828 // Containing frame will usually cover the whole screen, including dialog windows.
2829 // For freeform workspace windows it will not cover the whole screen and it also
2830 // won't exactly match the final freeform window frame (e.g. when overlapping with
2831 // the status bar). In that case we need to use the final frame.
2832 if (freeform) {
chaviw492139a2018-07-16 16:07:35 -07002833 frame.set(win.getFrameLw());
Adrian Roos4d18a2e2017-12-19 19:08:05 +01002834 } else if (win.isLetterboxedAppWindow()) {
2835 frame.set(getTask().getBounds());
Winson Chungc1674272018-02-21 10:15:17 -08002836 } else if (win.isDockedResizing()) {
2837 // If we are animating while docked resizing, then use the stack bounds as the
2838 // animation target (which will be different than the task bounds)
2839 frame.set(getTask().getParent().getBounds());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002840 } else {
chaviw553b0212018-07-12 13:37:01 -07002841 frame.set(win.getContainingFrame());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002842 }
2843 surfaceInsets = win.getAttrs().surfaceInsets;
Adrian Roos20e07892018-02-23 19:12:01 +01002844 // XXX(b/72757033): These are insets relative to the window frame, but we're really
2845 // interested in the insets relative to the frame we chose in the if-blocks above.
chaviw9c81e632018-07-31 11:17:52 -07002846 win.getContentInsets(insets);
2847 win.getStableInsets(stableInsets);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002848 }
2849
2850 if (mLaunchTaskBehind) {
2851 // Differentiate the two animations. This one which is briefly on the screen
2852 // gets the !enter animation, and the other activity which remains on the
2853 // screen gets the enter animation. Both appear in the mOpeningApps set.
2854 enter = false;
2855 }
Adrian Roosb125e0b2019-10-02 14:55:14 +02002856 ProtoLog.d(WM_DEBUG_APP_TRANSITIONS,
2857 "Loading animation for app transition. transit=%s enter=%b frame=%s insets=%s "
2858 + "surfaceInsets=%s",
2859 AppTransition.appTransitionToString(transit), enter, frame, insets, surfaceInsets);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002860 final Configuration displayConfig = displayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08002861 final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002862 displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
2863 surfaceInsets, stableInsets, isVoiceInteraction, freeform, getTask().mTaskId);
2864 if (a != null) {
2865 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
2866 final int containingWidth = frame.width();
2867 final int containingHeight = frame.height();
2868 a.initialize(containingWidth, containingHeight, width, height);
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002869 a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked());
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002870 }
2871 return a;
2872 }
2873
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002874 @Override
Jorim Jaggi6de61012018-03-19 14:53:23 +01002875 public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
2876 return mAnimatingAppWindowTokenRegistry != null
2877 && mAnimatingAppWindowTokenRegistry.notifyAboutToFinish(
2878 this, endDeferFinishCallback);
2879 }
2880
2881 @Override
lumarkf6f34942019-04-29 16:56:50 +08002882 public void onAnimationLeashLost(Transaction t) {
2883 super.onAnimationLeashLost(t);
Vishnu Naira2977262018-07-26 13:31:26 -07002884 if (mAnimationBoundsLayer != null) {
Robert Carr71200f22019-02-05 09:44:53 -08002885 t.remove(mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002886 mAnimationBoundsLayer = null;
2887 }
2888
Jorim Jaggi6de61012018-03-19 14:53:23 +01002889 if (mAnimatingAppWindowTokenRegistry != null) {
2890 mAnimatingAppWindowTokenRegistry.notifyFinished(this);
2891 }
2892 }
2893
2894 @Override
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002895 protected void setLayer(Transaction t, int layer) {
2896 if (!mSurfaceAnimator.hasLeash()) {
2897 t.setLayer(mSurfaceControl, layer);
2898 }
2899 }
2900
2901 @Override
2902 protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
2903 if (!mSurfaceAnimator.hasLeash()) {
2904 t.setRelativeLayer(mSurfaceControl, relativeTo, layer);
2905 }
2906 }
2907
2908 @Override
2909 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
2910 if (!mSurfaceAnimator.hasLeash()) {
Robert Carr10584fa2019-01-14 15:55:19 -08002911 t.reparent(mSurfaceControl, newParent);
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002912 }
2913 }
2914
2915 @Override
2916 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002917 // The leash is parented to the animation layer. We need to preserve the z-order by using
2918 // the prefix order index, but we boost if necessary.
Robert Carrb9506032018-02-13 13:54:00 -08002919 int layer = 0;
2920 if (!inPinnedWindowingMode()) {
2921 layer = getPrefixOrderIndex();
2922 } else {
2923 // Pinned stacks have animations take place within themselves rather than an animation
2924 // layer so we need to preserve the order relative to the stack (e.g. the order of our
2925 // task/parent).
2926 layer = getParent().getPrefixOrderIndex();
2927 }
2928
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002929 if (mNeedsZBoost) {
2930 layer += Z_BOOST_BASE;
2931 }
Jorim Jaggi9cd99132019-04-24 17:41:35 +02002932 if (!mNeedsAnimationBoundsLayer) {
chaviw619da692019-06-10 15:39:40 -07002933 t.setLayer(leash, layer);
Jorim Jaggi9cd99132019-04-24 17:41:35 +02002934 }
Robert Carr2f8aa392018-01-31 14:46:51 -08002935
2936 final DisplayContent dc = getDisplayContent();
Jorim Jaggibe418292018-03-26 16:14:12 +02002937 dc.assignStackOrdering();
Evan Rosky2289ba12018-11-19 18:28:18 -08002938
2939 if (leash == mTransitChangeLeash) {
2940 // This is a temporary state so skip any animation notifications
2941 return;
2942 } else if (mTransitChangeLeash != null) {
2943 // unparent mTransitChangeLeash for clean-up
Evan Rosky25b56192019-02-06 16:10:56 -08002944 clearChangeLeash(t, false /* cancel */);
Evan Rosky2289ba12018-11-19 18:28:18 -08002945 }
2946
Jorim Jaggi6de61012018-03-19 14:53:23 +01002947 if (mAnimatingAppWindowTokenRegistry != null) {
2948 mAnimatingAppWindowTokenRegistry.notifyStarting(this);
2949 }
Vishnu Naira2977262018-07-26 13:31:26 -07002950
2951 // If the animation needs to be cropped then an animation bounds layer is created as a child
2952 // of the pinned stack or animation layer. The leash is then reparented to this new layer.
2953 if (mNeedsAnimationBoundsLayer) {
Evan Rosky7735d352019-03-18 17:27:27 -07002954 mTmpRect.setEmpty();
2955 final Task task = getTask();
2956 if (getDisplayContent().mAppTransitionController.isTransitWithinTask(
2957 getTransit(), task)) {
2958 task.getBounds(mTmpRect);
2959 } else {
2960 final TaskStack stack = getStack();
2961 if (stack == null) {
2962 return;
2963 }
2964 // Set clip rect to stack bounds.
2965 stack.getBounds(mTmpRect);
Vishnu Naira2977262018-07-26 13:31:26 -07002966 }
2967 mAnimationBoundsLayer = createAnimationBoundsLayer(t);
2968
Vishnu Naira2977262018-07-26 13:31:26 -07002969 // Crop to stack bounds.
2970 t.setWindowCrop(mAnimationBoundsLayer, mTmpRect);
Jorim Jaggi9cd99132019-04-24 17:41:35 +02002971 t.setLayer(mAnimationBoundsLayer, layer);
Vishnu Naira2977262018-07-26 13:31:26 -07002972
2973 // Reparent leash to animation bounds layer.
Robert Carr10584fa2019-01-14 15:55:19 -08002974 t.reparent(leash, mAnimationBoundsLayer);
Vishnu Naira2977262018-07-26 13:31:26 -07002975 }
Jorim Jaggi619c9f72017-12-19 18:04:29 +01002976 }
2977
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002978 /**
2979 * This must be called while inside a transaction.
2980 */
2981 void showAllWindowsLocked() {
2982 forAllWindows(windowState -> {
2983 if (DEBUG_VISIBILITY) Slog.v(TAG, "performing show on: " + windowState);
2984 windowState.performShowLocked();
2985 }, false /* traverseTopToBottom */);
Jorim Jaggia5e10572017-11-15 14:36:26 +01002986 }
2987
2988 @Override
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002989 protected void onAnimationFinished() {
2990 super.onAnimationFinished();
2991
Ian8b2822e2019-05-14 11:59:02 -07002992 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#onAnimationFinished");
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002993 mTransit = TRANSIT_UNSET;
2994 mTransitFlags = 0;
Jorim Jaggib0fc8172017-11-23 17:04:08 +00002995 mNeedsZBoost = false;
Vishnu Naira2977262018-07-26 13:31:26 -07002996 mNeedsAnimationBoundsLayer = false;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002997
2998 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER,
2999 "AppWindowToken");
3000
Jorim Jaggi988f6682017-11-17 17:46:43 +01003001 clearThumbnail();
Jorim Jaggi752cd822018-03-29 16:29:18 +02003002 setClientHidden(isHidden() && hiddenRequested);
Jorim Jaggi988f6682017-11-17 17:46:43 +01003003
lumarkff0ab692018-11-05 20:32:30 +08003004 getDisplayContent().computeImeTargetIfNeeded(this);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003005
3006 if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + this
3007 + ": reportedVisible=" + reportedVisible
3008 + " okToDisplay=" + okToDisplay()
3009 + " okToAnimate=" + okToAnimate()
3010 + " startingDisplayed=" + startingDisplayed);
3011
Evan Rosky2289ba12018-11-19 18:28:18 -08003012 // clean up thumbnail window
3013 if (mThumbnail != null) {
3014 mThumbnail.destroy();
3015 mThumbnail = null;
3016 }
3017
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003018 // WindowState.onExitAnimationDone might modify the children list, so make a copy and then
3019 // traverse the copy.
3020 final ArrayList<WindowState> children = new ArrayList<>(mChildren);
3021 children.forEach(WindowState::onExitAnimationDone);
3022
lumark588a3e82018-07-20 18:53:54 +08003023 getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003024 scheduleAnimation();
Jorim Jaggi9b5e3312019-03-01 18:08:00 +01003025
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08003026 if (mAtmService.mRootActivityContainer.allResumedActivitiesIdle()
3027 || mAtmService.mStackSupervisor.isStoppingNoHistoryActivity()) {
3028 // If all activities are already idle or there is an activity that must be
3029 // stopped immediately after visible, then we now need to make sure we perform
3030 // the full stop of this activity. This is because we won't do that while they are still
3031 // waiting for the animation to finish.
3032 if (mAtmService.mStackSupervisor.mStoppingActivities.contains(this)) {
3033 mAtmService.mStackSupervisor.scheduleIdleLocked();
3034 }
3035 } else {
3036 // Instead of doing the full stop routine here, let's just hide any activities
3037 // we now can, and let them stop when the normal idle happens.
3038 mAtmService.mStackSupervisor.processStoppingActivitiesLocked(null /* idleActivity */,
3039 false /* remove */, true /* processPausingActivities */);
3040 }
Ian8b2822e2019-05-14 11:59:02 -07003041 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003042 }
3043
3044 @Override
3045 boolean isAppAnimating() {
3046 return isSelfAnimating();
3047 }
3048
3049 @Override
3050 boolean isSelfAnimating() {
3051 // If we are about to start a transition, we also need to be considered animating.
3052 return isWaitingForTransitionStart() || isReallyAnimating();
3053 }
3054
3055 /**
3056 * @return True if and only if we are actually running an animation. Note that
3057 * {@link #isSelfAnimating} also returns true if we are waiting for an animation to
3058 * start.
3059 */
3060 private boolean isReallyAnimating() {
3061 return super.isSelfAnimating();
3062 }
3063
Evan Rosky25b56192019-02-06 16:10:56 -08003064 /**
3065 * @param cancel {@code true} if clearing the leash due to cancelling instead of transferring
3066 * to another leash.
3067 */
3068 private void clearChangeLeash(Transaction t, boolean cancel) {
3069 if (mTransitChangeLeash == null) {
3070 return;
3071 }
3072 if (cancel) {
3073 clearThumbnail();
3074 SurfaceControl sc = getSurfaceControl();
3075 SurfaceControl parentSc = getParentSurfaceControl();
3076 // Don't reparent if surface is getting destroyed
3077 if (parentSc != null && sc != null) {
3078 t.reparent(sc, getParentSurfaceControl());
3079 }
3080 }
3081 t.hide(mTransitChangeLeash);
Evan Rosky08e20932019-05-14 10:54:07 -07003082 t.remove(mTransitChangeLeash);
Evan Rosky25b56192019-02-06 16:10:56 -08003083 mTransitChangeLeash = null;
3084 if (cancel) {
lumarkf6f34942019-04-29 16:56:50 +08003085 onAnimationLeashLost(t);
Evan Rosky25b56192019-02-06 16:10:56 -08003086 }
3087 }
3088
Jorim Jaggi988f6682017-11-17 17:46:43 +01003089 @Override
3090 void cancelAnimation() {
Evan Rosky2289ba12018-11-19 18:28:18 -08003091 cancelAnimationOnly();
Jorim Jaggi988f6682017-11-17 17:46:43 +01003092 clearThumbnail();
Evan Rosky25b56192019-02-06 16:10:56 -08003093 clearChangeLeash(getPendingTransaction(), true /* cancel */);
Evan Rosky2289ba12018-11-19 18:28:18 -08003094 }
3095
3096 /**
3097 * This only cancels the animation. It doesn't do other teardown like cleaning-up thumbnail
3098 * or interim leashes.
3099 * <p>
3100 * Used when canceling in preparation for starting a new animation.
3101 */
3102 void cancelAnimationOnly() {
3103 super.cancelAnimation();
Jorim Jaggi988f6682017-11-17 17:46:43 +01003104 }
3105
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003106 boolean isWaitingForTransitionStart() {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08003107 final DisplayContent dc = getDisplayContent();
3108 // TODO: Test for null can be removed once unification is done.
3109 if (dc == null) return false;
3110 return dc.mAppTransition.isTransitionSet()
3111 && (dc.mOpeningApps.contains(this)
3112 || dc.mClosingApps.contains(this)
3113 || dc.mChangingApps.contains(this));
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003114 }
3115
3116 public int getTransit() {
3117 return mTransit;
3118 }
3119
3120 int getTransitFlags() {
3121 return mTransitFlags;
3122 }
3123
Jorim Jaggi988f6682017-11-17 17:46:43 +01003124 void attachThumbnailAnimation() {
3125 if (!isReallyAnimating()) {
3126 return;
3127 }
3128 final int taskId = getTask().mTaskId;
3129 final GraphicBuffer thumbnailHeader =
lumark588a3e82018-07-20 18:53:54 +08003130 getDisplayContent().mAppTransition.getAppTransitionThumbnailHeader(taskId);
Jorim Jaggi988f6682017-11-17 17:46:43 +01003131 if (thumbnailHeader == null) {
Adrian Roosb125e0b2019-10-02 14:55:14 +02003132 ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, "No thumbnail header bitmap for: %d", taskId);
Jorim Jaggi988f6682017-11-17 17:46:43 +01003133 return;
3134 }
3135 clearThumbnail();
Vishnu Nair33197392019-08-30 10:29:37 -07003136 mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory, getPendingTransaction(),
3137 this, thumbnailHeader);
Jorim Jaggi988f6682017-11-17 17:46:43 +01003138 mThumbnail.startAnimation(getPendingTransaction(), loadThumbnailAnimation(thumbnailHeader));
3139 }
3140
Tony Mak64b8d562017-12-28 17:44:02 +00003141 /**
3142 * Attaches a surface with a thumbnail for the
3143 * {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation.
3144 */
3145 void attachCrossProfileAppsThumbnailAnimation() {
3146 if (!isReallyAnimating()) {
3147 return;
3148 }
3149 clearThumbnail();
3150
3151 final WindowState win = findMainWindow();
3152 if (win == null) {
3153 return;
3154 }
chaviw492139a2018-07-16 16:07:35 -07003155 final Rect frame = win.getFrameLw();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08003156 final int thumbnailDrawableRes = getTask().mUserId == mWmService.mCurrentUserId
Tony Mak64b8d562017-12-28 17:44:02 +00003157 ? R.drawable.ic_account_circle
Tony Makda4af232018-04-27 11:01:10 +01003158 : R.drawable.ic_corp_badge;
Tony Mak64b8d562017-12-28 17:44:02 +00003159 final GraphicBuffer thumbnail =
lumark588a3e82018-07-20 18:53:54 +08003160 getDisplayContent().mAppTransition
Tony Mak64b8d562017-12-28 17:44:02 +00003161 .createCrossProfileAppsThumbnail(thumbnailDrawableRes, frame);
3162 if (thumbnail == null) {
3163 return;
3164 }
Vishnu Nair33197392019-08-30 10:29:37 -07003165 mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory,
3166 getPendingTransaction(), this, thumbnail);
Tony Mak64b8d562017-12-28 17:44:02 +00003167 final Animation animation =
lumark588a3e82018-07-20 18:53:54 +08003168 getDisplayContent().mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(
chaviw492139a2018-07-16 16:07:35 -07003169 win.getFrameLw());
Tony Mak64b8d562017-12-28 17:44:02 +00003170 mThumbnail.startAnimation(getPendingTransaction(), animation, new Point(frame.left,
3171 frame.top));
3172 }
3173
Jorim Jaggi988f6682017-11-17 17:46:43 +01003174 private Animation loadThumbnailAnimation(GraphicBuffer thumbnailHeader) {
3175 final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
3176
3177 // If this is a multi-window scenario, we use the windows frame as
3178 // destination of the thumbnail header animation. If this is a full screen
3179 // window scenario, we use the whole display as the target.
3180 WindowState win = findMainWindow();
3181 Rect appRect = win != null ? win.getContentFrameLw() :
3182 new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
chaviw9c81e632018-07-31 11:17:52 -07003183 final Rect insets = win != null ? win.getContentInsets() : null;
Jorim Jaggi988f6682017-11-17 17:46:43 +01003184 final Configuration displayConfig = mDisplayContent.getConfiguration();
lumark588a3e82018-07-20 18:53:54 +08003185 return getDisplayContent().mAppTransition.createThumbnailAspectScaleAnimationLocked(
Jorim Jaggi988f6682017-11-17 17:46:43 +01003186 appRect, insets, thumbnailHeader, getTask().mTaskId, displayConfig.uiMode,
3187 displayConfig.orientation);
3188 }
3189
3190 private void clearThumbnail() {
3191 if (mThumbnail == null) {
3192 return;
3193 }
3194 mThumbnail.destroy();
3195 mThumbnail = null;
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003196 }
3197
Jorim Jaggif84e2f62018-01-16 14:17:59 +01003198 void registerRemoteAnimations(RemoteAnimationDefinition definition) {
3199 mRemoteAnimationDefinition = definition;
3200 }
3201
3202 RemoteAnimationDefinition getRemoteAnimationDefinition() {
3203 return mRemoteAnimationDefinition;
3204 }
3205
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003206 @Override
3207 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
3208 super.dump(pw, prefix, dumpAll);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003209 if (appToken != null) {
Wale Ogunwale72919d22016-12-08 18:58:50 -08003210 pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003211 }
Winson Chung48b25652018-10-22 14:04:30 -07003212 pw.println(prefix + "component=" + mActivityComponent.flattenToShortString());
Bryce Lee7fbeb8a2017-03-02 08:42:30 -08003213 pw.print(prefix); pw.print("task="); pw.println(getTask());
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -07003214 pw.print(prefix); pw.print(" mOccludesParent="); pw.print(mOccludesParent);
Wale Ogunwale51362492016-09-08 17:49:17 -07003215 pw.print(" mOrientation="); pw.println(mOrientation);
Wale Ogunwale89973222017-04-23 18:39:45 -07003216 pw.println(prefix + "hiddenRequested=" + hiddenRequested + " mClientHidden=" + mClientHidden
3217 + ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "")
3218 + " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible);
Craig Mautner59431632012-04-04 11:56:44 -07003219 if (paused) {
3220 pw.print(prefix); pw.print("paused="); pw.println(paused);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003221 }
Wale Ogunwale9017ec02016-02-25 08:55:25 -08003222 if (mAppStopped) {
3223 pw.print(prefix); pw.print("mAppStopped="); pw.println(mAppStopped);
3224 }
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07003225 if (mNumInterestingWindows != 0 || mNumDrawnWindows != 0
Jorim Jaggib0fc8172017-11-23 17:04:08 +00003226 || allDrawn || mLastAllDrawn) {
Wale Ogunwale9d9d8f12016-09-28 15:29:59 -07003227 pw.print(prefix); pw.print("mNumInterestingWindows=");
3228 pw.print(mNumInterestingWindows);
3229 pw.print(" mNumDrawnWindows="); pw.print(mNumDrawnWindows);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003230 pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
Craig Mautner6fbda632012-07-03 09:26:39 -07003231 pw.print(" allDrawn="); pw.print(allDrawn);
Jorim Jaggib0fc8172017-11-23 17:04:08 +00003232 pw.print(" lastAllDrawn="); pw.print(mLastAllDrawn);
Craig Mautner6fbda632012-07-03 09:26:39 -07003233 pw.println(")");
3234 }
3235 if (inPendingTransaction) {
3236 pw.print(prefix); pw.print("inPendingTransaction=");
3237 pw.println(inPendingTransaction);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003238 }
chaviwa8f07a72019-05-01 16:25:39 -07003239 if (mStartingData != null || removed || firstWindowDrawn || mIsExiting) {
3240 pw.print(prefix); pw.print("startingData="); pw.print(mStartingData);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003241 pw.print(" removed="); pw.print(removed);
Craig Mautner3d7ca312015-01-08 10:56:00 -08003242 pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
Craig Mautner799bc1d2015-01-14 10:33:48 -08003243 pw.print(" mIsExiting="); pw.println(mIsExiting);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003244 }
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08003245 if (startingWindow != null || startingSurface != null
Wale Ogunwale6c459212017-05-17 08:56:03 -07003246 || startingDisplayed || startingMoved || mHiddenSetFromTransferredStartingWindow) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003247 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
Jorim Jaggiba41f4b2016-12-14 17:43:07 -08003248 pw.print(" startingSurface="); pw.print(startingSurface);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003249 pw.print(" startingDisplayed="); pw.print(startingDisplayed);
Wale Ogunwale6c459212017-05-17 08:56:03 -07003250 pw.print(" startingMoved="); pw.print(startingMoved);
3251 pw.println(" mHiddenSetFromTransferredStartingWindow="
3252 + mHiddenSetFromTransferredStartingWindow);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003253 }
Jorim Jaggi0429f352015-12-22 16:29:16 +01003254 if (!mFrozenBounds.isEmpty()) {
Chong Zhangd78ddb42016-03-02 17:01:14 -08003255 pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
Jorim Jaggi26c8c422016-05-09 19:57:25 -07003256 pw.print(prefix); pw.print("mFrozenMergedConfig="); pw.println(mFrozenMergedConfig);
Chong Zhangd78ddb42016-03-02 17:01:14 -08003257 }
3258 if (mPendingRelaunchCount != 0) {
3259 pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount);
Jorim Jaggi0429f352015-12-22 16:29:16 +01003260 }
Riddle Hsub398da32019-01-21 21:48:16 +08003261 if (mSizeCompatScale != 1f || mSizeCompatBounds != null) {
3262 pw.println(prefix + "mSizeCompatScale=" + mSizeCompatScale + " mSizeCompatBounds="
3263 + mSizeCompatBounds);
3264 }
Wale Ogunwalee287e192017-04-21 09:30:12 -07003265 if (mRemovingFromDisplay) {
3266 pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay);
3267 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003268 }
3269
3270 @Override
3271 void setHidden(boolean hidden) {
3272 super.setHidden(hidden);
3273 scheduleAnimation();
3274 }
3275
3276 @Override
3277 void prepareSurfaces() {
3278 // isSelfAnimating also returns true when we are about to start a transition, so we need
3279 // to check super here.
3280 final boolean reallyAnimating = super.isSelfAnimating();
3281 final boolean show = !isHidden() || reallyAnimating;
Robert Carrd8e4fb72019-01-31 11:14:30 -08003282
3283 if (mSurfaceControl != null) {
3284 if (show && !mLastSurfaceShowing) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003285 getPendingTransaction().show(mSurfaceControl);
Robert Carrd8e4fb72019-01-31 11:14:30 -08003286 } else if (!show && mLastSurfaceShowing) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003287 getPendingTransaction().hide(mSurfaceControl);
Robert Carrd8e4fb72019-01-31 11:14:30 -08003288 }
Jorim Jaggi4d1835d2017-08-31 17:28:27 +02003289 }
Jorim Jaggi988f6682017-11-17 17:46:43 +01003290 if (mThumbnail != null) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003291 mThumbnail.setShowing(getPendingTransaction(), show);
Jorim Jaggi988f6682017-11-17 17:46:43 +01003292 }
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003293 mLastSurfaceShowing = show;
3294 super.prepareSurfaces();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003295 }
3296
Jorim Jaggi77d0f36c2018-03-16 17:49:49 +01003297 /**
3298 * @return Whether our {@link #getSurfaceControl} is currently showing.
3299 */
3300 boolean isSurfaceShowing() {
3301 return mLastSurfaceShowing;
3302 }
3303
Jorim Jaggib0fc8172017-11-23 17:04:08 +00003304 boolean isFreezingScreen() {
3305 return mFreezingScreen;
3306 }
3307
3308 @Override
3309 boolean needsZBoost() {
3310 return mNeedsZBoost || super.needsZBoost();
3311 }
3312
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07003313 @CallSuper
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003314 @Override
Nataniel Borges023ecb52019-01-16 14:15:43 -08003315 public void writeToProto(ProtoOutputStream proto, long fieldId,
3316 @WindowTraceLogLevel int logLevel) {
3317 // Critical log level logs only visible elements to mitigate performance overheard
3318 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
3319 return;
3320 }
3321
Steven Timotiusaf03df62017-07-18 16:56:43 -07003322 final long token = proto.start(fieldId);
3323 writeNameToProto(proto, NAME);
Nataniel Borges023ecb52019-01-16 14:15:43 -08003324 super.writeToProto(proto, WINDOW_TOKEN, logLevel);
Vishnu Nair04ab4392018-01-10 11:00:06 -08003325 proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing);
3326 proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart());
3327 proto.write(IS_REALLY_ANIMATING, isReallyAnimating());
3328 if (mThumbnail != null){
3329 mThumbnail.writeToProto(proto, THUMBNAIL);
3330 }
Wale Ogunwale83b8a6b2019-06-27 20:15:15 -07003331 proto.write(FILLS_PARENT, mOccludesParent);
Vishnu Nair04ab4392018-01-10 11:00:06 -08003332 proto.write(APP_STOPPED, mAppStopped);
3333 proto.write(HIDDEN_REQUESTED, hiddenRequested);
3334 proto.write(CLIENT_HIDDEN, mClientHidden);
3335 proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient);
3336 proto.write(REPORTED_DRAWN, reportedDrawn);
3337 proto.write(REPORTED_VISIBLE, reportedVisible);
3338 proto.write(NUM_INTERESTING_WINDOWS, mNumInterestingWindows);
3339 proto.write(NUM_DRAWN_WINDOWS, mNumDrawnWindows);
3340 proto.write(ALL_DRAWN, allDrawn);
3341 proto.write(LAST_ALL_DRAWN, mLastAllDrawn);
3342 proto.write(REMOVED, removed);
Nataniel Borges023ecb52019-01-16 14:15:43 -08003343 if (startingWindow != null) {
Vishnu Nair04ab4392018-01-10 11:00:06 -08003344 startingWindow.writeIdentifierToProto(proto, STARTING_WINDOW);
3345 }
3346 proto.write(STARTING_DISPLAYED, startingDisplayed);
3347 proto.write(STARTING_MOVED, startingMoved);
3348 proto.write(HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW,
3349 mHiddenSetFromTransferredStartingWindow);
3350 for (Rect bounds : mFrozenBounds) {
3351 bounds.writeToProto(proto, FROZEN_BOUNDS);
3352 }
Steven Timotiusaf03df62017-07-18 16:56:43 -07003353 proto.end(token);
3354 }
3355
3356 void writeNameToProto(ProtoOutputStream proto, long fieldId) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08003357 if (appToken != null) {
Steven Timotiusaf03df62017-07-18 16:56:43 -07003358 proto.write(fieldId, appToken.getName());
Steven Timotiusaf03df62017-07-18 16:56:43 -07003359 }
3360 }
3361
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08003362 void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) {
3363 final long token = proto.start(fieldId);
3364 proto.write(HASH_CODE, System.identityHashCode(this));
3365 proto.write(USER_ID, mUserId);
3366 proto.write(TITLE, ((ActivityRecord) this).intent.getComponent().flattenToShortString());
3367 proto.end(token);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08003368 }
Adrian Roos20e07892018-02-23 19:12:01 +01003369
3370 Rect getLetterboxInsets() {
3371 if (mLetterbox != null) {
3372 return mLetterbox.getInsets();
3373 } else {
3374 return new Rect();
3375 }
3376 }
Adrian Roos23df3a32018-03-15 15:41:13 +01003377
Riddle Hsu69de5fb2019-02-23 01:19:50 +08003378 /** Gets the inner bounds of letterbox. The bounds will be empty if there is no letterbox. */
3379 void getLetterboxInnerBounds(Rect outBounds) {
3380 if (mLetterbox != null) {
3381 outBounds.set(mLetterbox.getInnerFrame());
3382 } else {
3383 outBounds.setEmpty();
3384 }
3385 }
3386
Adrian Roos23df3a32018-03-15 15:41:13 +01003387 /**
Riddle Hsu69de5fb2019-02-23 01:19:50 +08003388 * @return {@code true} if there is a letterbox and any part of that letterbox overlaps with
Adrian Roos23df3a32018-03-15 15:41:13 +01003389 * the given {@code rect}.
3390 */
3391 boolean isLetterboxOverlappingWith(Rect rect) {
3392 return mLetterbox != null && mLetterbox.isOverlappingWith(rect);
3393 }
chaviw4ad54912018-05-30 11:05:44 -07003394
3395 /**
3396 * Sets if this AWT is in the process of closing or entering PIP.
3397 * {@link #mWillCloseOrEnterPip}}
3398 */
3399 void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
3400 mWillCloseOrEnterPip = willCloseOrEnterPip;
3401 }
3402
3403 /**
3404 * Returns whether this AWT is considered closing. Conditions are either
3405 * 1. Is this app animating and was requested to be hidden
3406 * 2. App is delayed closing since it might enter PIP.
3407 */
3408 boolean isClosingOrEnteringPip() {
3409 return (isAnimating() && hiddenRequested) || mWillCloseOrEnterPip;
3410 }
Jorim Jaggiaf0d6d22018-06-08 15:25:35 +02003411
3412 /**
3413 * @return Whether we are allowed to show non-starting windows at the moment. We disallow
3414 * showing windows during transitions in case we have windows that have wide-color-gamut
3415 * color mode set to avoid jank in the middle of the transition.
3416 */
3417 boolean canShowWindows() {
3418 return allDrawn && !(isReallyAnimating() && hasNonDefaultColorWindow());
3419 }
3420
3421 /**
3422 * @return true if we have a window that has a non-default color mode set; false otherwise.
3423 */
3424 private boolean hasNonDefaultColorWindow() {
3425 return forAllWindows(ws -> ws.mAttrs.getColorMode() != COLOR_MODE_DEFAULT,
3426 true /* topToBottom */);
3427 }
lumark588a3e82018-07-20 18:53:54 +08003428
chaviwdcf76ec2019-01-11 16:48:46 -08003429 private void updateColorTransform() {
3430 if (mSurfaceControl != null && mLastAppSaturationInfo != null) {
Tiger Huanged6794e2019-05-07 20:07:59 +08003431 getPendingTransaction().setColorTransform(mSurfaceControl,
3432 mLastAppSaturationInfo.mMatrix, mLastAppSaturationInfo.mTranslation);
chaviwdcf76ec2019-01-11 16:48:46 -08003433 mWmService.scheduleAnimationLocked();
3434 }
3435 }
3436
3437 private static class AppSaturationInfo {
3438 float[] mMatrix = new float[9];
3439 float[] mTranslation = new float[3];
3440
3441 void setSaturation(@Size(9) float[] matrix, @Size(3) float[] translation) {
3442 System.arraycopy(matrix, 0, mMatrix, 0, mMatrix.length);
3443 System.arraycopy(translation, 0, mTranslation, 0, mTranslation.length);
3444 }
3445 }
Jeff Browne9bdb312012-04-05 15:30:10 -07003446}