blob: 77530fb629bcd5b9715e01eb634bc51a71211af2 [file] [log] [blame]
Wale Ogunwaled63594a2016-07-18 07:48:30 -07001/*
2 * Copyright (C) 2016 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
Jorim Jaggi612bb882017-05-16 17:11:18 +020019import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
20import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
21import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -080022import static android.content.pm.ActivityInfo.isFixedOrientationLandscape;
23import static android.content.pm.ActivityInfo.isFixedOrientationPortrait;
24import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
25import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
26import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
lumark19a5d2e2019-10-11 16:19:30 +080027import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
Evan Rosky55bddd82020-01-29 13:07:18 -080028import static android.os.UserHandle.USER_NULL;
Vishnu Nair04ab4392018-01-10 11:00:06 -080029import static android.view.SurfaceControl.Transaction;
Louis Chang7501e332018-08-20 13:08:39 +080030
lumark19a5d2e2019-10-11 16:19:30 +080031import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
lumark8669ef32020-02-10 18:41:57 +080032import static com.android.server.wm.AppTransition.MAX_APP_TRANSITION_DURATION;
Evan Rosky55bddd82020-01-29 13:07:18 -080033import static com.android.server.wm.IdentifierProto.HASH_CODE;
34import static com.android.server.wm.IdentifierProto.TITLE;
35import static com.android.server.wm.IdentifierProto.USER_ID;
lumark19a5d2e2019-10-11 16:19:30 +080036import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
37import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
Vadim Caen1096f112019-12-18 11:44:26 +010038import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
chaviw9177c772020-03-24 11:35:22 -070039import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_ALL;
Issei Suzuki8b995df2020-01-08 12:23:04 +010040import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
lumark9bca6b42019-10-17 18:35:22 +080041import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
42import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
43import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
Vishnu Nairdddc9f52020-03-09 09:37:27 -070044import static com.android.server.wm.WindowContainerChildProto.WINDOW_CONTAINER;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070045import static com.android.server.wm.WindowContainerProto.CONFIGURATION_CONTAINER;
46import static com.android.server.wm.WindowContainerProto.ORIENTATION;
47import static com.android.server.wm.WindowContainerProto.SURFACE_ANIMATOR;
48import static com.android.server.wm.WindowContainerProto.VISIBLE;
Louis Chang7501e332018-08-20 13:08:39 +080049import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
50import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
51import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
lumark19a5d2e2019-10-11 16:19:30 +080052import static com.android.server.wm.WindowManagerService.logWithStack;
lumark85718662019-12-26 22:05:12 +080053import static com.android.server.wm.WindowManagerService.sHierarchicalAnimations;
lumark19a5d2e2019-10-11 16:19:30 +080054import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
Jorim Jaggi612bb882017-05-16 17:11:18 +020055
Wale Ogunwaled63594a2016-07-18 07:48:30 -070056import android.annotation.CallSuper;
Jorim Jaggi391790622018-04-18 15:30:44 +020057import android.annotation.IntDef;
Garfield Tan90b04282018-12-11 14:04:42 -080058import android.annotation.Nullable;
Jorim Jaggi391790622018-04-18 15:30:44 +020059import android.app.WindowConfiguration;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -080060import android.content.pm.ActivityInfo;
Andrii Kulian441e4492016-09-29 15:25:00 -070061import android.content.res.Configuration;
chaviwe07246a2017-12-12 16:18:29 -080062import android.graphics.Point;
63import android.graphics.Rect;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -080064import android.os.Debug;
Garfield Tan90b04282018-12-11 14:04:42 -080065import android.os.IBinder;
lumark19a5d2e2019-10-11 16:19:30 +080066import android.os.Trace;
67import android.util.Pair;
Vishnu Nair04ab4392018-01-10 11:00:06 -080068import android.util.Pools;
Jorim Jaggia5e10572017-11-15 14:36:26 +010069import android.util.Slog;
Vishnu Nair04ab4392018-01-10 11:00:06 -080070import android.util.proto.ProtoOutputStream;
lumark19a5d2e2019-10-11 16:19:30 +080071import android.view.DisplayInfo;
Robert Carrb1579c82017-09-05 14:54:47 -070072import android.view.MagnificationSpec;
Evan Rosky55bddd82020-01-29 13:07:18 -080073import android.view.RemoteAnimationDefinition;
lumark19a5d2e2019-10-11 16:19:30 +080074import android.view.RemoteAnimationTarget;
Robert Carrb1579c82017-09-05 14:54:47 -070075import android.view.SurfaceControl;
Jorim Jaggia5e10572017-11-15 14:36:26 +010076import android.view.SurfaceControl.Builder;
Robert Carrb1579c82017-09-05 14:54:47 -070077import android.view.SurfaceSession;
lumark19a5d2e2019-10-11 16:19:30 +080078import android.view.WindowManager;
79import android.view.animation.Animation;
Wale Ogunwaleadf116e2020-03-27 16:36:01 -070080import android.window.IWindowContainerToken;
81import android.window.WindowContainerToken;
Garfield Tan2f145f22018-11-01 15:27:03 -070082
Evan Rosky65dffa62019-02-04 14:09:53 -080083import com.android.internal.annotations.VisibleForTesting;
Jorim Jaggia5e10572017-11-15 14:36:26 +010084import com.android.internal.util.ToBooleanFunction;
lumark19a5d2e2019-10-11 16:19:30 +080085import com.android.server.protolog.common.ProtoLog;
Jorim Jaggia5e10572017-11-15 14:36:26 +010086import com.android.server.wm.SurfaceAnimator.Animatable;
Issei Suzuki8b995df2020-01-08 12:23:04 +010087import com.android.server.wm.SurfaceAnimator.AnimationType;
88import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
Garfield Tan2f145f22018-11-01 15:27:03 -070089
Jorim Jaggia5e10572017-11-15 14:36:26 +010090import java.io.PrintWriter;
Evan Roskya80f11c2020-01-23 19:17:10 -080091import java.lang.ref.WeakReference;
Yunfan Chen87b5a242019-10-01 17:53:59 +090092import java.util.ArrayList;
Wale Ogunwaled63594a2016-07-18 07:48:30 -070093import java.util.Comparator;
94import java.util.LinkedList;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070095import java.util.function.Consumer;
Wale Ogunwaledfbeed72019-11-20 08:57:39 -080096import java.util.function.Function;
Wale Ogunwaled1880962016-11-08 10:31:59 -080097import java.util.function.Predicate;
Wale Ogunwaled63594a2016-07-18 07:48:30 -070098
99/**
100 * Defines common functionality for classes that can hold windows directly or through their
Wale Ogunwale51362492016-09-08 17:49:17 -0700101 * children in a hierarchy form.
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700102 * The test class is {@link WindowContainerTests} which must be kept up-to-date and ran anytime
103 * changes are made to this class.
104 */
Wale Ogunwale98d62312017-07-12 09:24:56 -0700105class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<E>
Evan Rosky55bddd82020-01-29 13:07:18 -0800106 implements Comparable<WindowContainer>, Animatable, SurfaceFreezer.Freezable,
Robert Carre10ee3d2019-11-11 15:03:15 -0800107 BLASTSyncEngine.TransactionReadyListener {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100108
109 private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowContainer" : TAG_WM;
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700110
Louis Changdc077272019-11-12 16:52:56 +0800111 /** Animation layer that happens above all animating {@link ActivityStack}s. */
Jorim Jaggi391790622018-04-18 15:30:44 +0200112 static final int ANIMATION_LAYER_STANDARD = 0;
113
Louis Changdc077272019-11-12 16:52:56 +0800114 /** Animation layer that happens above all {@link ActivityStack}s. */
Jorim Jaggi391790622018-04-18 15:30:44 +0200115 static final int ANIMATION_LAYER_BOOSTED = 1;
116
117 /**
118 * Animation layer that is reserved for {@link WindowConfiguration#ACTIVITY_TYPE_HOME}
Winson Chung732446a2018-09-19 13:15:17 -0700119 * activities and all activities that are being controlled by the recents animation. This
Louis Changdc077272019-11-12 16:52:56 +0800120 * layer is generally below all {@link ActivityStack}s.
Jorim Jaggi391790622018-04-18 15:30:44 +0200121 */
122 static final int ANIMATION_LAYER_HOME = 2;
123
124 @IntDef(prefix = { "ANIMATION_LAYER_" }, value = {
125 ANIMATION_LAYER_STANDARD,
126 ANIMATION_LAYER_BOOSTED,
127 ANIMATION_LAYER_HOME,
128 })
129 @interface AnimationLayer {}
130
Andrii Kuliand2765632016-12-12 22:26:34 -0800131 static final int POSITION_TOP = Integer.MAX_VALUE;
132 static final int POSITION_BOTTOM = Integer.MIN_VALUE;
133
Andrii Kulian441e4492016-09-29 15:25:00 -0700134 /**
135 * The parent of this window container.
136 * For removing or setting new parent {@link #setParent} should be used, because it also
137 * performs configuration updates based on new parent's settings.
138 */
Jorim Jaggia5e10572017-11-15 14:36:26 +0100139 private WindowContainer<WindowContainer> mParent = null;
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700140
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200141 // Set to true when we are performing a reparenting operation so we only send one
142 // onParentChanged() notification.
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700143 boolean mReparenting;
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200144
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700145 // List of children for this window container. List is in z-order as the children appear on
146 // screen with the top-most window container at the tail of the list.
Jorim Jaggi612bb882017-05-16 17:11:18 +0200147 protected final WindowList<E> mChildren = new WindowList<E>();
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700148
Wale Ogunwale51362492016-09-08 17:49:17 -0700149 // The specified orientation for this window container.
Vadim Caen1096f112019-12-18 11:44:26 +0100150 @ActivityInfo.ScreenOrientation
Wale Ogunwale51362492016-09-08 17:49:17 -0700151 protected int mOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
152
Riddle Hsu6f548e92020-01-13 13:34:09 +0800153 /**
154 * The window container which decides its orientation since the last time
155 * {@link #getOrientation(int) was called.
156 */
157 protected WindowContainer mLastOrientationSource;
158
Wale Ogunwaleee41d4a2016-11-21 08:41:10 -0800159 private final Pools.SynchronizedPool<ForAllWindowsConsumerWrapper> mConsumerWrapperPool =
160 new Pools.SynchronizedPool<>(3);
161
Tiger Huanged6794e2019-05-07 20:07:59 +0800162 // The display this window container is on.
163 protected DisplayContent mDisplayContent;
164
Robert Carrb1579c82017-09-05 14:54:47 -0700165 protected SurfaceControl mSurfaceControl;
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100166 private int mLastLayer = 0;
167 private SurfaceControl mLastRelativeToLayer = null;
Robert Carrb1579c82017-09-05 14:54:47 -0700168
Tiger Huanged6794e2019-05-07 20:07:59 +0800169 // TODO(b/132320879): Remove this from WindowContainers except DisplayContent.
170 private final Transaction mPendingTransaction;
171
Robert Carrb1579c82017-09-05 14:54:47 -0700172 /**
Yunfan Chen87b5a242019-10-01 17:53:59 +0900173 * Windows that clients are waiting to have drawn.
174 */
175 final ArrayList<WindowState> mWaitingForDrawn = new ArrayList<>();
176
177 /**
Robert Carrb1579c82017-09-05 14:54:47 -0700178 * Applied as part of the animation pass in "prepareSurfaces".
179 */
Jorim Jaggia5e10572017-11-15 14:36:26 +0100180 protected final SurfaceAnimator mSurfaceAnimator;
Evan Rosky55bddd82020-01-29 13:07:18 -0800181 final SurfaceFreezer mSurfaceFreezer;
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800182 protected final WindowManagerService mWmService;
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100183
chaviwe07246a2017-12-12 16:18:29 -0800184 private final Point mTmpPos = new Point();
chaviw3e751af2018-01-11 11:22:39 -0800185 protected final Point mLastSurfacePosition = new Point();
chaviwe07246a2017-12-12 16:18:29 -0800186
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100187 /** Total number of elements in this subtree, including our own hierarchy element. */
188 private int mTreeWeight = 1;
189
chaviw7f1fa992018-01-10 13:52:12 -0800190 /**
Vishnu Nairddd80742018-08-21 14:12:46 -0700191 * Indicates whether we are animating and have committed the transaction to reparent our
chaviw7f1fa992018-01-10 13:52:12 -0800192 * surface to the animation leash
193 */
194 private boolean mCommittedReparentToAnimationLeash;
195
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800196 private final Configuration mTmpConfig = new Configuration();
197
lumark9bca6b42019-10-17 18:35:22 +0800198 /** Interface for {@link #isAnimating} to check which cases for the container is animating. */
199 public interface AnimationFlags {
200 /**
201 * A bit flag indicates that {@link #isAnimating} should also return {@code true}
202 * even though the container is not yet animating, but the window container or its
203 * relatives as specified by PARENTS or CHILDREN are part of an {@link AppTransition}
204 * that is pending so an animation starts soon.
205 */
206 int TRANSITION = 1;
207
208 /**
209 * A bit flag indicates that {@link #isAnimating} should also check if one of the
210 * ancestors of the container are animating in addition to the container itself.
211 */
212 int PARENTS = 2;
213
214 /**
215 * A bit flag indicates that {@link #isAnimating} should also check if one of the
216 * descendants of the container are animating in addition to the container itself.
217 */
218 int CHILDREN = 4;
219 }
220
Issei Suzuki25a9e2b2019-08-14 16:46:26 +0200221 /**
222 * Callback which is triggered while changing the parent, after setting up the surface but
223 * before asking the parent to assign child layers.
224 */
225 interface PreAssignChildLayersCallback {
226 void onPreAssignChildLayers();
227 }
228
lumark19a5d2e2019-10-11 16:19:30 +0800229 /**
230 * True if this an AppWindowToken and the activity which created this was launched with
231 * ActivityOptions.setLaunchTaskBehind.
232 *
233 * TODO(b/142617871): We run a special animation when the activity was launched with that
234 * flag, but it's not necessary anymore. Keep the window invisible until the task is explicitly
235 * selected to suppress an animation, and remove this flag.
236 */
237 boolean mLaunchTaskBehind;
238
239 /**
240 * If we are running an animation, this determines the transition type. Must be one of
241 * {@link AppTransition#TransitionFlags}.
242 */
243 int mTransit;
244
245 /**
246 * If we are running an animation, this determines the flags during this animation. Must be a
247 * bitwise combination of AppTransition.TRANSIT_FLAG_* constants.
248 */
249 int mTransitFlags;
250
251 /** Whether this container should be boosted at the top of all its siblings. */
252 @VisibleForTesting boolean mNeedsZBoost;
253
254 /** Layer used to constrain the animation to a container's stack bounds. */
255 SurfaceControl mAnimationBoundsLayer;
256
257 /** Whether this container needs to create mAnimationBoundsLayer for cropping animations. */
258 boolean mNeedsAnimationBoundsLayer;
259
260 /**
261 * This gets used during some open/close transitions as well as during a change transition
262 * where it represents the starting-state snapshot.
263 */
lumarkbc0032a2019-11-01 21:38:13 +0800264 WindowContainerThumbnail mThumbnail;
lumark19a5d2e2019-10-11 16:19:30 +0800265 final Point mTmpPoint = new Point();
266 protected final Rect mTmpRect = new Rect();
267 final Rect mTmpPrevBounds = new Rect();
268
Robert Carr7603dea2019-07-17 13:16:21 -0700269 private MagnificationSpec mLastMagnificationSpec;
270
Evan Rosky226de132020-01-03 18:00:29 -0800271 private boolean mIsFocusable = true;
272
Evan Roskya80f11c2020-01-23 19:17:10 -0800273 /**
274 * Used as a unique, cross-process identifier for this Container. It also serves a minimal
275 * interface to other processes.
276 */
277 RemoteToken mRemoteToken = null;
278
Robert Carre10ee3d2019-11-11 15:03:15 -0800279 BLASTSyncEngine mBLASTSyncEngine = new BLASTSyncEngine();
Rob Carrdb37d582020-03-10 12:31:07 -0700280 SurfaceControl.Transaction mBLASTSyncTransaction;
Robert Carre10ee3d2019-11-11 15:03:15 -0800281 boolean mUsingBLASTSyncTransaction = false;
282 BLASTSyncEngine.TransactionReadyListener mWaitingListener;
283 int mWaitingSyncId;
284
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800285 WindowContainer(WindowManagerService wms) {
286 mWmService = wms;
Vishnu Nair33197392019-08-30 10:29:37 -0700287 mPendingTransaction = wms.mTransactionFactory.get();
Rob Carrdb37d582020-03-10 12:31:07 -0700288 mBLASTSyncTransaction = wms.mTransactionFactory.get();
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800289 mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished, wms);
Evan Rosky55bddd82020-01-29 13:07:18 -0800290 mSurfaceFreezer = new SurfaceFreezer(this, wms);
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100291 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800292
Wale Ogunwale98d62312017-07-12 09:24:56 -0700293 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -0700294 final protected WindowContainer getParent() {
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700295 return mParent;
296 }
297
Wale Ogunwale98d62312017-07-12 09:24:56 -0700298 @Override
Wale Ogunwale61911492017-10-11 08:50:50 -0700299 protected int getChildCount() {
Wale Ogunwale98d62312017-07-12 09:24:56 -0700300 return mChildren.size();
301 }
302
303 @Override
Wale Ogunwale61911492017-10-11 08:50:50 -0700304 protected E getChildAt(int index) {
Wale Ogunwale98d62312017-07-12 09:24:56 -0700305 return mChildren.get(index);
306 }
307
chaviwe07246a2017-12-12 16:18:29 -0800308 @Override
309 public void onConfigurationChanged(Configuration newParentConfig) {
310 super.onConfigurationChanged(newParentConfig);
chaviw2f0567b2018-01-29 16:22:02 -0800311 updateSurfacePosition();
chaviwe07246a2017-12-12 16:18:29 -0800312 scheduleAnimation();
313 }
314
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200315 void reparent(WindowContainer newParent, int position) {
316 if (newParent == null) {
317 throw new IllegalArgumentException("reparent: can't reparent to null " + this);
318 }
319
320 final WindowContainer oldParent = mParent;
321 if (mParent == newParent) {
322 throw new IllegalArgumentException("WC=" + this + " already child of " + mParent);
323 }
324
325 // The display object before reparenting as that might lead to old parent getting removed
326 // from the display if it no longer has any child.
327 final DisplayContent prevDc = oldParent.getDisplayContent();
328 final DisplayContent dc = newParent.getDisplayContent();
329
330 mReparenting = true;
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700331 oldParent.removeChild(this);
Louis Chang2453d062019-11-19 22:30:48 +0800332 newParent.addChild(this, position);
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200333 mReparenting = false;
334
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200335 // Relayout display(s)
336 dc.setLayoutNeeded();
337 if (prevDc != dc) {
338 onDisplayChanged(dc);
339 prevDc.setLayoutNeeded();
340 }
341 getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700342
343 // Send onParentChanged notification here is we disabled sending it in setParent for
344 // reparenting case.
345 onParentChanged(newParent, oldParent);
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200346 }
347
Jorim Jaggia5e10572017-11-15 14:36:26 +0100348 final protected void setParent(WindowContainer<WindowContainer> parent) {
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200349 final WindowContainer oldParent = mParent;
Andrii Kulian441e4492016-09-29 15:25:00 -0700350 mParent = parent;
Wale Ogunwalea38654f2019-11-17 20:37:15 -0800351
352 if (mParent != null) {
353 mParent.onChildAdded(this);
354 }
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200355 if (!mReparenting) {
lumarkbde15132019-12-18 22:29:43 +0800356 if (mParent != null && mParent.mDisplayContent != null
357 && mDisplayContent != mParent.mDisplayContent) {
358 onDisplayChanged(mParent.mDisplayContent);
359 }
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200360 onParentChanged(mParent, oldParent);
361 }
Andrii Kuliand2765632016-12-12 22:26:34 -0800362 }
363
364 /**
365 * Callback that is triggered when @link WindowContainer#setParent(WindowContainer)} was called.
366 * Supposed to be overridden and contain actions that should be executed after parent was set.
367 */
Riddle Hsu3a4bb612019-01-31 00:02:22 +0800368 @Override
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200369 void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
370 onParentChanged(newParent, oldParent, null);
Issei Suzuki25a9e2b2019-08-14 16:46:26 +0200371 }
372
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200373 void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent,
374 PreAssignChildLayersCallback callback) {
375 super.onParentChanged(newParent, oldParent);
Robert Carrb1579c82017-09-05 14:54:47 -0700376 if (mParent == null) {
377 return;
378 }
Jorim Jaggia5e10572017-11-15 14:36:26 +0100379
Robert Carrb1579c82017-09-05 14:54:47 -0700380 if (mSurfaceControl == null) {
381 // If we don't yet have a surface, but we now have a parent, we should
382 // build a surface.
wilsonshih07cb2722020-03-16 23:19:24 +0800383 createSurfaceControl(false /*force*/);
Robert Carrb1579c82017-09-05 14:54:47 -0700384 } else {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100385 // If we have a surface but a new parent, we just need to perform a reparent. Go through
386 // surface animator such that hierarchy is preserved when animating, i.e.
387 // mSurfaceControl stays attached to the leash and we just reparent the leash to the
388 // new parent.
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100389 reparentSurfaceControl(getPendingTransaction(), mParent.mSurfaceControl);
Robert Carrb1579c82017-09-05 14:54:47 -0700390 }
391
Issei Suzuki25a9e2b2019-08-14 16:46:26 +0200392 if (callback != null) {
393 callback.onPreAssignChildLayers();
394 }
395
Robert Carrb1579c82017-09-05 14:54:47 -0700396 // Either way we need to ask the parent to assign us a Z-order.
397 mParent.assignChildLayers();
398 scheduleAnimation();
Andrii Kulian441e4492016-09-29 15:25:00 -0700399 }
400
wilsonshih07cb2722020-03-16 23:19:24 +0800401 void createSurfaceControl(boolean force) {
402 setSurfaceControl(makeSurface().build());
403 getPendingTransaction().show(mSurfaceControl);
404 onSurfaceShown(getPendingTransaction());
405 updateSurfacePosition();
406 }
407
Vishnu Nairfd6fb672020-02-14 12:56:37 -0800408 /**
409 * Called when the surface is shown for the first time.
410 */
411 void onSurfaceShown(Transaction t) {
412 // do nothing
413 }
414
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700415 // Temp. holders for a chain of containers we are currently processing.
Jorim Jaggia5e10572017-11-15 14:36:26 +0100416 private final LinkedList<WindowContainer> mTmpChain1 = new LinkedList<>();
417 private final LinkedList<WindowContainer> mTmpChain2 = new LinkedList<>();
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700418
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700419 /**
420 * Adds the input window container has a child of this container in order based on the input
421 * comparator.
422 * @param child The window container to add as a child of this window container.
423 * @param comparator Comparator to use in determining the position the child should be added to.
424 * If null, the child will be added to the top.
425 */
426 @CallSuper
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700427 protected void addChild(E child, Comparator<E> comparator) {
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700428 if (!child.mReparenting && child.getParent() != null) {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700429 throw new IllegalArgumentException("addChild: container=" + child.getName()
Andrii Kulian441e4492016-09-29 15:25:00 -0700430 + " is already a child of container=" + child.getParent().getName()
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700431 + " can't add to container=" + getName());
Wale Ogunwalef6192862016-09-10 13:42:30 -0700432 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700433
Andrii Kulianb94292e2016-10-19 13:30:58 -0700434 int positionToAdd = -1;
435 if (comparator != null) {
436 final int count = mChildren.size();
437 for (int i = 0; i < count; i++) {
438 if (comparator.compare(child, mChildren.get(i)) < 0) {
439 positionToAdd = i;
440 break;
441 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700442 }
443 }
444
Andrii Kulianb94292e2016-10-19 13:30:58 -0700445 if (positionToAdd == -1) {
446 mChildren.add(child);
447 } else {
448 mChildren.add(positionToAdd, child);
449 }
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100450
Andrii Kulianb94292e2016-10-19 13:30:58 -0700451 // Set the parent after we've actually added a child in case a subclass depends on this.
452 child.setParent(this);
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700453 }
454
Wale Ogunwalef6192862016-09-10 13:42:30 -0700455 /** Adds the input window container has a child of this container at the input index. */
456 @CallSuper
Wale Ogunwale72919d22016-12-08 18:58:50 -0800457 void addChild(E child, int index) {
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700458 if (!child.mReparenting && child.getParent() != null) {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700459 throw new IllegalArgumentException("addChild: container=" + child.getName()
Andrii Kulian441e4492016-09-29 15:25:00 -0700460 + " is already a child of container=" + child.getParent().getName()
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800461 + " can't add to container=" + getName()
462 + "\n callers=" + Debug.getCallers(15, "\n"));
Wale Ogunwalef6192862016-09-10 13:42:30 -0700463 }
Kazuki Takisef85197b2018-06-18 18:18:36 +0900464
465 if ((index < 0 && index != POSITION_BOTTOM)
466 || (index > mChildren.size() && index != POSITION_TOP)) {
467 throw new IllegalArgumentException("addChild: invalid position=" + index
468 + ", children number=" + mChildren.size());
469 }
470
471 if (index == POSITION_TOP) {
472 index = mChildren.size();
473 } else if (index == POSITION_BOTTOM) {
474 index = 0;
475 }
476
Wale Ogunwalef6192862016-09-10 13:42:30 -0700477 mChildren.add(index, child);
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100478
Andrii Kulianb94292e2016-10-19 13:30:58 -0700479 // Set the parent after we've actually added a child in case a subclass depends on this.
480 child.setParent(this);
Wale Ogunwalef6192862016-09-10 13:42:30 -0700481 }
482
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100483 private void onChildAdded(WindowContainer child) {
484 mTreeWeight += child.mTreeWeight;
485 WindowContainer parent = getParent();
486 while (parent != null) {
487 parent.mTreeWeight += child.mTreeWeight;
488 parent = parent.getParent();
489 }
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200490 onChildPositionChanged(child);
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100491 }
492
Wale Ogunwalef6192862016-09-10 13:42:30 -0700493 /**
494 * Removes the input child container from this container which is its parent.
495 *
496 * @return True if the container did contain the input child and it was detached.
497 */
498 @CallSuper
499 void removeChild(E child) {
500 if (mChildren.remove(child)) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100501 onChildRemoved(child);
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700502 if (!child.mReparenting) {
503 child.setParent(null);
504 }
Wale Ogunwalef6192862016-09-10 13:42:30 -0700505 } else {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700506 throw new IllegalArgumentException("removeChild: container=" + child.getName()
507 + " is not a child of container=" + getName());
Wale Ogunwalef6192862016-09-10 13:42:30 -0700508 }
509 }
510
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100511 private void onChildRemoved(WindowContainer child) {
512 mTreeWeight -= child.mTreeWeight;
513 WindowContainer parent = getParent();
514 while (parent != null) {
515 parent.mTreeWeight -= child.mTreeWeight;
516 parent = parent.getParent();
517 }
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200518 onChildPositionChanged(child);
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100519 }
520
Wale Ogunwale571771c2016-08-26 13:18:50 -0700521 /**
522 * Removes this window container and its children with no regard for what else might be going on
523 * in the system. For example, the container will be removed during animation if this method is
524 * called which isn't desirable. For most cases you want to call {@link #removeIfPossible()}
525 * which allows the system to defer removal until a suitable time.
526 */
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700527 @CallSuper
Wale Ogunwale571771c2016-08-26 13:18:50 -0700528 void removeImmediately() {
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700529 while (!mChildren.isEmpty()) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100530 final E child = mChildren.peekLast();
Wale Ogunwale571771c2016-08-26 13:18:50 -0700531 child.removeImmediately();
532 // Need to do this after calling remove on the child because the child might try to
533 // remove/detach itself from its parent which will cause an exception if we remove
534 // it before calling remove on the child.
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100535 if (mChildren.remove(child)) {
536 onChildRemoved(child);
537 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700538 }
539
Robert Carrb1579c82017-09-05 14:54:47 -0700540 if (mSurfaceControl != null) {
Tiger Huanged6794e2019-05-07 20:07:59 +0800541 getPendingTransaction().remove(mSurfaceControl);
Robert Carr8a2f9132019-11-11 15:03:15 -0800542 setSurfaceControl(null);
Garfield Tan265ab91a2019-11-12 16:30:49 -0800543 mLastSurfacePosition.set(0, 0);
Chavi Weingartenb736e322018-02-23 00:27:54 +0000544 scheduleAnimation();
Robert Carrb1579c82017-09-05 14:54:47 -0700545 }
546
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700547 if (mParent != null) {
Wale Ogunwalef6192862016-09-10 13:42:30 -0700548 mParent.removeChild(this);
Wale Ogunwale571771c2016-08-26 13:18:50 -0700549 }
550 }
551
552 /**
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100553 * @return The index of this element in the hierarchy tree in prefix order.
554 */
555 int getPrefixOrderIndex() {
556 if (mParent == null) {
557 return 0;
558 }
559 return mParent.getPrefixOrderIndex(this);
560 }
561
562 private int getPrefixOrderIndex(WindowContainer child) {
563 int order = 0;
564 for (int i = 0; i < mChildren.size(); i++) {
565 final WindowContainer childI = mChildren.get(i);
566 if (child == childI) {
567 break;
568 }
569 order += childI.mTreeWeight;
570 }
571 if (mParent != null) {
572 order += mParent.getPrefixOrderIndex(this);
573 }
574
575 // We also need to count ourselves.
576 order++;
577 return order;
578 }
579
580 /**
Wale Ogunwale571771c2016-08-26 13:18:50 -0700581 * Removes this window container and its children taking care not to remove them during a
582 * critical stage in the system. For example, some containers will not be removed during
583 * animation if this method is called.
584 */
585 // TODO: figure-out implementation that works best for this.
586 // E.g. when do we remove from parent list? maybe not...
587 void removeIfPossible() {
588 for (int i = mChildren.size() - 1; i >= 0; --i) {
589 final WindowContainer wc = mChildren.get(i);
590 wc.removeIfPossible();
591 }
592 }
593
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700594 /** Returns true if this window container has the input child. */
Winson Chunge2d72172018-01-25 17:46:20 +0000595 boolean hasChild(E child) {
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700596 for (int i = mChildren.size() - 1; i >= 0; --i) {
Winson Chunge2d72172018-01-25 17:46:20 +0000597 final E current = mChildren.get(i);
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700598 if (current == child || current.hasChild(child)) {
599 return true;
600 }
601 }
602 return false;
603 }
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700604
Issei Suzuki2f541842020-01-09 20:18:29 +0100605 /** @return true if this window container is a descendant of the input container. */
606 boolean isDescendantOf(WindowContainer ancestor) {
607 final WindowContainer parent = getParent();
608 if (parent == ancestor) return true;
609 return (parent != null) && parent.isDescendantOf(ancestor);
610 }
611
Andrii Kulian441e4492016-09-29 15:25:00 -0700612 /**
Andrii Kuliand2765632016-12-12 22:26:34 -0800613 * Move a child from it's current place in siblings list to the specified position,
614 * with an option to move all its parents to top.
615 * @param position Target position to move the child to.
616 * @param child Child to move to selected position.
617 * @param includingParents Flag indicating whether we need to move the entire branch of the
618 * hierarchy when we're moving a child to {@link #POSITION_TOP} or
619 * {@link #POSITION_BOTTOM}. When moving to other intermediate positions
620 * this flag will do nothing.
621 */
622 @CallSuper
623 void positionChildAt(int position, E child, boolean includingParents) {
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800624
625 if (child.getParent() != this) {
Wale Ogunwale0d465192020-01-23 19:14:44 -0800626 throw new IllegalArgumentException("positionChildAt: container=" + child.getName()
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800627 + " is not a child of container=" + getName()
628 + " current parent=" + child.getParent());
629 }
630
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800631 if (position >= mChildren.size() - 1) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800632 position = POSITION_TOP;
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700633 } else if (position <= 0) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800634 position = POSITION_BOTTOM;
635 }
636
637 switch (position) {
638 case POSITION_TOP:
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800639 if (mChildren.peekLast() != child) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800640 mChildren.remove(child);
Jorim Jaggi612bb882017-05-16 17:11:18 +0200641 mChildren.add(child);
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200642 onChildPositionChanged(child);
Andrii Kuliand2765632016-12-12 22:26:34 -0800643 }
644 if (includingParents && getParent() != null) {
645 getParent().positionChildAt(POSITION_TOP, this /* child */,
646 true /* includingParents */);
647 }
648 break;
649 case POSITION_BOTTOM:
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800650 if (mChildren.peekFirst() != child) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800651 mChildren.remove(child);
652 mChildren.addFirst(child);
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200653 onChildPositionChanged(child);
Andrii Kuliand2765632016-12-12 22:26:34 -0800654 }
655 if (includingParents && getParent() != null) {
656 getParent().positionChildAt(POSITION_BOTTOM, this /* child */,
657 true /* includingParents */);
658 }
659 break;
660 default:
Winson Chung123e07a2018-02-27 11:47:16 -0800661 // TODO: Removing the child before reinserting requires the caller to provide a
662 // position that takes into account the removed child (if the index of the
663 // child < position, then the position should be adjusted). We should consider
664 // doing this adjustment here and remove any adjustments in the callers.
Andrii Kuliand2765632016-12-12 22:26:34 -0800665 mChildren.remove(child);
666 mChildren.add(position, child);
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200667 onChildPositionChanged(child);
Andrii Kuliand2765632016-12-12 22:26:34 -0800668 }
669 }
670
671 /**
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800672 * Notify that a child's position has changed. Possible changes are adding or removing a child.
673 */
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200674 void onChildPositionChanged(WindowContainer child) { }
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800675
676 /**
Andrii Kulian441e4492016-09-29 15:25:00 -0700677 * Update override configuration and recalculate full config.
Evan Roskydfe3da72018-10-26 17:21:06 -0700678 * @see #mRequestedOverrideConfiguration
Andrii Kulian441e4492016-09-29 15:25:00 -0700679 * @see #mFullConfiguration
680 */
Wale Ogunwale98d62312017-07-12 09:24:56 -0700681 @Override
Evan Roskydfe3da72018-10-26 17:21:06 -0700682 public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800683 // We must diff before the configuration is applied so that we can capture the change
684 // against the existing bounds.
Evan Roskydfe3da72018-10-26 17:21:06 -0700685 final int diff = diffRequestedOverrideBounds(
686 overrideConfiguration.windowConfiguration.getBounds());
687 super.onRequestedOverrideConfigurationChanged(overrideConfiguration);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700688 if (mParent != null) {
689 mParent.onDescendantOverrideConfigurationChanged();
690 }
Bryce Leef3c6a472017-11-14 14:53:06 -0800691
692 if (diff == BOUNDS_CHANGE_NONE) {
693 return;
694 }
695
696 if ((diff & BOUNDS_CHANGE_SIZE) == BOUNDS_CHANGE_SIZE) {
697 onResize();
698 } else {
699 onMovedByResize();
700 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700701 }
702
703 /**
704 * Notify that a descendant's overrideConfiguration has changed.
705 */
706 void onDescendantOverrideConfigurationChanged() {
707 if (mParent != null) {
708 mParent.onDescendantOverrideConfigurationChanged();
709 }
Andrii Kulian441e4492016-09-29 15:25:00 -0700710 }
711
712 /**
Garfield Tan2f145f22018-11-01 15:27:03 -0700713 * Notify that the display this container is on has changed. This could be either this container
714 * is moved to a new display, or some configurations on the display it is on changes.
715 *
716 * @param dc The display this container is on after changes.
Wale Ogunwale02319a62016-09-26 15:21:22 -0700717 */
718 void onDisplayChanged(DisplayContent dc) {
Tiger Huanged6794e2019-05-07 20:07:59 +0800719 mDisplayContent = dc;
720 if (dc != null && dc != this) {
721 dc.getPendingTransaction().merge(mPendingTransaction);
722 }
Wale Ogunwale02319a62016-09-26 15:21:22 -0700723 for (int i = mChildren.size() - 1; i >= 0; --i) {
724 final WindowContainer child = mChildren.get(i);
725 child.onDisplayChanged(dc);
726 }
727 }
728
Tiger Huanged6794e2019-05-07 20:07:59 +0800729 DisplayContent getDisplayContent() {
730 return mDisplayContent;
731 }
732
Andrii Kulian86d676c2020-03-27 19:34:54 -0700733 /** Get the first node of type {@link DisplayArea} above or at this node. */
734 @Nullable
735 DisplayArea getDisplayArea() {
736 WindowContainer parent = getParent();
737 return parent != null ? parent.getDisplayArea() : null;
738 }
739
Evan Rosky688c8382020-04-03 17:27:08 -0700740 boolean isAttached() {
741 return getDisplayArea() != null;
742 }
743
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700744 void setWaitingForDrawnIfResizingChanged() {
745 for (int i = mChildren.size() - 1; i >= 0; --i) {
746 final WindowContainer wc = mChildren.get(i);
747 wc.setWaitingForDrawnIfResizingChanged();
748 }
749 }
750
751 void onResize() {
752 for (int i = mChildren.size() - 1; i >= 0; --i) {
753 final WindowContainer wc = mChildren.get(i);
Bryce Leed92ae482018-01-22 13:56:23 -0800754 wc.onParentResize();
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700755 }
756 }
757
Bryce Leed92ae482018-01-22 13:56:23 -0800758 void onParentResize() {
759 // In the case this container has specified its own bounds, a parent resize will not
760 // affect its bounds. Any relevant changes will be propagated through changes to the
761 // Configuration override.
762 if (hasOverrideBounds()) {
763 return;
764 }
765
766 // Default implementation is to treat as resize on self.
767 onResize();
768 }
769
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700770 void onMovedByResize() {
771 for (int i = mChildren.size() - 1; i >= 0; --i) {
772 final WindowContainer wc = mChildren.get(i);
773 wc.onMovedByResize();
774 }
775 }
776
777 void resetDragResizingChangeReported() {
778 for (int i = mChildren.size() - 1; i >= 0; --i) {
779 final WindowContainer wc = mChildren.get(i);
780 wc.resetDragResizingChangeReported();
781 }
782 }
783
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700784 void forceWindowsScaleableInTransaction(boolean force) {
785 for (int i = mChildren.size() - 1; i >= 0; --i) {
786 final WindowContainer wc = mChildren.get(i);
787 wc.forceWindowsScaleableInTransaction(force);
788 }
789 }
790
Jorim Jaggia5e10572017-11-15 14:36:26 +0100791 /**
lumark9bca6b42019-10-17 18:35:22 +0800792 * @return {@code true} when this container or its related containers are running an
793 * animation, {@code false} otherwise.
794 *
795 * By default this predicate only checks if this container itself is actually running an
796 * animation, but you can extend the check target over its relatives, or relax the condition
797 * so that this can return {@code true} if an animation starts soon by giving a combination
chaviw9177c772020-03-24 11:35:22 -0700798 * of {@link AnimationFlags}.
lumark9bca6b42019-10-17 18:35:22 +0800799 *
800 * Note that you can give a combination of bitmask flags to specify targets and condition for
801 * checking animating status.
802 * e.g. {@code isAnimating(TRANSITION | PARENT)} returns {@code true} if either this
803 * container itself or one of its parents is running an animation or waiting for an app
804 * transition.
805 *
806 * Note that TRANSITION propagates to parents and children as well.
807 *
chaviw9177c772020-03-24 11:35:22 -0700808 * @param flags The combination of bitmask flags to specify targets and condition for
809 * checking animating status.
810 * @param typesToCheck The combination of bitmask {@link AnimationType} to compare when
811 * determining if animating.
812 *
813 * @see AnimationFlags#TRANSITION
814 * @see AnimationFlags#PARENTS
815 * @see AnimationFlags#CHILDREN
Jorim Jaggia5e10572017-11-15 14:36:26 +0100816 */
chaviw9177c772020-03-24 11:35:22 -0700817 boolean isAnimating(int flags, int typesToCheck) {
818 int animationType = mSurfaceAnimator.getAnimationType();
819 if (mSurfaceAnimator.isAnimating() && (animationType & typesToCheck) > 0) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100820 return true;
821 }
lumark9bca6b42019-10-17 18:35:22 +0800822 if ((flags & TRANSITION) != 0 && isWaitingForTransitionStart()) {
823 return true;
824 }
825 if ((flags & PARENTS) != 0) {
826 final WindowContainer parent = getParent();
chaviw9177c772020-03-24 11:35:22 -0700827 if (parent != null && parent.isAnimating(flags & ~CHILDREN, typesToCheck)) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700828 return true;
829 }
830 }
lumark9bca6b42019-10-17 18:35:22 +0800831 if ((flags & CHILDREN) != 0) {
832 for (int i = 0; i < mChildren.size(); ++i) {
833 final WindowContainer wc = mChildren.get(i);
chaviw9177c772020-03-24 11:35:22 -0700834 if (wc.isAnimating(flags & ~PARENTS, typesToCheck)) {
lumark9bca6b42019-10-17 18:35:22 +0800835 return true;
836 }
837 }
838 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700839 return false;
840 }
841
Jorim Jaggia5e10572017-11-15 14:36:26 +0100842 /**
chaviw9177c772020-03-24 11:35:22 -0700843 * Similar to {@link #isAnimating(int, int)} except provide a bitmask of
844 * {@link AnimationType} to exclude, rather than include
845 * @param flags The combination of bitmask flags to specify targets and condition for
846 * checking animating status.
847 * @param typesToExclude The combination of bitmask {@link AnimationType} to exclude when
848 * checking if animating.
849 */
850 boolean isAnimatingExcluding(int flags, int typesToExclude) {
851 return isAnimating(flags, ANIMATION_TYPE_ALL & ~typesToExclude);
852 }
853
854 /**
855 * @see #isAnimating(int, int)
856 * TODO (b/152333373): Migrate calls to use isAnimating with specified animation type
857 */
858 boolean isAnimating(int flags) {
859 return isAnimating(flags, ANIMATION_TYPE_ALL);
860 }
861
862 /**
lumark9bca6b42019-10-17 18:35:22 +0800863 * @return {@code true} when the container is waiting the app transition start, {@code false}
864 * otherwise.
Jorim Jaggia5e10572017-11-15 14:36:26 +0100865 */
lumark9bca6b42019-10-17 18:35:22 +0800866 boolean isWaitingForTransitionStart() {
lumark52d5f422020-01-06 16:17:55 +0800867 return false;
Jorim Jaggia5e10572017-11-15 14:36:26 +0100868 }
869
870 /**
lumark9bca6b42019-10-17 18:35:22 +0800871 * @return {@code true} if in this subtree of the hierarchy we have an
Wale Ogunwaledfbeed72019-11-20 08:57:39 -0800872 * {@code ActivityRecord#isAnimating(TRANSITION)}, {@code false} otherwise.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200873 */
lumark9bca6b42019-10-17 18:35:22 +0800874 boolean isAppTransitioning() {
lumark5341d1c2019-12-14 01:54:02 +0800875 return getActivity(app -> app.isAnimating(PARENTS | TRANSITION)) != null;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200876 }
877
878 /**
Jorim Jaggia5e10572017-11-15 14:36:26 +0100879 * @return Whether our own container running an animation at the moment.
880 */
lumark9bca6b42019-10-17 18:35:22 +0800881 final boolean isAnimating() {
882 return isAnimating(0 /* self only */);
Jorim Jaggia5e10572017-11-15 14:36:26 +0100883 }
884
lumark19a5d2e2019-10-11 16:19:30 +0800885 /**
886 * @return {@code true} if the container is in changing app transition.
887 */
888 boolean isChangingAppTransition() {
Evan Rosky55bddd82020-01-29 13:07:18 -0800889 return mDisplayContent != null && mDisplayContent.mChangingContainers.contains(this);
lumark19a5d2e2019-10-11 16:19:30 +0800890 }
891
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700892 void sendAppVisibilityToClients() {
893 for (int i = mChildren.size() - 1; i >= 0; --i) {
894 final WindowContainer wc = mChildren.get(i);
895 wc.sendAppVisibilityToClients();
896 }
897 }
898
Wale Ogunwale44f21802016-09-02 12:49:48 -0700899 /**
900 * Returns true if the container or one of its children as some content it can display or wants
901 * to display (e.g. app views or saved surface).
902 *
903 * NOTE: While this method will return true if the there is some content to display, it doesn't
904 * mean the container is visible. Use {@link #isVisible()} to determine if the container is
905 * visible.
906 */
907 boolean hasContentToDisplay() {
908 for (int i = mChildren.size() - 1; i >= 0; --i) {
909 final WindowContainer wc = mChildren.get(i);
910 if (wc.hasContentToDisplay()) {
911 return true;
912 }
913 }
914 return false;
915 }
916
917 /**
918 * Returns true if the container or one of its children is considered visible from the
919 * WindowManager perspective which usually means valid surface and some other internal state
920 * are true.
921 *
922 * NOTE: While this method will return true if the surface is visible, it doesn't mean the
923 * client has actually displayed any content. Use {@link #hasContentToDisplay()} to determine if
924 * the container has any content to display.
925 */
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700926 boolean isVisible() {
Wale Ogunwalef6192862016-09-10 13:42:30 -0700927 // TODO: Will this be more correct if it checks the visibility of its parents?
928 // It depends...For example, Tasks and Stacks are only visible if there children are visible
929 // but, WindowState are not visible if there parent are not visible. Maybe have the
Andrii Kuliancd5dcb8b2017-01-03 17:09:45 -0800930 // container specify which direction to traverse for visibility?
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700931 for (int i = mChildren.size() - 1; i >= 0; --i) {
932 final WindowContainer wc = mChildren.get(i);
933 if (wc.isVisible()) {
934 return true;
935 }
936 }
937 return false;
938 }
939
Evan Roskya80f11c2020-01-23 19:17:10 -0800940 /**
Evan Rosky55bddd82020-01-29 13:07:18 -0800941 * Called when the visibility of a child is asked to change. This is before visibility actually
942 * changes (eg. a transition animation might play out first).
943 */
944 void onChildVisibilityRequested(boolean visible) {
945 // If we are changing visibility, then a snapshot isn't necessary and we are no-longer
946 // part of a change transition.
947 mSurfaceFreezer.unfreeze(getPendingTransaction());
948 if (mDisplayContent != null) {
949 mDisplayContent.mChangingContainers.remove(this);
950 }
951 WindowContainer parent = getParent();
952 if (parent != null) {
953 parent.onChildVisibilityRequested(visible);
954 }
955 }
956
957 void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) {
958 final long token = proto.start(fieldId);
959 proto.write(HASH_CODE, System.identityHashCode(this));
960 proto.write(USER_ID, USER_NULL);
961 proto.write(TITLE, "WindowContainer");
962 proto.end(token);
963 }
964
965 /**
Evan Roskya80f11c2020-01-23 19:17:10 -0800966 * Returns {@code true} if this container is focusable. Generally, if a parent is not focusable,
967 * this will not be focusable either.
968 */
Evan Rosky226de132020-01-03 18:00:29 -0800969 boolean isFocusable() {
Evan Roskya80f11c2020-01-23 19:17:10 -0800970 final WindowContainer parent = getParent();
971 return (parent == null || parent.isFocusable()) && mIsFocusable;
Evan Rosky226de132020-01-03 18:00:29 -0800972 }
973
974 /** Set whether this container or its children can be focusable */
Evan Rosky226de132020-01-03 18:00:29 -0800975 boolean setFocusable(boolean focusable) {
976 if (mIsFocusable == focusable) {
977 return false;
978 }
979 mIsFocusable = focusable;
980 return true;
981 }
982
Bryce Lee00d586d2017-07-28 20:48:43 -0700983 /**
Robert Carrb1579c82017-09-05 14:54:47 -0700984 * @return Whether this child is on top of the window hierarchy.
Bryce Lee00d586d2017-07-28 20:48:43 -0700985 */
986 boolean isOnTop() {
987 return getParent().getTopChild() == this && getParent().isOnTop();
988 }
989
Jorim Jaggi10abe2f2017-01-03 16:44:46 +0100990 /** Returns the top child container. */
991 E getTopChild() {
992 return mChildren.peekLast();
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700993 }
Wale Ogunwale51362492016-09-08 17:49:17 -0700994
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700995 /** Returns true if there is still a removal being deferred */
996 boolean checkCompleteDeferredRemoval() {
997 boolean stillDeferringRemoval = false;
998
999 for (int i = mChildren.size() - 1; i >= 0; --i) {
1000 final WindowContainer wc = mChildren.get(i);
1001 stillDeferringRemoval |= wc.checkCompleteDeferredRemoval();
1002 }
1003
1004 return stillDeferringRemoval;
1005 }
1006
1007 /** Checks if all windows in an app are all drawn and shows them if needed. */
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001008 void checkAppWindowsReadyToShow() {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001009 for (int i = mChildren.size() - 1; i >= 0; --i) {
1010 final WindowContainer wc = mChildren.get(i);
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001011 wc.checkAppWindowsReadyToShow();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001012 }
1013 }
1014
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001015 void onAppTransitionDone() {
1016 for (int i = mChildren.size() - 1; i >= 0; --i) {
1017 final WindowContainer wc = mChildren.get(i);
1018 wc.onAppTransitionDone();
1019 }
1020 }
1021
Garfield Tan90b04282018-12-11 14:04:42 -08001022 /**
1023 * Called when this container or one of its descendants changed its requested orientation, and
1024 * wants this container to handle it or pass it to its parent.
1025 *
1026 * @param freezeDisplayToken freeze this app window token if display needs to freeze
1027 * @param requestingContainer the container which orientation request has changed
1028 * @return {@code true} if handled; {@code false} otherwise.
1029 */
1030 boolean onDescendantOrientationChanged(@Nullable IBinder freezeDisplayToken,
1031 @Nullable ConfigurationContainer requestingContainer) {
1032 final WindowContainer parent = getParent();
1033 if (parent == null) {
1034 return false;
1035 }
1036 return parent.onDescendantOrientationChanged(freezeDisplayToken,
1037 requestingContainer);
1038 }
1039
1040 /**
Garfield Tan49dae102019-02-04 09:51:59 -08001041 * Check if this container or its parent will handle orientation changes from descendants. It's
1042 * different from the return value of {@link #onDescendantOrientationChanged(IBinder,
1043 * ConfigurationContainer)} in the sense that the return value of this method tells if this
1044 * container or its parent will handle the request eventually, while the return value of the
1045 * other method is if it handled the request synchronously.
1046 *
1047 * @return {@code true} if it handles or will handle orientation change in the future; {@code
1048 * false} if it won't handle the change at anytime.
1049 */
1050 boolean handlesOrientationChangeFromDescendant() {
1051 final WindowContainer parent = getParent();
1052 return parent != null && parent.handlesOrientationChangeFromDescendant();
1053 }
1054
1055 /**
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001056 * Get the configuration orientation by the requested screen orientation
1057 * ({@link ActivityInfo.ScreenOrientation}) of this activity.
1058 *
1059 * @return orientation in ({@link Configuration#ORIENTATION_LANDSCAPE},
1060 * {@link Configuration#ORIENTATION_PORTRAIT},
1061 * {@link Configuration#ORIENTATION_UNDEFINED}).
1062 */
1063 int getRequestedConfigurationOrientation() {
1064 if (mOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
1065 // NOSENSOR means the display's "natural" orientation, so return that.
1066 if (mDisplayContent != null) {
1067 return mDisplayContent.getNaturalOrientation();
1068 }
1069 } else if (mOrientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
1070 // LOCKED means the activity's orientation remains unchanged, so return existing value.
1071 return getConfiguration().orientation;
1072 } else if (isFixedOrientationLandscape(mOrientation)) {
1073 return ORIENTATION_LANDSCAPE;
1074 } else if (isFixedOrientationPortrait(mOrientation)) {
1075 return ORIENTATION_PORTRAIT;
1076 }
1077 return ORIENTATION_UNDEFINED;
1078 }
1079
1080 /**
Garfield Tan90b04282018-12-11 14:04:42 -08001081 * Calls {@link #setOrientation(int, IBinder, ActivityRecord)} with {@code null} to the last 2
1082 * parameters.
1083 *
1084 * @param orientation the specified orientation.
1085 */
Wale Ogunwale51362492016-09-08 17:49:17 -07001086 void setOrientation(int orientation) {
Garfield Tan90b04282018-12-11 14:04:42 -08001087 setOrientation(orientation, null /* freezeDisplayToken */,
1088 null /* ActivityRecord */);
1089 }
1090
1091 /**
1092 * Sets the specified orientation of this container. It percolates this change upward along the
1093 * hierarchy to let each level of the hierarchy a chance to respond to it.
1094 *
1095 * @param orientation the specified orientation. Needs to be one of {@link
1096 * android.content.pm.ActivityInfo.ScreenOrientation}.
1097 * @param freezeDisplayToken uses this token to freeze display if orientation change is not
1098 * done. Display will not be frozen if this is {@code null}, which
1099 * should only happen in tests.
1100 * @param requestingContainer the container which orientation request has changed. Mostly used
1101 * to ensure it gets correct configuration.
1102 */
1103 void setOrientation(int orientation, @Nullable IBinder freezeDisplayToken,
1104 @Nullable ConfigurationContainer requestingContainer) {
Wale Ogunwale8a1860a2019-06-05 08:57:19 -07001105 if (mOrientation == orientation) {
Garfield Tan90b04282018-12-11 14:04:42 -08001106 return;
1107 }
Wale Ogunwale8a1860a2019-06-05 08:57:19 -07001108
1109 mOrientation = orientation;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001110 final int configOrientation = getRequestedConfigurationOrientation();
1111 if (getRequestedOverrideConfiguration().orientation != configOrientation) {
1112 mTmpConfig.setTo(getRequestedOverrideConfiguration());
1113 mTmpConfig.orientation = configOrientation;
1114 onRequestedOverrideConfigurationChanged(mTmpConfig);
1115 }
1116
Garfield Tan90b04282018-12-11 14:04:42 -08001117 final WindowContainer parent = getParent();
1118 if (parent != null) {
1119 onDescendantOrientationChanged(freezeDisplayToken, requestingContainer);
1120 }
Wale Ogunwale51362492016-09-08 17:49:17 -07001121 }
1122
Vadim Caen1096f112019-12-18 11:44:26 +01001123 @ActivityInfo.ScreenOrientation
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001124 int getOrientation() {
1125 return getOrientation(mOrientation);
1126 }
1127
Wale Ogunwale51362492016-09-08 17:49:17 -07001128 /**
1129 * Returns the specified orientation for this window container or one of its children is there
1130 * is one set, or {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSET} if no
1131 * specification is set.
1132 * NOTE: {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED} is a
1133 * specification...
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001134 *
1135 * @param candidate The current orientation candidate that will be returned if we don't find a
1136 * better match.
1137 * @return The orientation as specified by this branch or the window hierarchy.
Wale Ogunwale51362492016-09-08 17:49:17 -07001138 */
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001139 int getOrientation(int candidate) {
Riddle Hsu6f548e92020-01-13 13:34:09 +08001140 mLastOrientationSource = null;
Bryce Leea163b762017-01-24 11:05:01 -08001141 if (!fillsParent()) {
1142 // Ignore containers that don't completely fill their parents.
Wale Ogunwale51362492016-09-08 17:49:17 -07001143 return SCREEN_ORIENTATION_UNSET;
1144 }
1145
Bryce Leea163b762017-01-24 11:05:01 -08001146 // The container fills its parent so we can use it orientation if it has one
1147 // specified; otherwise we prefer to use the orientation of its topmost child that has one
Wale Ogunwale51362492016-09-08 17:49:17 -07001148 // specified and fall back on this container's unset or unspecified value as a candidate
1149 // if none of the children have a better candidate for the orientation.
1150 if (mOrientation != SCREEN_ORIENTATION_UNSET
1151 && mOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
Riddle Hsu6f548e92020-01-13 13:34:09 +08001152 mLastOrientationSource = this;
Wale Ogunwale51362492016-09-08 17:49:17 -07001153 return mOrientation;
1154 }
Wale Ogunwale51362492016-09-08 17:49:17 -07001155
1156 for (int i = mChildren.size() - 1; i >= 0; --i) {
1157 final WindowContainer wc = mChildren.get(i);
1158
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001159 // TODO: Maybe mOrientation should default to SCREEN_ORIENTATION_UNSET vs.
1160 // SCREEN_ORIENTATION_UNSPECIFIED?
1161 final int orientation = wc.getOrientation(candidate == SCREEN_ORIENTATION_BEHIND
1162 ? SCREEN_ORIENTATION_BEHIND : SCREEN_ORIENTATION_UNSET);
Wale Ogunwale51362492016-09-08 17:49:17 -07001163 if (orientation == SCREEN_ORIENTATION_BEHIND) {
1164 // container wants us to use the orientation of the container behind it. See if we
1165 // can find one. Else return SCREEN_ORIENTATION_BEHIND so the caller can choose to
1166 // look behind this container.
1167 candidate = orientation;
Riddle Hsu6f548e92020-01-13 13:34:09 +08001168 mLastOrientationSource = wc;
Wale Ogunwale51362492016-09-08 17:49:17 -07001169 continue;
1170 }
1171
1172 if (orientation == SCREEN_ORIENTATION_UNSET) {
1173 continue;
1174 }
1175
1176 if (wc.fillsParent() || orientation != SCREEN_ORIENTATION_UNSPECIFIED) {
1177 // Use the orientation if the container fills its parent or requested an explicit
1178 // orientation that isn't SCREEN_ORIENTATION_UNSPECIFIED.
Vadim Caenfc14c662020-01-20 16:00:31 +01001179 ProtoLog.v(WM_DEBUG_ORIENTATION, "%s is requesting orientation %d (%s)",
1180 wc.toString(), orientation,
1181 ActivityInfo.screenOrientationToString(orientation));
Riddle Hsu6f548e92020-01-13 13:34:09 +08001182 mLastOrientationSource = wc;
Wale Ogunwale51362492016-09-08 17:49:17 -07001183 return orientation;
1184 }
1185 }
1186
1187 return candidate;
1188 }
1189
1190 /**
Riddle Hsu6f548e92020-01-13 13:34:09 +08001191 * @return The deepest source which decides the orientation of this window container since the
1192 * last time {@link #getOrientation(int) was called.
1193 */
1194 @Nullable
1195 WindowContainer getLastOrientationSource() {
1196 final WindowContainer source = mLastOrientationSource;
1197 if (source != null && source != this) {
1198 final WindowContainer nextSource = source.getLastOrientationSource();
1199 if (nextSource != null) {
1200 return nextSource;
1201 }
1202 }
1203 return source;
1204 }
1205
1206 /**
Wale Ogunwale51362492016-09-08 17:49:17 -07001207 * Returns true if this container is opaque and fills all the space made available by its parent
1208 * container.
1209 *
1210 * NOTE: It is possible for this container to occupy more space than the parent has (or less),
1211 * this is just a signal from the client to window manager stating its intent, but not what it
1212 * actually does.
1213 */
1214 boolean fillsParent() {
1215 return false;
1216 }
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001217
Wale Ogunwale6213caa2016-12-02 16:47:15 +00001218 // TODO: Users would have their own window containers under the display container?
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -07001219 void switchUser(int userId) {
Wale Ogunwale6213caa2016-12-02 16:47:15 +00001220 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -07001221 mChildren.get(i).switchUser(userId);
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001222 }
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001223 }
1224
Wale Ogunwale9bb1a1e2019-12-30 11:29:52 -08001225 boolean showToCurrentUser() {
1226 return true;
1227 }
1228
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001229 /**
1230 * For all windows at or below this container call the callback.
1231 * @param callback Calls the {@link ToBooleanFunction#apply} method for each window found and
1232 * stops the search if {@link ToBooleanFunction#apply} returns true.
1233 * @param traverseTopToBottom If true traverses the hierarchy from top-to-bottom in terms of
1234 * z-order, else from bottom-to-top.
1235 * @return True if the search ended before we reached the end of the hierarchy due to
Wale Ogunwale1e129a42016-11-21 13:03:47 -08001236 * {@link ToBooleanFunction#apply} returning true.
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001237 */
1238 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001239 if (traverseTopToBottom) {
1240 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001241 if (mChildren.get(i).forAllWindows(callback, traverseTopToBottom)) {
1242 return true;
1243 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001244 }
1245 } else {
1246 final int count = mChildren.size();
1247 for (int i = 0; i < count; i++) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001248 if (mChildren.get(i).forAllWindows(callback, traverseTopToBottom)) {
1249 return true;
1250 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001251 }
1252 }
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001253 return false;
1254 }
1255
1256 void forAllWindows(Consumer<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleee41d4a2016-11-21 08:41:10 -08001257 ForAllWindowsConsumerWrapper wrapper = obtainConsumerWrapper(callback);
1258 forAllWindows(wrapper, traverseTopToBottom);
1259 wrapper.release();
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001260 }
1261
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001262 boolean forAllActivities(Function<ActivityRecord, Boolean> callback) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001263 return forAllActivities(callback, true /*traverseTopToBottom*/);
1264 }
1265
1266 boolean forAllActivities(
1267 Function<ActivityRecord, Boolean> callback, boolean traverseTopToBottom) {
1268 if (traverseTopToBottom) {
1269 for (int i = mChildren.size() - 1; i >= 0; --i) {
1270 if (mChildren.get(i).forAllActivities(callback, traverseTopToBottom)) return true;
1271 }
1272 } else {
1273 final int count = mChildren.size();
1274 for (int i = 0; i < count; i++) {
1275 if (mChildren.get(i).forAllActivities(callback, traverseTopToBottom)) return true;
lumark9bca6b42019-10-17 18:35:22 +08001276 }
lumark588a3e82018-07-20 18:53:54 +08001277 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001278
lumark9bca6b42019-10-17 18:35:22 +08001279 return false;
lumark588a3e82018-07-20 18:53:54 +08001280 }
1281
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001282 void forAllActivities(Consumer<ActivityRecord> callback) {
1283 forAllActivities(callback, true /*traverseTopToBottom*/);
1284 }
1285
1286 void forAllActivities(Consumer<ActivityRecord> callback, boolean traverseTopToBottom) {
1287 if (traverseTopToBottom) {
1288 for (int i = mChildren.size() - 1; i >= 0; --i) {
1289 mChildren.get(i).forAllActivities(callback, traverseTopToBottom);
1290 }
1291 } else {
1292 final int count = mChildren.size();
1293 for (int i = 0; i < count; i++) {
1294 mChildren.get(i).forAllActivities(callback, traverseTopToBottom);
1295 }
1296 }
1297 }
1298
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001299 /**
1300 * Process all activities in this branch of the tree.
1301 *
1302 * @param callback Called for each activity found.
1303 * @param boundary We don't return activities via {@param callback} until we get to this node in
1304 * the tree.
1305 * @param includeBoundary If the boundary from be processed to return activities.
1306 * @param traverseTopToBottom direction to traverse the tree.
1307 * @return {@code true} if we ended the search before reaching the end of the tree.
1308 */
1309 final boolean forAllActivities(Function<ActivityRecord, Boolean> callback,
1310 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom) {
1311 return forAllActivities(
1312 callback, boundary, includeBoundary, traverseTopToBottom, new boolean[1]);
1313 }
1314
1315 private boolean forAllActivities(Function<ActivityRecord, Boolean> callback,
1316 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1317 boolean[] boundaryFound) {
1318 if (traverseTopToBottom) {
1319 for (int i = mChildren.size() - 1; i >= 0; --i) {
1320 if (processForAllActivitiesWithBoundary(callback, boundary, includeBoundary,
1321 traverseTopToBottom, boundaryFound, mChildren.get(i))) {
1322 return true;
1323 }
1324 }
1325 } else {
1326 final int count = mChildren.size();
1327 for (int i = 0; i < count; i++) {
1328 if (processForAllActivitiesWithBoundary(callback, boundary, includeBoundary,
1329 traverseTopToBottom, boundaryFound, mChildren.get(i))) {
1330 return true;
1331 }
1332 }
1333 }
1334
1335 return false;
1336 }
1337
1338 private boolean processForAllActivitiesWithBoundary(Function<ActivityRecord, Boolean> callback,
1339 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1340 boolean[] boundaryFound, WindowContainer wc) {
1341 if (wc == boundary) {
1342 boundaryFound[0] = true;
1343 if (!includeBoundary) return false;
1344 }
1345
1346 if (boundaryFound[0]) {
1347 return wc.forAllActivities(callback, traverseTopToBottom);
1348 }
1349
1350 return wc.forAllActivities(
1351 callback, boundary, includeBoundary, traverseTopToBottom, boundaryFound);
1352 }
1353
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001354 /** @return {@code true} if this node or any of its children contains an activity. */
1355 boolean hasActivity() {
1356 for (int i = mChildren.size() - 1; i >= 0; --i) {
1357 if (mChildren.get(i).hasActivity()) {
1358 return true;
1359 }
1360 }
1361 return false;
1362 }
1363
1364 ActivityRecord getActivity(Predicate<ActivityRecord> callback) {
1365 return getActivity(callback, true /*traverseTopToBottom*/);
1366 }
1367
1368 ActivityRecord getActivity(Predicate<ActivityRecord> callback, boolean traverseTopToBottom) {
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001369 return getActivity(callback, traverseTopToBottom, null /*boundary*/);
1370 }
1371
1372 ActivityRecord getActivity(Predicate<ActivityRecord> callback, boolean traverseTopToBottom,
1373 WindowContainer boundary) {
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001374 if (traverseTopToBottom) {
1375 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001376 final WindowContainer wc = mChildren.get(i);
1377 if (wc == boundary) return null;
1378
1379 final ActivityRecord r = wc.getActivity(callback, traverseTopToBottom, boundary);
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001380 if (r != null) {
1381 return r;
1382 }
1383 }
1384 } else {
1385 final int count = mChildren.size();
1386 for (int i = 0; i < count; i++) {
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001387 final WindowContainer wc = mChildren.get(i);
1388 if (wc == boundary) return null;
1389
1390 final ActivityRecord r = wc.getActivity(callback, traverseTopToBottom, boundary);
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001391 if (r != null) {
1392 return r;
1393 }
1394 }
1395 }
1396
1397 return null;
1398 }
1399
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001400 /**
1401 * Gets an activity in a branch of the tree.
1402 *
1403 * @param callback called to test if this is the activity that should be returned.
1404 * @param boundary We don't return activities via {@param callback} until we get to this node in
1405 * the tree.
1406 * @param includeBoundary If the boundary from be processed to return activities.
1407 * @param traverseTopToBottom direction to traverse the tree.
1408 * @return The activity if found or null.
1409 */
1410 final ActivityRecord getActivity(Predicate<ActivityRecord> callback,
1411 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom) {
1412 return getActivity(
1413 callback, boundary, includeBoundary, traverseTopToBottom, new boolean[1]);
1414 }
1415
1416 private ActivityRecord getActivity(Predicate<ActivityRecord> callback,
1417 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1418 boolean[] boundaryFound) {
1419 if (traverseTopToBottom) {
1420 for (int i = mChildren.size() - 1; i >= 0; --i) {
1421 final ActivityRecord r = processGetActivityWithBoundary(callback, boundary,
1422 includeBoundary, traverseTopToBottom, boundaryFound, mChildren.get(i));
1423 if (r != null) {
1424 return r;
1425 }
1426 }
1427 } else {
1428 final int count = mChildren.size();
1429 for (int i = 0; i < count; i++) {
1430 final ActivityRecord r = processGetActivityWithBoundary(callback, boundary,
1431 includeBoundary, traverseTopToBottom, boundaryFound, mChildren.get(i));
1432 if (r != null) {
1433 return r;
1434 }
1435 }
1436 }
1437
1438 return null;
1439 }
1440
1441 private ActivityRecord processGetActivityWithBoundary(Predicate<ActivityRecord> callback,
1442 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1443 boolean[] boundaryFound, WindowContainer wc) {
1444 if (wc == boundary || boundary == null) {
1445 boundaryFound[0] = true;
1446 if (!includeBoundary) return null;
1447 }
1448
1449 if (boundaryFound[0]) {
1450 return wc.getActivity(callback, traverseTopToBottom);
1451 }
1452
1453 return wc.getActivity(
1454 callback, boundary, includeBoundary, traverseTopToBottom, boundaryFound);
1455 }
1456
1457 ActivityRecord getActivityAbove(ActivityRecord r) {
1458 return getActivity((above) -> true, r,
1459 false /*includeBoundary*/, false /*traverseTopToBottom*/);
1460 }
1461
1462 ActivityRecord getActivityBelow(ActivityRecord r) {
1463 return getActivity((below) -> true, r,
1464 false /*includeBoundary*/, true /*traverseTopToBottom*/);
1465 }
1466
1467 ActivityRecord getBottomMostActivity() {
1468 return getActivity((r) -> true, false /*traverseTopToBottom*/);
1469 }
1470
1471 ActivityRecord getTopMostActivity() {
1472 return getActivity((r) -> true, true /*traverseTopToBottom*/);
1473 }
1474
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001475 ActivityRecord getTopActivity(boolean includeFinishing, boolean includeOverlays) {
1476 // Break down into 4 calls to avoid object creation due to capturing input params.
1477 if (includeFinishing) {
1478 if (includeOverlays) {
1479 return getActivity((r) -> true);
1480 }
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08001481 return getActivity((r) -> !r.isTaskOverlay());
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001482 } else if (includeOverlays) {
1483 return getActivity((r) -> !r.finishing);
1484 }
1485
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08001486 return getActivity((r) -> !r.finishing && !r.isTaskOverlay());
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001487 }
1488
Winson Chungd5852192019-09-06 17:20:28 -07001489 void forAllWallpaperWindows(Consumer<WallpaperWindowToken> callback) {
1490 for (int i = mChildren.size() - 1; i >= 0; --i) {
1491 mChildren.get(i).forAllWallpaperWindows(callback);
1492 }
1493 }
1494
Jorim Jaggi51304d72017-05-17 17:25:32 +02001495 /**
1496 * For all tasks at or below this container call the callback.
1497 *
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001498 * @param callback Calls the {@link ToBooleanFunction#apply} method for each task found and
1499 * stops the search if {@link ToBooleanFunction#apply} returns {@code true}.
1500 */
1501 boolean forAllTasks(Function<Task, Boolean> callback) {
1502 for (int i = mChildren.size() - 1; i >= 0; --i) {
1503 if (mChildren.get(i).forAllTasks(callback)) {
1504 return true;
1505 }
1506 }
1507 return false;
1508 }
1509
1510 /**
1511 * For all tasks at or below this container call the callback.
1512 *
Jorim Jaggi51304d72017-05-17 17:25:32 +02001513 * @param callback Callback to be called for every task.
1514 */
1515 void forAllTasks(Consumer<Task> callback) {
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001516 forAllTasks(callback, true /*traverseTopToBottom*/);
1517 }
1518
1519 void forAllTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
1520 final int count = mChildren.size();
1521 if (traverseTopToBottom) {
1522 for (int i = count - 1; i >= 0; --i) {
1523 mChildren.get(i).forAllTasks(callback, traverseTopToBottom);
1524 }
1525 } else {
1526 for (int i = 0; i < count; i++) {
1527 mChildren.get(i).forAllTasks(callback, traverseTopToBottom);
1528 }
Jorim Jaggi51304d72017-05-17 17:25:32 +02001529 }
1530 }
1531
Wale Ogunwale0d465192020-01-23 19:14:44 -08001532 void forAllLeafTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
Jeff Changdc9c1d42020-02-11 14:57:34 +08001533 final int count = mChildren.size();
1534 if (traverseTopToBottom) {
1535 for (int i = count - 1; i >= 0; --i) {
Wale Ogunwale0d465192020-01-23 19:14:44 -08001536 mChildren.get(i).forAllLeafTasks(callback, traverseTopToBottom);
Jeff Changdc9c1d42020-02-11 14:57:34 +08001537 }
1538 } else {
1539 for (int i = 0; i < count; i++) {
Wale Ogunwale0d465192020-01-23 19:14:44 -08001540 mChildren.get(i).forAllLeafTasks(callback, traverseTopToBottom);
Jeff Changdc9c1d42020-02-11 14:57:34 +08001541 }
1542 }
1543 }
1544
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001545 Task getTaskAbove(Task t) {
1546 return getTask(
1547 (above) -> true, t, false /*includeBoundary*/, false /*traverseTopToBottom*/);
1548 }
1549
1550 Task getTaskBelow(Task t) {
1551 return getTask((below) -> true, t, false /*includeBoundary*/, true /*traverseTopToBottom*/);
1552 }
1553
1554 Task getBottomMostTask() {
1555 return getTask((t) -> true, false /*traverseTopToBottom*/);
1556 }
1557
1558 Task getTopMostTask() {
1559 return getTask((t) -> true, true /*traverseTopToBottom*/);
1560 }
1561
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001562 Task getTask(Predicate<Task> callback) {
1563 return getTask(callback, true /*traverseTopToBottom*/);
1564 }
1565
1566 Task getTask(Predicate<Task> callback, boolean traverseTopToBottom) {
1567 if (traverseTopToBottom) {
1568 for (int i = mChildren.size() - 1; i >= 0; --i) {
1569 final Task t = mChildren.get(i).getTask(callback, traverseTopToBottom);
1570 if (t != null) {
1571 return t;
1572 }
1573 }
1574 } else {
1575 final int count = mChildren.size();
1576 for (int i = 0; i < count; i++) {
1577 final Task t = mChildren.get(i).getTask(callback, traverseTopToBottom);
1578 if (t != null) {
1579 return t;
1580 }
1581 }
1582 }
1583
1584 return null;
1585 }
1586
lumarkbc0032a2019-11-01 21:38:13 +08001587 /**
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001588 * Gets an task in a branch of the tree.
lumarkbc0032a2019-11-01 21:38:13 +08001589 *
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001590 * @param callback called to test if this is the task that should be returned.
1591 * @param boundary We don't return tasks via {@param callback} until we get to this node in
1592 * the tree.
1593 * @param includeBoundary If the boundary from be processed to return tasks.
1594 * @param traverseTopToBottom direction to traverse the tree.
1595 * @return The task if found or null.
lumarkbc0032a2019-11-01 21:38:13 +08001596 */
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001597 final Task getTask(Predicate<Task> callback, WindowContainer boundary, boolean includeBoundary,
1598 boolean traverseTopToBottom) {
1599 return getTask(callback, boundary, includeBoundary, traverseTopToBottom, new boolean[1]);
1600 }
1601
1602 private Task getTask(Predicate<Task> callback,
1603 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1604 boolean[] boundaryFound) {
1605 if (traverseTopToBottom) {
1606 for (int i = mChildren.size() - 1; i >= 0; --i) {
1607 final Task t = processGetTaskWithBoundary(callback, boundary,
1608 includeBoundary, traverseTopToBottom, boundaryFound, mChildren.get(i));
1609 if (t != null) {
1610 return t;
1611 }
1612 }
1613 } else {
1614 final int count = mChildren.size();
1615 for (int i = 0; i < count; i++) {
1616 final Task t = processGetTaskWithBoundary(callback, boundary,
1617 includeBoundary, traverseTopToBottom, boundaryFound, mChildren.get(i));
1618 if (t != null) {
1619 return t;
1620 }
lumarkbc0032a2019-11-01 21:38:13 +08001621 }
1622 }
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001623
1624 return null;
1625 }
1626
1627 private Task processGetTaskWithBoundary(Predicate<Task> callback,
1628 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1629 boolean[] boundaryFound, WindowContainer wc) {
1630 if (wc == boundary || boundary == null) {
1631 boundaryFound[0] = true;
1632 if (!includeBoundary) return null;
1633 }
1634
1635 if (boundaryFound[0]) {
1636 return wc.getTask(callback, traverseTopToBottom);
1637 }
1638
1639 return wc.getTask(
1640 callback, boundary, includeBoundary, traverseTopToBottom, boundaryFound);
lumarkbc0032a2019-11-01 21:38:13 +08001641 }
1642
Wale Ogunwaled1880962016-11-08 10:31:59 -08001643 WindowState getWindow(Predicate<WindowState> callback) {
1644 for (int i = mChildren.size() - 1; i >= 0; --i) {
1645 final WindowState w = mChildren.get(i).getWindow(callback);
1646 if (w != null) {
1647 return w;
1648 }
1649 }
1650
1651 return null;
1652 }
1653
Wale Ogunwaledec34082020-03-22 09:45:00 -07001654 void forAllDisplayAreas(Consumer<DisplayArea> callback) {
1655 for (int i = mChildren.size() - 1; i >= 0; --i) {
1656 mChildren.get(i).forAllDisplayAreas(callback);
1657 }
1658 }
1659
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001660 /**
Wale Ogunwalef6192862016-09-10 13:42:30 -07001661 * Returns 1, 0, or -1 depending on if this container is greater than, equal to, or lesser than
1662 * the input container in terms of z-order.
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001663 */
1664 @Override
1665 public int compareTo(WindowContainer other) {
1666 if (this == other) {
1667 return 0;
1668 }
1669
1670 if (mParent != null && mParent == other.mParent) {
Jorim Jaggi612bb882017-05-16 17:11:18 +02001671 final WindowList<WindowContainer> list = mParent.mChildren;
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001672 return list.indexOf(this) > list.indexOf(other) ? 1 : -1;
1673 }
1674
1675 final LinkedList<WindowContainer> thisParentChain = mTmpChain1;
1676 final LinkedList<WindowContainer> otherParentChain = mTmpChain2;
Jorim Jaggi4448e1e2017-05-16 22:26:02 +02001677 try {
1678 getParents(thisParentChain);
1679 other.getParents(otherParentChain);
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001680
Jorim Jaggi4448e1e2017-05-16 22:26:02 +02001681 // Find the common ancestor of both containers.
1682 WindowContainer commonAncestor = null;
1683 WindowContainer thisTop = thisParentChain.peekLast();
1684 WindowContainer otherTop = otherParentChain.peekLast();
1685 while (thisTop != null && otherTop != null && thisTop == otherTop) {
1686 commonAncestor = thisParentChain.removeLast();
1687 otherParentChain.removeLast();
1688 thisTop = thisParentChain.peekLast();
1689 otherTop = otherParentChain.peekLast();
1690 }
1691
1692 // Containers don't belong to the same hierarchy???
1693 if (commonAncestor == null) {
1694 throw new IllegalArgumentException("No in the same hierarchy this="
1695 + thisParentChain + " other=" + otherParentChain);
1696 }
1697
1698 // Children are always considered greater than their parents, so if one of the containers
1699 // we are comparing it the parent of the other then whichever is the child is greater.
1700 if (commonAncestor == this) {
1701 return -1;
1702 } else if (commonAncestor == other) {
1703 return 1;
1704 }
1705
1706 // The position of the first non-common ancestor in the common ancestor list determines
1707 // which is greater the which.
1708 final WindowList<WindowContainer> list = commonAncestor.mChildren;
1709 return list.indexOf(thisParentChain.peekLast()) > list.indexOf(otherParentChain.peekLast())
1710 ? 1 : -1;
1711 } finally {
1712 mTmpChain1.clear();
1713 mTmpChain2.clear();
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001714 }
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001715 }
1716
1717 private void getParents(LinkedList<WindowContainer> parents) {
1718 parents.clear();
1719 WindowContainer current = this;
1720 do {
1721 parents.addLast(current);
1722 current = current.mParent;
1723 } while (current != null);
1724 }
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001725
Robert Carrb1579c82017-09-05 14:54:47 -07001726 SurfaceControl.Builder makeSurface() {
1727 final WindowContainer p = getParent();
1728 return p.makeChildSurface(this);
1729 }
1730
Robert Carrf59b8dd2017-10-02 18:58:36 -07001731 /**
1732 * @param child The WindowContainer this child surface is for, or null if the Surface
1733 * is not assosciated with a WindowContainer (e.g. a surface used for Dimming).
1734 */
Robert Carrb1579c82017-09-05 14:54:47 -07001735 SurfaceControl.Builder makeChildSurface(WindowContainer child) {
1736 final WindowContainer p = getParent();
1737 // Give the parent a chance to set properties. In hierarchy v1 we rely
1738 // on this to set full-screen dimensions on all our Surface-less Layers.
Robert Carree4d4b92017-11-22 12:21:46 -08001739 return p.makeChildSurface(child)
1740 .setParent(mSurfaceControl);
Robert Carrb1579c82017-09-05 14:54:47 -07001741 }
Robert Carrdea7bf42019-04-04 12:02:51 -07001742 /*
1743 * @return The SurfaceControl parent for this containers SurfaceControl.
1744 * The SurfaceControl must be valid if non-null.
1745 */
Jorim Jaggia5e10572017-11-15 14:36:26 +01001746 @Override
1747 public SurfaceControl getParentSurfaceControl() {
1748 final WindowContainer parent = getParent();
1749 if (parent == null) {
1750 return null;
1751 }
1752 return parent.getSurfaceControl();
1753 }
1754
Robert Carrb1579c82017-09-05 14:54:47 -07001755 /**
1756 * @return Whether this WindowContainer should be magnified by the accessibility magnifier.
1757 */
1758 boolean shouldMagnify() {
Yuki Awano4c36b552018-04-24 17:27:50 +09001759 if (mSurfaceControl == null) {
1760 return false;
1761 }
1762
Robert Carrb1579c82017-09-05 14:54:47 -07001763 for (int i = 0; i < mChildren.size(); i++) {
1764 if (!mChildren.get(i).shouldMagnify()) {
1765 return false;
1766 }
1767 }
1768 return true;
1769 }
1770
1771 SurfaceSession getSession() {
1772 if (getParent() != null) {
1773 return getParent().getSession();
1774 }
1775 return null;
1776 }
1777
1778 void assignLayer(Transaction t, int layer) {
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001779 final boolean changed = layer != mLastLayer || mLastRelativeToLayer != null;
1780 if (mSurfaceControl != null && changed) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01001781 setLayer(t, layer);
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001782 mLastLayer = layer;
1783 mLastRelativeToLayer = null;
1784 }
1785 }
1786
1787 void assignRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
1788 final boolean changed = layer != mLastLayer || mLastRelativeToLayer != relativeTo;
1789 if (mSurfaceControl != null && changed) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01001790 setRelativeLayer(t, relativeTo, layer);
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001791 mLastLayer = layer;
1792 mLastRelativeToLayer = relativeTo;
Robert Carrb1579c82017-09-05 14:54:47 -07001793 }
1794 }
1795
Jorim Jaggi619c9f72017-12-19 18:04:29 +01001796 protected void setLayer(Transaction t, int layer) {
1797
1798 // Route through surface animator to accommodate that our surface control might be
1799 // attached to the leash, and leash is attached to parent container.
1800 mSurfaceAnimator.setLayer(t, layer);
1801 }
1802
1803 protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
1804
1805 // Route through surface animator to accommodate that our surface control might be
1806 // attached to the leash, and leash is attached to parent container.
1807 mSurfaceAnimator.setRelativeLayer(t, relativeTo, layer);
1808 }
1809
1810 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
1811 mSurfaceAnimator.reparent(t, newParent);
1812 }
1813
Robert Carrb1579c82017-09-05 14:54:47 -07001814 void assignChildLayers(Transaction t) {
1815 int layer = 0;
Robert Carrb1579c82017-09-05 14:54:47 -07001816
1817 // We use two passes as a way to promote children which
1818 // need Z-boosting to the end of the list.
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001819 for (int j = 0; j < mChildren.size(); ++j) {
1820 final WindowContainer wc = mChildren.get(j);
1821 wc.assignChildLayers(t);
1822 if (!wc.needsZBoost()) {
1823 wc.assignLayer(t, layer++);
Robert Carrb1579c82017-09-05 14:54:47 -07001824 }
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001825 }
1826 for (int j = 0; j < mChildren.size(); ++j) {
1827 final WindowContainer wc = mChildren.get(j);
1828 if (wc.needsZBoost()) {
1829 wc.assignLayer(t, layer++);
1830 }
Robert Carrb1579c82017-09-05 14:54:47 -07001831 }
1832 }
1833
1834 void assignChildLayers() {
Robert Carrf59b8dd2017-10-02 18:58:36 -07001835 assignChildLayers(getPendingTransaction());
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001836 scheduleAnimation();
Robert Carrb1579c82017-09-05 14:54:47 -07001837 }
1838
1839 boolean needsZBoost() {
1840 for (int i = 0; i < mChildren.size(); i++) {
1841 if (mChildren.get(i).needsZBoost()) {
1842 return true;
1843 }
1844 }
1845 return false;
1846 }
1847
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001848 /**
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001849 * Write to a protocol buffer output stream. Protocol buffer message definition is at
Yi Jin6c6e9ca2018-03-20 16:53:35 -07001850 * {@link com.android.server.wm.WindowContainerProto}.
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001851 *
Adrian Roos4921ccf2017-09-28 16:54:06 +02001852 * @param proto Stream to write the WindowContainer object to.
1853 * @param fieldId Field Id of the WindowContainer as defined in the parent message.
Nataniel Borges023ecb52019-01-16 14:15:43 -08001854 * @param logLevel Determines the amount of data to be written to the Protobuf.
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001855 * @hide
1856 */
1857 @CallSuper
1858 @Override
Jeffrey Huangcb782852019-12-05 11:28:11 -08001859 public void dumpDebug(ProtoOutputStream proto, long fieldId,
Nataniel Borges023ecb52019-01-16 14:15:43 -08001860 @WindowTraceLogLevel int logLevel) {
1861 boolean isVisible = isVisible();
1862 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible) {
1863 return;
1864 }
1865
Adrian Roos4921ccf2017-09-28 16:54:06 +02001866 final long token = proto.start(fieldId);
Jeffrey Huangcb782852019-12-05 11:28:11 -08001867 super.dumpDebug(proto, CONFIGURATION_CONTAINER, logLevel);
Adrian Roos4921ccf2017-09-28 16:54:06 +02001868 proto.write(ORIENTATION, mOrientation);
Nataniel Borges023ecb52019-01-16 14:15:43 -08001869 proto.write(VISIBLE, isVisible);
1870 if (mSurfaceAnimator.isAnimating()) {
Jeffrey Huangcb782852019-12-05 11:28:11 -08001871 mSurfaceAnimator.dumpDebug(proto, SURFACE_ANIMATOR);
Nataniel Borges023ecb52019-01-16 14:15:43 -08001872 }
Vishnu Nairdddc9f52020-03-09 09:37:27 -07001873
1874 // add children to proto
1875 for (int i = 0; i < getChildCount(); i++) {
1876 final long childToken = proto.start(WindowContainerProto.CHILDREN);
1877 final E child = getChildAt(i);
1878 child.dumpDebug(proto, child.getProtoFieldId(), logLevel);
1879 proto.end(childToken);
1880 }
Adrian Roos4921ccf2017-09-28 16:54:06 +02001881 proto.end(token);
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001882 }
1883
Vishnu Nairdddc9f52020-03-09 09:37:27 -07001884 /**
1885 * @return a proto field id to identify where to add the derived class to the generic window
1886 * container proto.
1887 */
1888 long getProtoFieldId() {
1889 return WINDOW_CONTAINER;
1890 }
1891
Wale Ogunwaleee41d4a2016-11-21 08:41:10 -08001892 private ForAllWindowsConsumerWrapper obtainConsumerWrapper(Consumer<WindowState> consumer) {
1893 ForAllWindowsConsumerWrapper wrapper = mConsumerWrapperPool.acquire();
1894 if (wrapper == null) {
1895 wrapper = new ForAllWindowsConsumerWrapper();
1896 }
1897 wrapper.setConsumer(consumer);
1898 return wrapper;
1899 }
1900
1901 private final class ForAllWindowsConsumerWrapper implements ToBooleanFunction<WindowState> {
1902
1903 private Consumer<WindowState> mConsumer;
1904
1905 void setConsumer(Consumer<WindowState> consumer) {
1906 mConsumer = consumer;
1907 }
1908
1909 @Override
1910 public boolean apply(WindowState w) {
1911 mConsumer.accept(w);
1912 return false;
1913 }
1914
1915 void release() {
1916 mConsumer = null;
1917 mConsumerWrapperPool.release(this);
1918 }
1919 }
Robert Carrb1579c82017-09-05 14:54:47 -07001920
1921 // TODO(b/68336570): Should this really be on WindowContainer since it
1922 // can only be used on the top-level nodes that aren't animated?
1923 // (otherwise we would be fighting other callers of setMatrix).
1924 void applyMagnificationSpec(Transaction t, MagnificationSpec spec) {
1925 if (shouldMagnify()) {
1926 t.setMatrix(mSurfaceControl, spec.scale, 0, 0, spec.scale)
1927 .setPosition(mSurfaceControl, spec.offsetX, spec.offsetY);
Robert Carr7603dea2019-07-17 13:16:21 -07001928 mLastMagnificationSpec = spec;
Robert Carrb1579c82017-09-05 14:54:47 -07001929 } else {
Jackal Guoa8b3a272019-12-16 15:24:58 +08001930 clearMagnificationSpec(t);
Robert Carrb1579c82017-09-05 14:54:47 -07001931 for (int i = 0; i < mChildren.size(); i++) {
1932 mChildren.get(i).applyMagnificationSpec(t, spec);
1933 }
1934 }
1935 }
1936
Robert Carr7603dea2019-07-17 13:16:21 -07001937 void clearMagnificationSpec(Transaction t) {
1938 if (mLastMagnificationSpec != null) {
1939 t.setMatrix(mSurfaceControl, 1, 0, 0, 1)
1940 .setPosition(mSurfaceControl, 0, 0);
1941 }
1942 mLastMagnificationSpec = null;
1943 for (int i = 0; i < mChildren.size(); i++) {
1944 mChildren.get(i).clearMagnificationSpec(t);
1945 }
1946 }
1947
Robert Carrb1579c82017-09-05 14:54:47 -07001948 void prepareSurfaces() {
chaviw7f1fa992018-01-10 13:52:12 -08001949 // If a leash has been set when the transaction was committed, then the leash reparent has
1950 // been committed.
1951 mCommittedReparentToAnimationLeash = mSurfaceAnimator.hasLeash();
Robert Carrb1579c82017-09-05 14:54:47 -07001952 for (int i = 0; i < mChildren.size(); i++) {
1953 mChildren.get(i).prepareSurfaces();
1954 }
1955 }
1956
1957 /**
chaviw7f1fa992018-01-10 13:52:12 -08001958 * @return true if the reparent to animation leash transaction has been committed, false
1959 * otherwise.
1960 */
1961 boolean hasCommittedReparentToAnimationLeash() {
1962 return mCommittedReparentToAnimationLeash;
1963 }
1964
1965 /**
Tiger Huanged6794e2019-05-07 20:07:59 +08001966 * Trigger a call to prepareSurfaces from the animation thread, such that pending transactions
1967 * will be applied.
Robert Carrb1579c82017-09-05 14:54:47 -07001968 */
1969 void scheduleAnimation() {
1970 if (mParent != null) {
1971 mParent.scheduleAnimation();
1972 }
1973 }
1974
Robert Carrdea7bf42019-04-04 12:02:51 -07001975 /**
1976 * @return The SurfaceControl for this container.
1977 * The SurfaceControl must be valid if non-null.
1978 */
Jorim Jaggia5e10572017-11-15 14:36:26 +01001979 @Override
1980 public SurfaceControl getSurfaceControl() {
Robert Carrb1579c82017-09-05 14:54:47 -07001981 return mSurfaceControl;
1982 }
1983
Jorim Jaggia5e10572017-11-15 14:36:26 +01001984 @Override
1985 public Transaction getPendingTransaction() {
Robert Carre10ee3d2019-11-11 15:03:15 -08001986 if (mUsingBLASTSyncTransaction) {
1987 return mBLASTSyncTransaction;
1988 }
1989
Tiger Huanged6794e2019-05-07 20:07:59 +08001990 final DisplayContent displayContent = getDisplayContent();
1991 if (displayContent != null && displayContent != this) {
1992 return displayContent.getPendingTransaction();
1993 }
1994 // This WindowContainer has not attached to a display yet or this is a DisplayContent, so we
1995 // let the caller to save the surface operations within the local mPendingTransaction.
1996 // If this is not a DisplayContent, we will merge it to the pending transaction of its
1997 // display once it attaches to it.
Robert Carrf59b8dd2017-10-02 18:58:36 -07001998 return mPendingTransaction;
1999 }
Jorim Jaggia5e10572017-11-15 14:36:26 +01002000
2001 /**
2002 * Starts an animation on the container.
2003 *
2004 * @param anim The animation to run.
2005 * @param hidden Whether our container is currently hidden. TODO This should use isVisible at
2006 * some point but the meaning is too weird to work for all containers.
Issei Suzuki8b995df2020-01-08 12:23:04 +01002007 * @param type The type of animation defined as {@link AnimationType}.
Issei Suzuki2f541842020-01-09 20:18:29 +01002008 * @param animationFinishedCallback The callback being triggered when the animation finishes.
Jorim Jaggia5e10572017-11-15 14:36:26 +01002009 */
Issei Suzuki2f541842020-01-09 20:18:29 +01002010 void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden,
Issei Suzuki8b995df2020-01-08 12:23:04 +01002011 @AnimationType int type,
2012 @Nullable OnAnimationFinishedCallback animationFinishedCallback) {
2013 if (DEBUG_ANIM) {
2014 Slog.v(TAG, "Starting animation on " + this + ": type=" + type + ", anim=" + anim);
2015 }
Jorim Jaggia5e10572017-11-15 14:36:26 +01002016
2017 // TODO: This should use isVisible() but because isVisible has a really weird meaning at
2018 // the moment this doesn't work for all animatable window containers.
Evan Rosky55bddd82020-01-29 13:07:18 -08002019 mSurfaceAnimator.startAnimation(t, anim, hidden, type, animationFinishedCallback,
2020 mSurfaceFreezer);
Issei Suzuki2f541842020-01-09 20:18:29 +01002021 }
2022
Issei Suzuki8b995df2020-01-08 12:23:04 +01002023 void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden,
2024 @AnimationType int type) {
2025 startAnimation(t, anim, hidden, type, null /* animationFinishedCallback */);
Jorim Jaggia5e10572017-11-15 14:36:26 +01002026 }
2027
Jorim Jaggi980c9de2017-11-17 01:41:37 +01002028 void transferAnimation(WindowContainer from) {
2029 mSurfaceAnimator.transferAnimation(from.mSurfaceAnimator);
2030 }
2031
Jorim Jaggia5e10572017-11-15 14:36:26 +01002032 void cancelAnimation() {
2033 mSurfaceAnimator.cancelAnimation();
2034 }
2035
2036 @Override
Evan Rosky55bddd82020-01-29 13:07:18 -08002037 public SurfaceControl getFreezeSnapshotTarget() {
2038 return null;
2039 }
2040
2041 @Override
Jorim Jaggia5e10572017-11-15 14:36:26 +01002042 public Builder makeAnimationLeash() {
Vishnu Nairfd6fb672020-02-14 12:56:37 -08002043 return makeSurface().setContainerLayer();
Jorim Jaggia5e10572017-11-15 14:36:26 +01002044 }
2045
Jorim Jaggi596a1992017-12-29 14:48:02 +01002046 @Override
2047 public SurfaceControl getAnimationLeashParent() {
2048 return getParentSurfaceControl();
2049 }
2050
chaviw23ee71c2017-12-18 11:29:41 -08002051 /**
2052 * @return The layer on which all app animations are happening.
2053 */
Jorim Jaggi391790622018-04-18 15:30:44 +02002054 SurfaceControl getAppAnimationLayer(@AnimationLayer int animationLayer) {
chaviw23ee71c2017-12-18 11:29:41 -08002055 final WindowContainer parent = getParent();
2056 if (parent != null) {
Jorim Jaggi391790622018-04-18 15:30:44 +02002057 return parent.getAppAnimationLayer(animationLayer);
chaviw23ee71c2017-12-18 11:29:41 -08002058 }
2059 return null;
2060 }
2061
lumark19a5d2e2019-10-11 16:19:30 +08002062 // TODO: Remove this and use #getBounds() instead once we set an app transition animation
2063 // on TaskStack.
2064 Rect getAnimationBounds(int appStackClipMode) {
lumark85718662019-12-26 22:05:12 +08002065 return getDisplayedBounds();
lumark19a5d2e2019-10-11 16:19:30 +08002066 }
2067
2068 /**
2069 * Applies the app transition animation according the given the layout properties in the
2070 * window hierarchy.
2071 *
2072 * @param lp The layout parameters of the window.
2073 * @param transit The app transition type indicates what kind of transition to be applied.
2074 * @param enter Whether the app transition is entering transition or not.
2075 * @param isVoiceInteraction Whether the container is participating in voice interaction or not.
2076 *
2077 * @return {@code true} when the container applied the app transition, {@code false} if the
2078 * app transition is disabled or skipped.
2079 *
2080 * @see #getAnimationAdapter
2081 */
2082 boolean applyAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
lumark04bceb92020-03-07 00:03:33 +08002083 boolean isVoiceInteraction, @Nullable OnAnimationFinishedCallback finishedCallback) {
lumark19a5d2e2019-10-11 16:19:30 +08002084 if (mWmService.mDisableTransitionAnimation) {
2085 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
2086 "applyAnimation: transition animation is disabled or skipped. "
2087 + "container=%s", this);
2088 cancelAnimation();
2089 return false;
2090 }
2091
2092 // Only apply an animation if the display isn't frozen. If it is frozen, there is no reason
2093 // to animate and it can cause strange artifacts when we unfreeze the display if some
2094 // different animation is running.
2095 try {
2096 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "WC#applyAnimation");
2097 if (okToAnimate()) {
lumark04bceb92020-03-07 00:03:33 +08002098 applyAnimationUnchecked(lp, enter, transit, isVoiceInteraction, finishedCallback);
lumark19a5d2e2019-10-11 16:19:30 +08002099 } else {
2100 cancelAnimation();
2101 }
2102 } finally {
2103 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2104 }
2105
2106 return isAnimating();
2107 }
2108
2109 /**
2110 * Gets the {@link AnimationAdapter} according the given window layout properties in the window
2111 * hierarchy.
2112 *
2113 * @return The return value will always contain two elements, one for normal animations and the
2114 * other for thumbnail animation, both can be {@code null}.
2115 *
2116 * @See com.android.server.wm.RemoteAnimationController.RemoteAnimationRecord
2117 * @See LocalAnimationAdapter
2118 */
2119 Pair<AnimationAdapter, AnimationAdapter> getAnimationAdapter(WindowManager.LayoutParams lp,
2120 int transit, boolean enter, boolean isVoiceInteraction) {
2121 final Pair<AnimationAdapter, AnimationAdapter> resultAdapters;
2122 final int appStackClipMode = getDisplayContent().mAppTransition.getAppStackClipMode();
2123
2124 // Separate position and size for use in animators.
2125 mTmpRect.set(getAnimationBounds(appStackClipMode));
lumark85718662019-12-26 22:05:12 +08002126 if (sHierarchicalAnimations) {
2127 getRelativeDisplayedPosition(mTmpPoint);
2128 } else {
2129 mTmpPoint.set(mTmpRect.left, mTmpRect.top);
2130 }
lumark19a5d2e2019-10-11 16:19:30 +08002131 mTmpRect.offsetTo(0, 0);
2132
2133 final RemoteAnimationController controller =
2134 getDisplayContent().mAppTransition.getRemoteAnimationController();
2135 final boolean isChanging = AppTransition.isChangeTransit(transit) && enter
2136 && isChangingAppTransition();
2137
2138 // Delaying animation start isn't compatible with remote animations at all.
2139 if (controller != null && !mSurfaceAnimator.isAnimationStartDelayed()) {
lumark2ec19122020-01-23 00:09:04 +08002140 final Rect localBounds = new Rect(mTmpRect);
2141 localBounds.offsetTo(mTmpPoint.x, mTmpPoint.y);
lumark19a5d2e2019-10-11 16:19:30 +08002142 final RemoteAnimationController.RemoteAnimationRecord adapters =
lumark2ec19122020-01-23 00:09:04 +08002143 controller.createRemoteAnimationRecord(this, mTmpPoint, localBounds,
2144 mTmpRect, (isChanging ? mSurfaceFreezer.mFreezeBounds : null));
lumark19a5d2e2019-10-11 16:19:30 +08002145 resultAdapters = new Pair<>(adapters.mAdapter, adapters.mThumbnailAdapter);
2146 } else if (isChanging) {
2147 final float durationScale = mWmService.getTransitionAnimationScaleLocked();
2148 final DisplayInfo displayInfo = getDisplayContent().getDisplayInfo();
2149 mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y);
2150
lumarkbc0032a2019-11-01 21:38:13 +08002151 final AnimationAdapter adapter = new LocalAnimationAdapter(
Evan Rosky55bddd82020-01-29 13:07:18 -08002152 new WindowChangeAnimationSpec(mSurfaceFreezer.mFreezeBounds, mTmpRect,
2153 displayInfo, durationScale, true /* isAppAnimation */,
2154 false /* isThumbnail */),
lumark19a5d2e2019-10-11 16:19:30 +08002155 getSurfaceAnimationRunner());
2156
Evan Rosky55bddd82020-01-29 13:07:18 -08002157 final AnimationAdapter thumbnailAdapter = mSurfaceFreezer.mSnapshot != null
2158 ? new LocalAnimationAdapter(new WindowChangeAnimationSpec(
2159 mSurfaceFreezer.mFreezeBounds, mTmpRect, displayInfo, durationScale,
2160 true /* isAppAnimation */, true /* isThumbnail */), getSurfaceAnimationRunner())
lumarkbc0032a2019-11-01 21:38:13 +08002161 : null;
lumark19a5d2e2019-10-11 16:19:30 +08002162 resultAdapters = new Pair<>(adapter, thumbnailAdapter);
2163 mTransit = transit;
2164 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
2165 } else {
2166 mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM);
2167 final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
2168
2169 if (a != null) {
2170 // Only apply corner radius to animation if we're not in multi window mode.
2171 // We don't want rounded corners when in pip or split screen.
2172 final float windowCornerRadius = !inMultiWindowMode()
2173 ? getDisplayContent().getWindowCornerRadius()
2174 : 0;
2175 AnimationAdapter adapter = new LocalAnimationAdapter(
2176 new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
2177 getDisplayContent().mAppTransition.canSkipFirstFrame(),
2178 appStackClipMode, true /* isAppAnimation */, windowCornerRadius),
2179 getSurfaceAnimationRunner());
2180
2181 resultAdapters = new Pair<>(adapter, null);
2182 mNeedsZBoost = a.getZAdjustment() == Animation.ZORDER_TOP;
2183 mTransit = transit;
2184 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
2185 } else {
2186 resultAdapters = new Pair<>(null, null);
2187 }
2188 }
2189 return resultAdapters;
2190 }
2191
lumark04bceb92020-03-07 00:03:33 +08002192 protected void applyAnimationUnchecked(WindowManager.LayoutParams lp, boolean enter,
2193 int transit, boolean isVoiceInteraction,
2194 @Nullable OnAnimationFinishedCallback finishedCallback) {
2195 final Pair<AnimationAdapter, AnimationAdapter> adapters = getAnimationAdapter(lp,
2196 transit, enter, isVoiceInteraction);
2197 AnimationAdapter adapter = adapters.first;
2198 AnimationAdapter thumbnailAdapter = adapters.second;
2199 if (adapter != null) {
2200 startAnimation(getPendingTransaction(), adapter, !isVisible(),
2201 ANIMATION_TYPE_APP_TRANSITION, finishedCallback);
2202 if (adapter.getShowWallpaper()) {
2203 getDisplayContent().pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2204 }
2205 if (thumbnailAdapter != null) {
2206 mSurfaceFreezer.mSnapshot.startAnimation(getPendingTransaction(),
2207 thumbnailAdapter, ANIMATION_TYPE_APP_TRANSITION, (type, anim) -> { });
2208 }
2209 }
2210 }
2211
lumark19a5d2e2019-10-11 16:19:30 +08002212 final SurfaceAnimationRunner getSurfaceAnimationRunner() {
2213 return mWmService.mSurfaceAnimationRunner;
2214 }
2215
2216 private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
2217 boolean isVoiceInteraction) {
Winson Chung1b5d0552020-04-06 19:28:49 -07002218 if (isOrganized()) {
2219 // Defer to the task organizer to run animations
2220 return null;
2221 }
2222
lumark19a5d2e2019-10-11 16:19:30 +08002223 final DisplayContent displayContent = getDisplayContent();
2224 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2225 final int width = displayInfo.appWidth;
2226 final int height = displayInfo.appHeight;
2227 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM, "applyAnimation: container=%s", this);
2228
2229 // Determine the visible rect to calculate the thumbnail clip with
2230 // getAnimationFrames.
2231 final Rect frame = new Rect(0, 0, width, height);
2232 final Rect displayFrame = new Rect(0, 0,
2233 displayInfo.logicalWidth, displayInfo.logicalHeight);
2234 final Rect insets = new Rect();
2235 final Rect stableInsets = new Rect();
2236 final Rect surfaceInsets = new Rect();
2237 getAnimationFrames(frame, insets, stableInsets, surfaceInsets);
2238
2239 if (mLaunchTaskBehind) {
2240 // Differentiate the two animations. This one which is briefly on the screen
2241 // gets the !enter animation, and the other one which remains on the
2242 // screen gets the enter animation. Both appear in the mOpeningApps set.
2243 enter = false;
2244 }
2245 ProtoLog.d(WM_DEBUG_APP_TRANSITIONS,
2246 "Loading animation for app transition. transit=%s enter=%b frame=%s insets=%s "
2247 + "surfaceInsets=%s",
2248 AppTransition.appTransitionToString(transit), enter, frame, insets, surfaceInsets);
2249 final Configuration displayConfig = displayContent.getConfiguration();
2250 final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,
2251 displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
2252 surfaceInsets, stableInsets, isVoiceInteraction, inFreeformWindowingMode(), this);
2253 if (a != null) {
lumark8669ef32020-02-10 18:41:57 +08002254 if (a != null) {
2255 // Setup the maximum app transition duration to prevent malicious app may set a long
2256 // animation duration or infinite repeat counts for the app transition through
2257 // ActivityOption#makeCustomAnimation or WindowManager#overridePendingTransition.
2258 a.restrictDuration(MAX_APP_TRANSITION_DURATION);
2259 }
2260 if (DEBUG_ANIM) {
2261 logWithStack(TAG, "Loaded animation " + a + " for " + this
2262 + ", duration: " + ((a != null) ? a.getDuration() : 0));
2263 }
lumark19a5d2e2019-10-11 16:19:30 +08002264 final int containingWidth = frame.width();
2265 final int containingHeight = frame.height();
2266 a.initialize(containingWidth, containingHeight, width, height);
2267 a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked());
2268 }
2269 return a;
2270 }
2271
2272 RemoteAnimationTarget createRemoteAnimationTarget(
2273 RemoteAnimationController.RemoteAnimationRecord record) {
2274 return null;
2275 }
2276
Daichi Hirono8ecfc6b2020-02-18 16:28:03 +09002277 boolean canCreateRemoteAnimationTarget() {
2278 return false;
2279 }
2280
lumark19a5d2e2019-10-11 16:19:30 +08002281 boolean okToDisplay() {
lumark5341d1c2019-12-14 01:54:02 +08002282 final DisplayContent dc = getDisplayContent();
2283 return dc != null && dc.okToDisplay();
lumark19a5d2e2019-10-11 16:19:30 +08002284 }
2285
2286 boolean okToAnimate() {
lumark3b8bbc82019-12-02 16:22:08 +08002287 return okToAnimate(false /* ignoreFrozen */);
2288 }
2289
2290 boolean okToAnimate(boolean ignoreFrozen) {
lumark5341d1c2019-12-14 01:54:02 +08002291 final DisplayContent dc = getDisplayContent();
2292 return dc != null && dc.okToAnimate(ignoreFrozen);
lumark19a5d2e2019-10-11 16:19:30 +08002293 }
2294
Jorim Jaggia5e10572017-11-15 14:36:26 +01002295 @Override
2296 public void commitPendingTransaction() {
2297 scheduleAnimation();
2298 }
2299
Robert Carr2f8aa392018-01-31 14:46:51 -08002300 void reassignLayer(Transaction t) {
Jorim Jaggia5e10572017-11-15 14:36:26 +01002301 final WindowContainer parent = getParent();
2302 if (parent != null) {
2303 parent.assignChildLayers(t);
2304 }
2305 }
2306
Riddle Hsu3d0aa4f2020-04-09 17:58:50 +08002307 void resetSurfacePositionForAnimationLeash(Transaction t) {
2308 t.setPosition(mSurfaceControl, 0, 0);
2309 mLastSurfacePosition.set(0, 0);
2310 }
2311
Jorim Jaggia5e10572017-11-15 14:36:26 +01002312 @Override
2313 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
Robert Carrf12f9d32018-03-01 15:24:36 -08002314 mLastLayer = -1;
Jorim Jaggia5e10572017-11-15 14:36:26 +01002315 reassignLayer(t);
Evan Rosky0ad8d2c2020-03-16 12:09:58 -07002316
2317 // Leash is now responsible for position, so set our position to 0.
Riddle Hsu3d0aa4f2020-04-09 17:58:50 +08002318 resetSurfacePositionForAnimationLeash(t);
Jorim Jaggia5e10572017-11-15 14:36:26 +01002319 }
2320
2321 @Override
lumarkf6f34942019-04-29 16:56:50 +08002322 public void onAnimationLeashLost(Transaction t) {
Robert Carrf12f9d32018-03-01 15:24:36 -08002323 mLastLayer = -1;
Evan Rosky55bddd82020-01-29 13:07:18 -08002324 mSurfaceFreezer.unfreeze(t);
Jorim Jaggia5e10572017-11-15 14:36:26 +01002325 reassignLayer(t);
Evan Rosky0ad8d2c2020-03-16 12:09:58 -07002326 updateSurfacePosition(t);
Jorim Jaggia5e10572017-11-15 14:36:26 +01002327 }
2328
2329 /**
2330 * Called when an animation has finished running.
2331 */
Issei Suzuki8b995df2020-01-08 12:23:04 +01002332 protected void onAnimationFinished(@AnimationType int type, AnimationAdapter anim) {
chaviwccd5d502019-02-22 13:30:31 -08002333 mWmService.onAnimationFinished();
Jorim Jaggia5e10572017-11-15 14:36:26 +01002334 }
2335
2336 /**
2337 * @return The currently running animation, if any, or {@code null} otherwise.
2338 */
2339 AnimationAdapter getAnimation() {
2340 return mSurfaceAnimator.getAnimation();
2341 }
2342
2343 /**
lumark5bd11af2019-12-21 01:52:28 +08002344 * @return The {@link WindowContainer} which is running an animation.
2345 *
2346 * It traverses from the current container to its parents recursively. If nothing is animating,
2347 * it will return {@code null}.
2348 */
2349 @Nullable
2350 WindowContainer getAnimatingContainer() {
2351 if (isAnimating()) {
2352 return this;
2353 }
2354 final WindowContainer parent = getParent();
2355 return (parent != null) ? parent.getAnimatingContainer() : null;
2356 }
2357
2358 /**
Jorim Jaggia5e10572017-11-15 14:36:26 +01002359 * @see SurfaceAnimator#startDelayingAnimationStart
2360 */
2361 void startDelayingAnimationStart() {
2362 mSurfaceAnimator.startDelayingAnimationStart();
2363 }
2364
2365 /**
2366 * @see SurfaceAnimator#endDelayingAnimationStart
2367 */
2368 void endDelayingAnimationStart() {
2369 mSurfaceAnimator.endDelayingAnimationStart();
2370 }
2371
2372 @Override
2373 public int getSurfaceWidth() {
2374 return mSurfaceControl.getWidth();
2375 }
2376
2377 @Override
2378 public int getSurfaceHeight() {
2379 return mSurfaceControl.getHeight();
2380 }
2381
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002382 @CallSuper
Jorim Jaggia5e10572017-11-15 14:36:26 +01002383 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
2384 if (mSurfaceAnimator.isAnimating()) {
2385 pw.print(prefix); pw.println("ContainerAnimator:");
2386 mSurfaceAnimator.dump(pw, prefix + " ");
2387 }
2388 }
chaviwe07246a2017-12-12 16:18:29 -08002389
Evan Rosky0ad8d2c2020-03-16 12:09:58 -07002390 final void updateSurfacePosition() {
2391 updateSurfacePosition(getPendingTransaction());
2392 }
2393
2394 void updateSurfacePosition(Transaction t) {
Wale Ogunwaledec34082020-03-22 09:45:00 -07002395 // Avoid fighting with the organizer over Surface position.
2396 if (isOrganized()) return;
2397
Evan Rosky0ad8d2c2020-03-16 12:09:58 -07002398 if (mSurfaceControl == null || mSurfaceAnimator.hasLeash()) {
chaviwe07246a2017-12-12 16:18:29 -08002399 return;
2400 }
2401
Evan Roskyed6767f2018-10-26 17:21:06 -07002402 getRelativeDisplayedPosition(mTmpPos);
chaviw3e751af2018-01-11 11:22:39 -08002403 if (mTmpPos.equals(mLastSurfacePosition)) {
2404 return;
2405 }
2406
Evan Rosky0ad8d2c2020-03-16 12:09:58 -07002407 t.setPosition(mSurfaceControl, mTmpPos.x, mTmpPos.y);
chaviw3e751af2018-01-11 11:22:39 -08002408 mLastSurfacePosition.set(mTmpPos.x, mTmpPos.y);
chaviwe07246a2017-12-12 16:18:29 -08002409 }
2410
Evan Rosky65dffa62019-02-04 14:09:53 -08002411 @VisibleForTesting
Evan Rosky89f5c1d2019-01-29 10:04:05 -08002412 Point getLastSurfacePosition() {
2413 return mLastSurfacePosition;
2414 }
2415
Evan Roskyed6767f2018-10-26 17:21:06 -07002416 /**
2417 * Displayed bounds specify where to display this container at. It differs from bounds during
2418 * certain operations (like animation or interactive dragging).
2419 *
2420 * @return the bounds to display this container at.
2421 */
2422 Rect getDisplayedBounds() {
2423 return getBounds();
2424 }
2425
lumark19a5d2e2019-10-11 16:19:30 +08002426 /**
2427 * The {@code outFrame} retrieved by this method specifies where the animation will finish
2428 * the entrance animation, as the next frame will display the window at these coordinates. In
2429 * case of exit animation, this is where the animation will start, as the frame before the
2430 * animation is displaying the window at these bounds.
2431 *
2432 * @param outFrame The bounds where entrance animation finishes or exit animation starts.
2433 * @param outInsets Insets that are covered by system windows.
2434 * @param outStableInsets Insets that determine the area covered by the stable system windows.
2435 * @param outSurfaceInsets Positive insets between the drawing surface and window content.
2436 */
2437 void getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets,
2438 Rect outSurfaceInsets) {
2439 final DisplayInfo displayInfo = getDisplayContent().getDisplayInfo();
2440 outFrame.set(0, 0, displayInfo.appWidth, displayInfo.appHeight);
2441 outInsets.setEmpty();
2442 outStableInsets.setEmpty();
2443 outSurfaceInsets.setEmpty();
2444 }
2445
Evan Roskyed6767f2018-10-26 17:21:06 -07002446 void getRelativeDisplayedPosition(Point outPos) {
Wale Ogunwaledec34082020-03-22 09:45:00 -07002447 // In addition to updateSurfacePosition, we keep other code that sets
2448 // position from fighting with the organizer
2449 if (isOrganized()) {
2450 outPos.set(0, 0);
2451 return;
2452 }
2453
Evan Roskyed6767f2018-10-26 17:21:06 -07002454 final Rect dispBounds = getDisplayedBounds();
2455 outPos.set(dispBounds.left, dispBounds.top);
chaviwe07246a2017-12-12 16:18:29 -08002456 final WindowContainer parent = getParent();
2457 if (parent != null) {
Evan Roskyed6767f2018-10-26 17:21:06 -07002458 final Rect parentBounds = parent.getDisplayedBounds();
chaviwe07246a2017-12-12 16:18:29 -08002459 outPos.offset(-parentBounds.left, -parentBounds.top);
2460 }
2461 }
chaviw2fb06bc2018-01-19 17:09:15 -08002462
Yunfan Chen87b5a242019-10-01 17:53:59 +09002463 void waitForAllWindowsDrawn() {
Yunfan Chen87b5a242019-10-01 17:53:59 +09002464 forAllWindows(w -> {
Riddle Hsu5df3b752019-12-16 13:27:37 -06002465 w.requestDrawIfNeeded(mWaitingForDrawn);
Yunfan Chen87b5a242019-10-01 17:53:59 +09002466 }, true /* traverseTopToBottom */);
2467 }
2468
chaviw2fb06bc2018-01-19 17:09:15 -08002469 Dimmer getDimmer() {
2470 if (mParent == null) {
2471 return null;
2472 }
2473 return mParent.getDimmer();
2474 }
Robert Carr8a2f9132019-11-11 15:03:15 -08002475
2476 void setSurfaceControl(SurfaceControl sc) {
2477 mSurfaceControl = sc;
2478 }
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002479
Evan Rosky55bddd82020-01-29 13:07:18 -08002480 RemoteAnimationDefinition getRemoteAnimationDefinition() {
2481 return null;
2482 }
2483
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002484 /** Cheap way of doing cast and instanceof. */
2485 Task asTask() {
2486 return null;
2487 }
2488
2489 /** Cheap way of doing cast and instanceof. */
2490 ActivityRecord asActivityRecord() {
2491 return null;
2492 }
Evan Roskya80f11c2020-01-23 19:17:10 -08002493
Wale Ogunwaledec34082020-03-22 09:45:00 -07002494 /**
2495 * @return {@code true} if window container is manage by a
2496 * {@link android.window.WindowOrganizer}
2497 */
2498 boolean isOrganized() {
2499 return false;
Evan Roskya80f11c2020-01-23 19:17:10 -08002500 }
2501
Evan Roskya8fde152020-01-07 19:09:13 -08002502 static WindowContainer fromBinder(IBinder binder) {
2503 return RemoteToken.fromBinder(binder).getContainer();
2504 }
2505
Wale Ogunwaleadf116e2020-03-27 16:36:01 -07002506 static class RemoteToken extends IWindowContainerToken.Stub {
2507
Evan Roskya80f11c2020-01-23 19:17:10 -08002508 final WeakReference<WindowContainer> mWeakRef;
Wale Ogunwaleadf116e2020-03-27 16:36:01 -07002509 private WindowContainerToken mWindowContainerToken;
Evan Roskya80f11c2020-01-23 19:17:10 -08002510
2511 RemoteToken(WindowContainer container) {
2512 mWeakRef = new WeakReference<>(container);
2513 }
2514
2515 WindowContainer getContainer() {
2516 return mWeakRef.get();
2517 }
2518
2519 static RemoteToken fromBinder(IBinder binder) {
2520 return (RemoteToken) binder;
2521 }
2522
2523 @Override
2524 public SurfaceControl getLeash() {
Wale Ogunwaledec34082020-03-22 09:45:00 -07002525 final WindowContainer wc = getContainer();
2526 if (wc == null) return null;
2527 // We need to copy the SurfaceControl instead of returning the original
2528 // because the Parcel FLAGS PARCELABLE_WRITE_RETURN_VALUE cause SurfaceControls
2529 // to release themselves.
Jorim Jaggiee540702020-04-02 21:40:52 +02002530 return new SurfaceControl(wc.getSurfaceControl());
Evan Roskya80f11c2020-01-23 19:17:10 -08002531 }
2532
Wale Ogunwaleadf116e2020-03-27 16:36:01 -07002533 WindowContainerToken toWindowContainerToken() {
2534 if (mWindowContainerToken == null) {
2535 mWindowContainerToken = new WindowContainerToken(this);
2536 }
2537 return mWindowContainerToken;
2538 }
2539
Evan Roskya80f11c2020-01-23 19:17:10 -08002540 @Override
2541 public String toString() {
2542 StringBuilder sb = new StringBuilder(128);
2543 sb.append("RemoteToken{");
2544 sb.append(Integer.toHexString(System.identityHashCode(this)));
2545 sb.append(' ');
2546 sb.append(mWeakRef.get());
2547 sb.append('}');
2548 return sb.toString();
2549 }
2550 }
Robert Carre10ee3d2019-11-11 15:03:15 -08002551
2552 @Override
Wale Ogunwaleadf116e2020-03-27 16:36:01 -07002553 public void onTransactionReady(int mSyncId, SurfaceControl.Transaction mergedTransaction) {
Robert Carre10ee3d2019-11-11 15:03:15 -08002554 mergedTransaction.merge(mBLASTSyncTransaction);
2555 mUsingBLASTSyncTransaction = false;
2556
Wale Ogunwaleadf116e2020-03-27 16:36:01 -07002557 mWaitingListener.onTransactionReady(mWaitingSyncId, mergedTransaction);
Robert Carre10ee3d2019-11-11 15:03:15 -08002558
2559 mWaitingListener = null;
2560 mWaitingSyncId = -1;
2561 }
2562
Rob Carr25376512020-03-09 15:23:19 -07002563 /**
2564 * Returns true if any of the children elected to participate in the Sync
2565 */
2566 boolean addChildrenToSyncSet(int localId) {
2567 boolean willSync = false;
2568
2569 for (int i = 0; i < mChildren.size(); i++) {
2570 final WindowContainer child = mChildren.get(i);
2571 willSync |= mBLASTSyncEngine.addToSyncSet(localId, child);
2572 }
2573 return willSync;
2574 }
2575
Robert Carre10ee3d2019-11-11 15:03:15 -08002576 boolean prepareForSync(BLASTSyncEngine.TransactionReadyListener waitingListener,
2577 int waitingId) {
Robert Carr8ccc4fc2020-03-13 10:48:49 -07002578 boolean willSync = true;
2579
2580 // If we are invisible, no need to sync, likewise if we are already engaged in a sync,
2581 // we can't support overlapping syncs on a single container yet.
2582 if (!isVisible() || mWaitingListener != null) {
2583 return false;
Robert Carre10ee3d2019-11-11 15:03:15 -08002584 }
2585 mUsingBLASTSyncTransaction = true;
2586
Robert Carre10ee3d2019-11-11 15:03:15 -08002587 // Make sure to set these before we call setReady in case the sync was a no-op
2588 mWaitingSyncId = waitingId;
2589 mWaitingListener = waitingListener;
2590
Rob Carr25376512020-03-09 15:23:19 -07002591 int localId = mBLASTSyncEngine.startSyncSet(this);
2592 willSync |= addChildrenToSyncSet(localId);
Robert Carre10ee3d2019-11-11 15:03:15 -08002593 mBLASTSyncEngine.setReady(localId);
2594
2595 return willSync;
2596 }
Robert Carr6cc720b2020-04-06 13:45:31 -07002597
2598 boolean useBLASTSync() {
2599 return mUsingBLASTSyncTransaction;
2600 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -07002601}